I've wrote to file some assembly instructions and I would like to make them executable. However, I'm messing up something with the program headers. I've read the whole man page about the ELF header, but I didn't understand much.
#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);
}
When I execute the ex.out It gives a segmentation fault and a core dump. This is what the core dump looks like.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
NOTE 0x0000000000000158 0x0000000000000000 0x0000000000000000
0x0000000000000aac 0x0000000000000000 0x0
LOAD 0x0000000000001000 0x00007f1a823b2000 0x0000000000000000
0x0000000000000000 0x0000000000001000 RWE 0x1000
LOAD 0x0000000000001000 0x00007fff4a1d0000 0x0000000000000000
0x0000000000021000 0x0000000000021000 RWE 0x1000
LOAD 0x0000000000022000 0x00007fff4a1f1000 0x0000000000000000
0x0000000000003000 0x0000000000003000 R 0x1000
LOAD 0x0000000000025000 0x00007fff4a1f4000 0x0000000000000000
0x0000000000002000 0x0000000000002000 R E 0x1000
Displaying notes found at file offset 0x00000158 with length 0x00000aac:
Owner Data size Description
CORE 0x00000150 NT_PRSTATUS (prstatus structure)
CORE 0x00000088 NT_PRPSINFO (prpsinfo structure)
CORE 0x00000080 NT_SIGINFO (siginfo_t data)
CORE 0x00000140 NT_AUXV (auxiliary vector)
CORE 0x00000048 NT_FILE (mapped files)
Page size: 4096
Start End Page Offset
0x00007f1a823b2000 0x00007f1a823b3000 0x0000000000000004
/home/sudo_user/Compiler/ex.out
CORE 0x00000200 NT_FPREGSET (floating point registers)
LINUX 0x00000440 NT_X86_XSTATE (x86 XSAVE extended state)
description data: ffffffdf 66 f ...
It really did allocate a 4096 bytes page for me, so what could be the problem here? This is the 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
Also when I try to run gdb
with it, It also gives a segmentation fault:
"Program received signal SIGSEGV, Segmentation fault.
0x00007fffeffae040 in ??"
EDIT
Moreover, if I set p_vaddr to 0 no segmentation fault occurs, however the code doesn't behave like expected. For example, if I put an print instruction on the code, nothing gets printed on the command line when the file is executed.
User contributions licensed under CC BY-SA 3.0