问题描述
我手写了一个 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 生成的文件给我的完全一样。
/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
才会起作用。