微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决对手写 ELF 文件中符号的未定义引用

我手写了一个 ELF32 目标文件,我想通过它来链接。 gcc 但是当我尝试使用我的函数/标签时我得到了一个未定义的引用。我在测试 C 文件中将它定义为 extern 但这不会改变任何东西。

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

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

您在此处看到的是 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

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

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

我将符号设置为全局,这两个 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 并为符号指定大小,但没有解决此问题。符号表的布局与我的 NASM 生成文件给我的完全一样

编辑:我试图与我的 ELF 链接文件出现错误

/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之后的这个文件的符号表:

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 执行链接可以最好地理解错误:

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

在每个符号表中,所有带有 STB_LOCAL 绑定的符号都在弱符号之前 和全局符号。正如“节”所描述的,符号表节的 sh_info 节头成员保存第一个非本地符号的符号表索引。

您必须将 .symtab.sh_info 设置为 3,然后您的 test.o 才会起作用。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。