forked from yrp604/rappel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
elf_amd64.c
91 lines (78 loc) · 2.14 KB
/
elf_amd64.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <elf.h>
#include <stdint.h>
#include <string.h>
#include <sys/user.h>
#include "common.h"
#include "elf_gen.h"
const size_t gen_elf_amd64(
uint8_t **out,
const unsigned long start,
const uint8_t *const code,
const size_t code_sz)
{
/* We give the elf header and phdr an entire page, because the elf loader can
* only map the file at PAGE_SIZE offsets. So our file will look like this
* for an invocation with some code and 2 data segments.
*
* +----------+
* | 1st page |
* | ehdr |
* | phdr |
* | shdr |
* | shdr |
* |----------|
* | 2nd page |
* | code |
* |----------|
* | 3rd page |
* | data 1 |
* |----------|
* | 4th page |
* | data 2 |
* +----------+
*
* TODO add data section, section headers
*/
const size_t pg_align_dist = start - (start & ~0xffff);
const size_t pad_sz = PAGE_SIZE - (PAGE_SIZE % code_sz);
const size_t sz = PAGE_SIZE + pg_align_dist + code_sz + pad_sz;
uint8_t *const e = xmalloc(sz);
mem_assign(e, sz, TRAP, TRAP_SZ);
Elf64_Ehdr *const ehdr = (Elf64_Ehdr *) e;
ehdr->e_ident[0] = ELFMAG0;
ehdr->e_ident[1] = ELFMAG1;
ehdr->e_ident[2] = ELFMAG2;
ehdr->e_ident[3] = ELFMAG3;
ehdr->e_ident[4] = ELFCLASS64;
ehdr->e_ident[5] = ELFDATA2LSB;
ehdr->e_ident[6] = EV_CURRENT;
ehdr->e_ident[7] = ELFOSABI_NONE;
ehdr->e_ident[9] = 0;
// Padding
ehdr->e_type = ET_EXEC;
ehdr->e_machine = EM_X86_64;
ehdr->e_version = EV_CURRENT;
ehdr->e_entry = start;
ehdr->e_phoff = sizeof(Elf64_Ehdr);
ehdr->e_shoff = 0; // XXX
ehdr->e_flags = 0;
ehdr->e_ehsize = sizeof(Elf64_Ehdr);
ehdr->e_phentsize = sizeof(Elf64_Phdr);
ehdr->e_phnum = 1;
ehdr->e_shentsize = 0;
ehdr->e_shnum = 0;
ehdr->e_shstrndx = 0;
Elf64_Phdr *const phdr = (Elf64_Phdr *) ((uint8_t *) e + sizeof(Elf64_Ehdr));
phdr->p_type = PT_LOAD;
phdr->p_flags = PF_X | PF_R;
phdr->p_offset = PAGE_SIZE;
phdr->p_vaddr = start - pg_align_dist;
phdr->p_paddr = 0;
phdr->p_filesz = code_sz + pg_align_dist;
phdr->p_memsz = code_sz + pg_align_dist;
phdr->p_align = 0x4;
uint8_t *const data = (uint8_t *) e + PAGE_SIZE + pg_align_dist;
memcpy(data, code, code_sz);
*out = e;
return sz;
}