Я пытался узнать о машинном коде x86-64 и файлах ELF. Для этой цели я написал код для создания файла ELF с некоторым машинным кодом в нем. Я использую некоторый машинный код, который я собрал с помощью nasm
(он просто печатает сообщение и вызывает системный вызов exit
, затем я учусь самостоятельно собирать машинный код) и написал программу C для написания правильного заголовка ELF / Заголовки разделов / Таблица символов и т. Д. c. вручную в файл.
Теперь я пытаюсь связать свой файл (с одной функцией в нем) с другим файлом elf, который я генерирую через gcc
из C кода (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");
}
Результат readelf -a
в моем ELF-файле (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'
, хотя функция hello
определена в hello.o
(обратите внимание на запись в таблице символов с именем hello
, которая находится в разделе 1, раздел .text
и, кажется, имеет правильный размер / тип / значение / привязку).
Если я скомпилирую файл только с void hello(){}
так же, как я скомпилировал test.c
, эти два объектных файла, очевидно, могут быть связаны. Кроме того, если я сгенерирую свой собственный файл ELF hello.o
как исполняемый файл, переименовав функцию hello
в _start
, она будет работать нормально. Я уже некоторое время бьюсь головой о стену, и есть две вещи, которые я хотел бы знать: Очевидно, я хотел бы знать свою проблему с файлом ELF. Но также я хотел бы знать, как я могу отлаживать такие проблемы в будущем. Я попытался собрать ld
из исходного кода (клонирование репозитория GNU binutils) с отладочными символами, но я не очень далеко продвинулся в отладке самого ld
.
Изменить: я загрузил свой эльфийский файл сюда: https://drive.google.com/file/d/1cRNr0VPAjkEbueuWFYwLYbpijVnLySqq/view?usp=sharing