我目前正在尝试使用基于文档的ELFIO库创建简单的ELF可执行文件(第8页)[1]。这是从readelf
输出的,当他们的代码略微修改后的版本上运行时(没什么重要的,只是不同的字符串和地址库。对齐,标志等都没有改变。)
ELF Header:
Magic: 7f 45 4c 46 01 01 01 03 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x400000
Start of program headers: 52 (bytes into file)
Start of section headers: 4168 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 2
Size of section headers: 40 (bytes)
Number of section headers: 4
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 00102e 000017 00 0 0 0
[ 2] .text PROGBITS 00400000 001000 00001d 00 AX 0 0 16
[ 3] .data PROGBITS 00400020 001020 00000e 00 WA 0 0 4
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x00400000 0x00400000 0x0001d 0x0001d R E 0x1000
LOAD 0x001020 0x00400020 0x00400020 0x0000e 0x0000e RW 0x10
Section to Segment mapping:
Segment Sections...
00 .text
01 .data
此可执行文件运行正常。我想从文本部分进一步移动数据部分,所以我选择了地址0x400040
。在这里你可以看到它就是我所做的一切。
ELF Header:
Magic: 7f 45 4c 46 01 01 01 03 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x400000
Start of program headers: 52 (bytes into file)
Start of section headers: 4168 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 2
Size of section headers: 40 (bytes)
Number of section headers: 4
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 00102e 000017 00 0 0 0
[ 2] .text PROGBITS 00400000 001000 00001d 00 AX 0 0 16
[ 3] .data PROGBITS 00400040 001020 00000e 00 WA 0 0 4
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x00400000 0x00400000 0x0001d 0x0001d R E 0x1000
LOAD 0x001020 0x00400040 0x00400040 0x0000e 0x0000e RW 0x10
Section to Segment mapping:
Segment Sections...
00 .text
01 .data
但是,这个文件保留seg。一开始就错了。我真的不明白发生了什么。起初我虽然它与部分和段的对齐有关,但它们对我来说似乎没问题。我还怀疑ASLR(因为Hello World的地址是硬编码的,没有重定位)并试图在/proc/sys/kernel/randomize_va_space
中将其关闭。我还检查了linux内核源代码,特别是文件fs/binfmt_elf.c
,但为了完全理解那里发生了什么,我需要更多时间。所以我想请求你的帮助。如果你知道地址0x400040
有什么问题,为什么这个文件会保留seg。错误,或者你可以指向我内核中的某些代码行,那么我真的很感激。
修改:我还尝试了gdb
,但bt
提供了No stack
。在入口点地址上设置读取观察点不起作用。
编辑2:在使用该文件后,我发现将第二段的文件偏移从0x1020
移动到0x1040
会导致文件正常工作。所以现在我的问题是,文件偏移和虚拟地址是否需要处于某种关系?
答案 0 :(得分:2)
所以现在我的问题是,文件偏移和虚拟地址是否需要处于某种关系?
是:文件偏移量必须与VirtAddr
和PhysAddr
模数页面大小一致,因为文件是mmap
直接(由内核加载程序)
如果您不保持这种关系,内核将创建一个新流程,尝试将您的可执行文件映射到它,发现您违反了基本约束,并将终止您的流程(使用SIGKILL
, 我相信)。您的进程永远不会在用户空间中执行单个指令。
答案 1 :(得分:-1)
没有创建堆栈框架,这意味着在入口点之前出现了一些问题。 请告诉我文件是否与libc等任何库模块链接,因为它们将提供初始设置来调用我们的入口点函数。 使用gdb并在_start创建断点。如果您没有与图书馆链接,那么设置堆栈,参数,环境的任务将由您负责。