【问题标题】:Link error with LLVM StackMaps from asm/C来自 asm/C 的 LLVM StackMaps 链接错误
【发布时间】:2016-07-01 15:41:38
【问题描述】:

我目前正在尝试使用LLVM's stackmap feature 编写一个基本的 C 堆栈遍历器。我已经生成了堆栈图,现在我正在尝试将堆栈图传递给 C 函数,以便我可以使用它。

尤其是我无法将__LLVM_StackMaps 传递给我的堆栈步行者。我尝试将它作为汇编函数的参数传递:

     .text
     .globl stackHelper
     .extern stackWalker
     .extern __LLVM_StackMaps
stackHelper:
    mov %rsp, %rdi
    mov __LLVM_StackMaps, %rsi
    jmp stackWalker

我得到了错误 (.text+0x7): undefined reference to ``__LLVM_StackMaps'.

objdump 说 __LLVM_StackMaps 不在 .text 或 .data 中,而是在自定义的 .llvm_stackmaps 部分中。这是 objdump 的输出:

factorial.o:     file format elf64-x86-64
factorial.o
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000067  0000000000000000  0000000000000000  00000040  2**4
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .rodata.str1.1 00000005  0000000000000000  0000000000000000  000000a7  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.GNU-stack 00000000  0000000000000000  0000000000000000  000000ac  2**0
                  CONTENTS, READONLY
  3 .llvm_stackmaps 00000050  0000000000000000  0000000000000000  000000b0  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  4 .eh_frame     00000050  0000000000000000  0000000000000000  00000100  2**3
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 factorial.ll
0000000000000000 l       .llvm_stackmaps    0000000000000000 __LLVM_StackMaps
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .rodata.str1.1 0000000000000000 .rodata.str1.1
0000000000000030 g     F .text  0000000000000037 fact
0000000000000000 g     F .text  0000000000000023 main
0000000000000000         *UND*  0000000000000000 printf
0000000000000000         *UND*  0000000000000000 stackHelper


RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
0000000000000011 R_X86_64_32       .rodata.str1.1
000000000000001b R_X86_64_PC32     printf-0x0000000000000004
000000000000004e R_X86_64_PC32     stackHelper-0x0000000000000004


RELOCATION RECORDS FOR [.llvm_stackmaps]:
OFFSET           TYPE              VALUE
0000000000000010 R_X86_64_64       fact


RELOCATION RECORDS FOR [.eh_frame]:
OFFSET           TYPE              VALUE
0000000000000020 R_X86_64_PC32     .text
0000000000000034 R_X86_64_PC32     .text+0x0000000000000030

我的猜测是它无法访问此表中的符号。有没有办法从我的汇编函数中访问这些数据,或者我需要在链接阶段做些什么来让它正确地访问它?

【问题讨论】:

  • 通常要访问外部,您需要链接到它,方法是加入库代码或访问共享库。另外,您确定变量名开头的下划线数量正确吗?这通常会让人绊倒。
  • 下划线的正确数量是多少?当我尝试将脚本链接在一起时,我收到未定义引用的错误。有没有办法访问汇编中不同部分的数据?
  • 该部分无关紧要,只要它是可见符号即可。更好的问题,到底是什么.mov
  • @PeterCordes 我已经用 __LLVM_StackMap 添加了文件的 objdump。
  • 我已经告诉过你,问题不在于该部分。该符号根本没有导出。请参阅 objdump 输出中的 l 含义 local

标签: assembly llvm x86-64 visibility objdump


【解决方案1】:

@Jester 指出的问题是该符号被标记为本地,因此仅对它出现的文件可见。

0000000000000000 l       .llvm_stackmaps    0000000000000000 __LLVM_StackMaps

第一列地址后面的l 表示符号是LOCALg 表示它是 GLOBAL 并且对外部对象可见。

如果不能通过源代码将阶乘中的符号改成非静态的,那么可以直接使用OBJCOPY来改变符号在目标文件中的可见性:

objcopy  --globalize-symbol=__LLVM_StackMaps factorial.o factorial.o

第一个目标文件factorial.o 是要处理的输入文件,第二个factorial.o 是输出文件。如果您愿意,可以指定不同的输出对象。我的示例用更改覆盖了原来的 factorial.o。生成的 factorial.o 现在应该有一个类似于以下内容的条目:

0000000000000000 g       .llvm_stackmaps    0000000000000000 __LLVM_StackMaps

选项--globalize-symbolOBJCOPY documentation中描述为:

--globalize-symbol=symbolname

赋予符号符号名全局范围,使其在定义它的文件之外可见。这个选项可能不止一次给出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多