我正在try 从头开始创建一个ELF64文件;我现在用来测试它的程序只是使用汇编调用exit()syscall;没有库的链接等.下面是"Dumpelf"的输出:
#include <elf.h>
/*
* ELF dump of 'elftest'
* 4120 (0x1018) bytes
*/
Elf64_Dyn dumpedelf_dyn_0[];
struct {
Elf64_Ehdr ehdr;
Elf64_Phdr phdrs[3];
Elf64_Shdr shdrs[3];
Elf64_Dyn *dyns;
} dumpedelf_0 = {
.ehdr = {
.e_ident = { /* (EI_NIDENT bytes) */
/* [0] EI_MAG: */ 0x7F,'E','L','F',
/* [4] EI_CLASS: */ 2 , /* (ELFCLASS64) */
/* [5] EI_DATA: */ 1 , /* (ELFDATA2LSB) */
/* [6] EI_VERSION: */ 1 , /* (EV_CURRENT) */
/* [7] EI_OSABI: */ 0 , /* (ELFOSABI_NONE) */
/* [8] EI_ABIVERSION: */ 0 ,
/* [9-15] EI_PAD: */ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
},
.e_type = 2 , /* (ET_EXEC) */
.e_machine = 62 , /* (EM_X86_64) */
.e_version = 1 , /* (EV_CURRENT) */
.e_entry = 0x400000 , /* (start address at runtime) */
.e_phoff = 64 , /* (bytes into file) */
.e_shoff = 232 , /* (bytes into file) */
.e_flags = 0x0 ,
.e_ehsize = 64 , /* (bytes) */
.e_phentsize = 56 , /* (bytes) */
.e_phnum = 3 , /* (program headers) */
.e_shentsize = 64 , /* (bytes) */
.e_shnum = 3 , /* (section headers) */
.e_shstrndx = 1
},
.phdrs = {
/* Program Header #0 0x40 */
{
.p_type = 6 , /* [PT_PHDR] */
.p_offset = 64 , /* (bytes into file) */
.p_vaddr = 0x40 , /* (virtual addr at runtime) */
.p_paddr = 0x40 , /* (physical addr at runtime) */
.p_filesz = 168 , /* (bytes in file) */
.p_memsz = 168 , /* (bytes in mem at runtime) */
.p_flags = 0x4 , /* PF_R */
.p_align = 8 , /* (min mem alignment in bytes) */
},
/* Program Header #1 0x78 */ <-- PT_NULL=OK, PT_LOAD=SEGFAULT
{
.p_type = 1 , /* [PT_LOAD] */
.p_offset = 0 , /* (bytes into file) */
.p_vaddr = 0x0 , /* (virtual addr at runtime) */
.p_paddr = 0x0 , /* (physical addr at runtime) */
.p_filesz = 441 , /* (bytes in file) */
.p_memsz = 441 , /* (bytes in mem at runtime) */
.p_flags = 0x4 , /* PF_R */
.p_align = 4096 , /* (min mem alignment in bytes) */
},
/* Program Header #2 0xB0 */ <-- WORKS AS EXPECTED
{
.p_type = 1 , /* [PT_LOAD] */
.p_offset = 4096 , /* (bytes into file) */
.p_vaddr = 0x400000 , /* (virtual addr at runtime) */
.p_paddr = 0x400000 , /* (physical addr at runtime) */
.p_filesz = 24 , /* (bytes in file) */
.p_memsz = 24 , /* (bytes in mem at runtime) */
.p_flags = 0x5 , /* PF_R | PF_X */
.p_align = 4096 , /* (min mem alignment in bytes) */
},
},
.shdrs = {
/* Section Header #0 '' 0xE8 */
{
.sh_name = 0 ,
.sh_type = 0 , /* [SHT_NULL] */
.sh_flags = 0 ,
.sh_addr = 0x0 ,
.sh_offset = 0 , /* (bytes) */
.sh_size = 0 , /* (bytes) */
.sh_link = 0 ,
.sh_info = 0 ,
.sh_addralign = 0 ,
.sh_entsize = 0
},
/* Section Header #1 '.shstrtab' 0x128 */
{
.sh_name = 1 ,
.sh_type = 3 , /* [SHT_STRTAB] */
.sh_flags = 32 ,
.sh_addr = 0x1A8 ,
.sh_offset = 424 , /* (bytes) */
.sh_size = 17 , /* (bytes) */
.sh_link = 0 ,
.sh_info = 0 ,
.sh_addralign = 1 ,
.sh_entsize = 1
},
/* Section Header #2 '.text' 0x168 */
{
.sh_name = 11 ,
.sh_type = 1 , /* [SHT_PROGBITS] */
.sh_flags = 6 ,
.sh_addr = 0x400000 ,
.sh_offset = 4096 , /* (bytes) */
.sh_size = 24 , /* (bytes) */
.sh_link = 0 ,
.sh_info = 0 ,
.sh_addralign = 16 ,
.sh_entsize = 0
},
},
.dyns = dumpedelf_dyn_0,
};
Elf64_Dyn dumpedelf_dyn_0[] = {
/* no dynamic tags ! */ };
如果我try 在x86_64 Linux中执行该程序,程序会出现分段错误.试图在GDB中调试它实际上是不可能的,GDB告诉我程序"在启动期间"出现了段错误,所以在那里没有帮助.
在与这个问题纠缠了几天之后,我始终无法弄清楚为什么这会导致段错误;我已经查看了许多其他可执行文件,包括系统二进制文件和用各种不同程序编译的文件,它们都加载了vaddr=0x0处的ELF头文件,没有问题,为什么在这种情况下它会失败?
如果我将Program Header #1 0x78
从PT_LOAD
更改为PT_NULL
,以不将ELF64标头加载到内存中,程序将按预期运行,并且没有错误地退出,因此我知道可执行部分是正常的.这会将问题缩小到该标头,但这不是一个可行的解决方案.
编辑:这是与使用readelf -a
查看的相同文件:
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: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400000
Start of program headers: 64 (bytes into file)
Start of section headers: 232 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 3
Size of section headers: 64 (bytes)
Number of section headers: 3
Section header string table index: 1
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .shstrtab STRTAB 00000000000001a8 000001a8
0000000000000011 0000000000000001 S 0 0 1
[ 2] .text PROGBITS 0000000000400000 00001000
0000000000000018 0000000000000000 AX 0 0 16
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),
D (mbind), l (large), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000000a8 0x00000000000000a8 R 0x8
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x00000000000001b9 0x00000000000001b9 R 0x1000
LOAD 0x0000000000001000 0x0000000000400000 0x0000000000400000
0x0000000000000018 0x0000000000000018 R E 0x1000
Section to Segment mapping:
Segment Sections...
00
01
02 .text
There is no dynamic section in this file.
There are no relocations in this file.
No processor specific unwind information to decode
No version information found in this file.
编辑#2:添加了以普通用户身份和以root
身份输出的strace,这令人惊讶地工作:
$ strace ./filename
execve("./filename", ["./filename"], 0x7ffd660b1910 /* 28 vars */) = -1 EPERM (Operation not permitted)
+++ killed by SIGSEGV +++
Segmentation fault
(as root)
# strace ./filename
execve("./filename", ["./filename"], 0x7ffd06138b90 /* 27 vars */) = 0
exit(0) = ?
+++ exited with 0 +++
$ stat filename
File: filename
Size: 4120 Blocks: 16 IO Block: 4096 regular file
Device: 820h/2080d Inode: 1920 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 1000/ username) Gid: ( 1000/ username)
Access: 2023-06-15 13:24:24.007538545 +0200
Modify: 2023-06-15 13:24:16.787538566 +0200
Change: 2023-06-15 13:24:16.787538566 +0200
Birth: 2023-06-15 13:24:16.787538566 +0200