C++ 如何计算ELF程序头的虚拟地址?
我已经写了一些汇编指令文件,我想让它们可以执行。然而,我把程序标题搞砸了。我已经阅读了关于精灵头的整个手册页,但我不太明白C++ 如何计算ELF程序头的虚拟地址?,c++,elf,coredump,C++,Elf,Coredump,我已经写了一些汇编指令文件,我想让它们可以执行。然而,我把程序标题搞砸了。我已经阅读了关于精灵头的整个手册页,但我不太明白 #include <elf.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> void MakeExecutable(char *codeBuffer, char *startAddr, unsigned int codeSize){ c
#include <elf.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
void MakeExecutable(char *codeBuffer, char *startAddr, unsigned int codeSize){
char *fileBuffer = (char*) malloc(2058);
memset(fileBuffer, 0, 2058);
//I've omitted the sections declaration
unsigned int codeOffset = sizeof(Elf64_Ehdr) + (unsigned int ) (startAddr - codeBuffer);
Elf64_Ehdr *h = (Elf64_Ehdr*) &fileBuffer[0];
h->e_ident[0] = 0x7f;
h->e_ident[1] = 0x45;
h->e_ident[2] = 0x4c;
h->e_ident[3] = 0x46;
h->e_ident[EI_CLASS] = ELFCLASS64;
h->e_ident[EI_DATA] = ELFDATA2LSB;
h->e_ident[EI_VERSION] = EV_CURRENT;
h->e_ident[EI_OSABI] = ELFOSABI_SYSV;
h->e_type = ET_DYN;
h->e_machine = EM_X86_64;
h->e_version = EV_CURRENT;
h->e_entry = 64;
h->e_phentsize = sizeof(Elf64_Phdr);
h->e_shentsize = sizeof(Elf64_Shdr);
h->e_shoff = 0;
h->e_phoff = 800;
h->e_shnum = 0;
h->e_phnum = 1;
h->e_shstrndx= 0;
h->e_ehsize = sizeof(Elf64_Ehdr);
Elf64_Phdr *ph = (Elf64_Phdr*) &fileBuffer[800];
ph->p_type = PT_LOAD;
ph->p_vaddr = 0x8050000;
ph->p_paddr = 0;
ph->p_offset = 0x4000;
ph->p_memsz = 2058;
ph->p_flags = PF_X | PF_R | PF_W;
ph->p_filesz = 2058;
ph->p_align = 0x100000;
int file = open("ex.out", O_TRUNC | O_RDWR, S_IRWXO | S_IRWXU | S_IRWXG );
int error = write(file, fileBuffer, 2058);
close(file);
}
它确实为我分配了4096字节的页面,那么这里会有什么问题呢?这是objdump
ex.out: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 81 ec 01 00 00 00 sub $0x1,%rsp
b: 8a 85 10 00 00 00 mov 0x10(%rbp),%al
11: 88 85 ff ff ff ff mov %al,-0x1(%rbp)
17: 49 c7 c1 00 00 00 00 mov $0x0,%r9
1e: 49 c7 c0 00 00 00 00 mov $0x0,%r8
25: 49 c7 c2 00 00 00 00 mov $0x0,%r10
2c: 48 c7 c2 00 00 00 00 mov $0x0,%rdx
33: 48 c7 c6 00 00 00 00 mov $0x0,%rsi
3a: 48 c7 c7 00 00 00 00 mov $0x0,%rdi
41: 48 c7 c0 3c 00 00 00 mov $0x3c,%rax
48: 0f 05 syscall
4a: 48 89 ec mov %rbp,%rsp
4d: 5d pop %rbp
4e: c3 retq
ex.out:文件格式elf64-x86-64
第节的分解。正文:
0000000000000000 :
0:55推送%rbp
1:48 89 e5 mov%rsp,%rbp
4:48 81 ec 01 00 00分$0x1,%rsp
b:8a 85 10 00 mov 0x10(%rbp),%al
11:88 85 ff移动%al,-0x1(%rbp)
17:49 c7 c1 00 mov$0x0,%r9
1e:49 c7 C000 mov$0x0,%r8
25:49 c7 c2 00 mov$0x0,%r10
2c:48 c7 c2 00 mov$0x0,%rdx
33:48 c7 C600 mov$0x0,%rsi
3a:48 c7 c7 00 mov$0x0,%rdi
41:48 c7 c0 3c 00 mov$0x3c,%rax
48:0f 05系统调用
4a:48 89 ec mov%rbp,%rsp
4d:5d pop%rbp
4e:c3 retq
另外,当我尝试使用它运行gdb
时,它也会出现分段错误:
'程序收到信号SIGSEGV,分段故障。
0x00007fffeffae040英寸???”
编辑
此外,如果我将p_vaddr设置为0,则不会出现分段错误,但是代码的行为与预期不符。例如,如果我在代码上放了一条打印指令,则在执行文件时,命令行上不会打印任何内容。代码段不使用
codeBuffer
,也不使用codefset
。请提供代码段不使用codeBuffer
,也不使用codecoffset
。请提供
ex.out: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 81 ec 01 00 00 00 sub $0x1,%rsp
b: 8a 85 10 00 00 00 mov 0x10(%rbp),%al
11: 88 85 ff ff ff ff mov %al,-0x1(%rbp)
17: 49 c7 c1 00 00 00 00 mov $0x0,%r9
1e: 49 c7 c0 00 00 00 00 mov $0x0,%r8
25: 49 c7 c2 00 00 00 00 mov $0x0,%r10
2c: 48 c7 c2 00 00 00 00 mov $0x0,%rdx
33: 48 c7 c6 00 00 00 00 mov $0x0,%rsi
3a: 48 c7 c7 00 00 00 00 mov $0x0,%rdi
41: 48 c7 c0 3c 00 00 00 mov $0x3c,%rax
48: 0f 05 syscall
4a: 48 89 ec mov %rbp,%rsp
4d: 5d pop %rbp
4e: c3 retq