手写 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.
您必须将 .symtab
s .sh_info
设置为 3,然后您的 test.o
才能工作。
我手写了一个 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.
您必须将 .symtab
s .sh_info
设置为 3,然后您的 test.o
才能工作。