手写 ELF 文件中未定义的符号引用

Undefined reference to symbol in hand-written ELF file

我手写了一个 ELF32 目标文件,我想 link 通过它。 gcc 但是当我尝试使用我的 function/label 时,我得到了一个未定义的引用。我在测试 C 文件中将其定义为 extern 但这并没有改变任何东西。

此目标文件包含以下程序集:

00000000 <func>:
   0:   31 c0                   xor    %eax,%eax
   2:   40                      inc    %eax
   3:   b3 2a                   mov    [=10=]x2a,%bl
   5:   cd 80                   int    [=10=]x80

您在这里看到的是 objdump -S test.o 的输出,它表明 objdump 非常有能力找到我的 .text 部分。

我的 readelf 输出是:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          128 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         5
  Section header string table index: 1

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .shstrtab         STRTAB          00000000 000034 000021 00      0   0  1
  [ 2] .text             PROGBITS        00000000 000060 000007 00  AX  0   0 16
  [ 3] .strtab           STRTAB          00000000 000070 00000d 00      0   0  1
  [ 4] .symtab           SYMTAB          00000000 000150 000040 10      3   4  4

Symbol table '.symtab' contains 4 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS test.S
     2: 00000000     0 SECTION LOCAL  DEFAULT    2 
     3: 00000000     0 NOTYPE  GLOBAL DEFAULT    2 func

这进一步表明我有一个有效的符号 table 和部分。

我的问题是,确切 发生未定义引用的条件是什么?我在这里做错了什么可能导致这样的错误?每个部分的对齐 是必须的 吗?我已经基本做到了。

我将我的符号设置为全局,这两个ELF分析程序都找到了但是GCC仍然无法识别该符号...

这是 ELF 文件的转储:

00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000  .ELF............
00000010: 0100 0300 0100 0000 0000 0000 0000 0000  ................
00000020: 8000 0000 0000 0000 3400 0000 0000 2800  ........4.....(.
00000030: 0500 0100 002e 7368 7374 7274 6162 002e  ......shstrtab..
00000040: 7465 7874 002e 7374 7274 6162 002e 7379  text..strtab..sy
00000050: 6d74 6162 0000 0000 0000 0000 0000 0000  mtab............
00000060: 31c0 40b3 2acd 8000 0000 0000 0000 0000  1.@.*...........
00000070: 0066 756e 6300 7465 7374 2e53 0000 0000  .func.test.S....
00000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000090: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000a0: 0000 0000 0000 0000 0100 0000 0300 0000  ................
000000b0: 0000 0000 0000 0000 3400 0000 2100 0000  ........4...!...
000000c0: 0000 0000 0000 0000 0100 0000 0000 0000  ................
000000d0: 0b00 0000 0100 0000 0600 0000 0000 0000  ................
000000e0: 6000 0000 0700 0000 0000 0000 0000 0000  `...............
000000f0: 1000 0000 0000 0000 1100 0000 0300 0000  ................
00000100: 0000 0000 0000 0000 7000 0000 0d00 0000  ........p.......
00000110: 0000 0000 0000 0000 0100 0000 0000 0000  ................
00000120: 1900 0000 0200 0000 0000 0000 0000 0000  ................
00000130: 5001 0000 4000 0000 0300 0000 0400 0000  P...@...........
00000140: 0400 0000 1000 0000 0000 0000 0000 0000  ................
00000150: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000160: 0600 0000 0000 0000 0000 0000 0400 f1ff  ................
00000170: 0000 0000 0000 0000 0000 0000 0300 0200  ................
00000180: 0100 0000 0000 0000 0000 0000 1000 0200  ................

我已经尝试将函数名称 NOTYPE 更改为 FUNC 并为符号指定大小,但没有解决问题。符号 table 的布局 完全 正如我的 NASM 生成的文件给我的那样。

编辑: 我尝试使用我的 ELF link 的文件出现错误:

/usr/bin/ld: foo.o: in function `main':
foo.c:(.text+0x18): undefined reference to `func'
collect2: error: ld returned 1 exit status

来自 运行 gcc -m32 foo.o test.o

源代码:

extern void func();

int
main(int argc,
     char **argv)
{
    func();
    return 0;
}

gcc -m32 -c foo.c -o foo.o之后此文件的符号table:

Symbol table '.symtab' contains 15 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS foo.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    2 
     3: 00000000     0 SECTION LOCAL  DEFAULT    4 
     4: 00000000     0 SECTION LOCAL  DEFAULT    5 
     5: 00000000     0 SECTION LOCAL  DEFAULT    6 
     6: 00000000     0 SECTION LOCAL  DEFAULT    8 
     7: 00000000     0 SECTION LOCAL  DEFAULT    9 
     8: 00000000     0 SECTION LOCAL  DEFAULT   10 
     9: 00000000     0 SECTION LOCAL  DEFAULT    7 
    10: 00000000     0 SECTION LOCAL  DEFAULT    1 
    11: 00000000    38 FUNC    GLOBAL DEFAULT    2 main
    12: 00000000     0 FUNC    GLOBAL HIDDEN     6 __x86.get_pc_thunk.ax
    13: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND _GLOBAL_OFFSET_TABLE_
    14: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND func

通过使用 lld 执行 link:

可以最好地理解该错误
ld.lld -m elf_i386  -e main main.o test.o
ld.lld: error: test.o: non-local symbol (3) found at index < .symtab's sh_info (4)

来自 Solaris 链接器 docs:

In each symbol table, all symbols with STB_LOCAL binding precede the weak and global symbols. As "Sections" describes, a symbol table section's sh_info section header member holds the symbol table index for the first non-local symbol.

您必须将 .symtabs .sh_info 设置为 3,然后您的 test.o 才能工作。