提问人:user1652403 提问时间:6/21/2020 最后编辑:user1652403 更新时间:6/22/2020 访问量:1683
自定义 ELF 文件中未定义的引用,但符号在文件符号表中定义
Undefined reference in a custom ELF file, but the symbol is defined in the files symbol table
问:
我一直在尝试了解 x86-64 机器代码和 ELF 文件。为此,我编写了一些代码来生成一个包含一些机器代码的 ELF 文件。我使用一些我组装的机器代码(它只是打印一条消息并调用系统调用,接下来是自己学习组装机器代码)并编写了一个 C 程序来手动将正确的 ELF 标头/Section 标头/符号表等写入文件。nasm
exit
现在我正在尝试将我的文件(其中包含单个函数)链接到另一个 elf 文件,我通过 C 代码生成该文件():gcc
test.c
// does not work with or without "extern"
extern void hello();
void _start()
{
hello();
// exit system call
asm(
"movl $60,%eax;"
"xorl %ebx,%ebx;"
"syscall");
}
我的ELF文件的输出是():readelf -a
hello.o
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 64 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 9
Section header string table index: 8
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000280
0000000000000044 0000000000000000 AX 0 0 16
[ 2] .rela.text RELA 0000000000000000 000002c8
0000000000000030 0000000000000018 I 6 1 8
[ 3] .data PROGBITS 0000000000000000 00000300
0000000000000005 0000000000000000 WA 0 0 16
[ 4] .bss NOBITS 0000000000000000 00000310
0000000000000080 0000000000000000 A 0 0 16
[ 5] .rodata PROGBITS 0000000000000000 00000310
000000000000000d 0000000000000000 A 0 0 16
[ 6] .symtab SYMTAB 0000000000000000 00000320
0000000000000150 0000000000000018 7 14 8
[ 7] .strtab STRTAB 0000000000000000 00000470
0000000000000028 0000000000000000 0 0 1
[ 8] .shstrtab STRTAB 0000000000000000 00000498
000000000000003f 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
There is no dynamic section in this file.
Relocation section '.rela.text' at offset 0x2c8 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
00000000001a 000500000001 R_X86_64_64 0000000000000000 .rodata + 0
000000000024 00050000000a R_X86_64_32 0000000000000000 .rodata + d
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
Symbol table '.symtab' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 SECTION LOCAL DEFAULT 1
2: 0000000000000000 0 SECTION LOCAL DEFAULT 2
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 8
9: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello.c
10: 0000000000000000 68 FUNC GLOBAL DEFAULT 1 hello
11: 0000000000000060 13 OBJECT LOCAL DEFAULT 5 msg
12: 000000000000000d 8 NOTYPE LOCAL DEFAULT ABS len
13: 0000000000000050 5 OBJECT GLOBAL DEFAULT 3 _test
No version information found in this file.
我已经编译了test.c
gcc -c -nostdlib -fno-asynchronous-unwind-tables test.c -o test.o
然后与 链接,不幸的是,这会产生ld test.o hello.o
ld: test.o: in function `_start':
test.c:(.text+0xa): undefined reference to `hello'
即使函数在 (请注意符号表中命名的条目,该条目位于第 1 节,该部分中,并且似乎具有正确的大小/类型/值/绑定)。hello
hello.o
hello
.text
如果我以与编译相同的方式编译一个文件,这两个目标文件显然可以链接。此外,如果我将自己的 ELF 文件生成为可执行文件,则将函数重命名为它可以很好地执行。我已经用头撞墙一段时间了,我想知道两件事:显然我想知道我的ELF文件问题。但我也想知道将来如何调试此类问题。我尝试使用调试符号从源代码构建(克隆 GNU binutils 存储库),但我没有走得很远调试本身。void hello(){}
test.c
hello.o
hello
_start
ld
ld
编辑:我已在此处上传了我的精灵文件: https://drive.google.com/file/d/1cRNr0VPAjkEbueuWFYwLYbpijVnLySqq/view?usp=sharing
答:
这很难调试。
以下是您上传到 Google 云端硬盘的文件的输出(它与您的问题中的信息不匹配):readelf -WSs hello.o
There are 9 section headers, starting at offset 0x40:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000000000 000280 000044 00 AX 0 0 16
[ 2] .rela.text RELA 0000000000000000 0002c8 000030 18 I 6 1 8
[ 3] .data PROGBITS 0000000000000000 000300 000005 00 WA 0 0 16
[ 4] .bss NOBITS 0000000000000000 000310 000080 00 A 0 0 16
[ 5] .rodata PROGBITS 0000000000000000 000310 00000d 00 A 0 0 16
[ 6] .symtab SYMTAB 0000000000000000 000320 000150 18 7 14 8
[ 7] .strtab STRTAB 0000000000000000 000470 000028 00 0 0 1
[ 8] .shstrtab STRTAB 0000000000000000 000498 00003f 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
Symbol table '.symtab' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 SECTION LOCAL DEFAULT 1
2: 0000000000000000 0 SECTION LOCAL DEFAULT 2
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 6
7: 0000000000000000 0 SECTION LOCAL DEFAULT 7
8: 0000000000000000 0 SECTION LOCAL DEFAULT 8
9: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello.c
10: 0000000000000000 68 FUNC GLOBAL DEFAULT 1 hello
11: 0000000000000060 13 OBJECT LOCAL DEFAULT 5 msg
12: 000000000000000d 8 NOTYPE LOCAL DEFAULT ABS len
13: 0000000000000050 5 OBJECT GLOBAL DEFAULT 3 _test
问题出在该部分的值 (14) 上。.sh_info
.symtab
根据文档,for 部分应该包含“比最后一个本地符号(绑定STB_LOCAL)的符号表索引大一个”。.sh_info
SYMTAB
因此,值 14 告诉链接器此文件中的所有符号都是本地符号,因此不可能用于解析对它们的任何外部引用。
您需要将所有符号移动到 1 之前(此处,并且需要在 之前移动),以便符号表如下所示:LOCAL
GLOBAL
msg
len
hello
...
9: 0000000000000000 0 FILE LOCAL DEFAULT ABS hello.c
10: 0000000000000060 13 OBJECT LOCAL DEFAULT 5 msg
11: 000000000000000d 8 NOTYPE LOCAL DEFAULT ABS len
12: 0000000000000000 68 FUNC GLOBAL DEFAULT 1 hello
13: 0000000000000050 5 OBJECT GLOBAL DEFAULT 3 _test
然后将该部分设置为 12。.sh_info
.symtab
但我也想知道将来如何调试此类问题。
正如你所发现的,调试 binutils 非常困难,部分原因是它使用了 ,它充满了宏,而且本身很难调试。ld
libbfd
我通过从源代码构建 Gold 来调试它,幸运的是,这产生了完全相同的失败。
评论
.sh_info
.sh_link
readelf
上一个:C++ 中所有函数的未定义引用
评论
hello.o
hello.o
hello
readelf
ld
hello.o
<elf.h>
readelf
objdump