Link 来自 asm/C 的 LLVM StackMaps 错误

Link error with LLVM StackMaps from asm/C

我目前正在尝试使用 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

我的猜测是它无法访问此 table 中的符号。有没有办法从我的汇编函数访问这些数据,或者我是否需要在链接阶段做一些事情以允许它正确访问这些数据?

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

0000000000000000 l       .llvm_stackmaps    0000000000000000 __LLVM_StackMaps

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

如果无法通过源码将factorial中的symbol改为non-static,那么可以使用OBJCOPY改变symbol在object中的可见性直接归档:

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

Give symbol symbolname global scoping so that it is visible outside of the file in which it is defined. This option may be given more than once.