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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#include <stdint.h>
#include "drive.h"
#include "elf.h"
#include "task.h"
#include "util.h"
#include "paging.h"
#include "pmap.h"
#define ELF_MAGIC 0x464c457f
enum {
ELF_32 = 1,
ELF_64 = 2
};
enum {
LITTLE_ENDIAN = 1,
BIG_ENDIAN = 2
};
enum {
//...
ARCH_X86 = 0x03
//...
};
struct elf_header {
uint32_t magic;
uint8_t word_size;
uint8_t endianness;
uint8_t elf_version;
uint8_t target_os;//ignored
uint8_t os_abi_version;//should be zero
uint8_t reserved[7];
uint16_t object_type;//TODO
uint16_t architecture;//should be ARCH_X86
uint32_t elf_version_2;
uint32_t entry_vma;
uint32_t phtable_fa;
uint32_t shtable_fa;
uint32_t flags;
uint16_t eh_size;
uint16_t phentry_size;
uint16_t phtable_count;
uint16_t shentry_size;
uint16_t shtable_count;
uint16_t sh_names_entry;
} __attribute__ ((packed));
enum {
PT_UNUSED = 0,
PT_LOADME = 1,
PT_DYNLINK = 2,
PT_INTERP = 3,
PT_COMMENT = 4,
PT_SHARED = 5,
PT_PHTABLE = 6,
PT_TL_TMPL = 7
};
enum {
PH_WRITABLE = 0x02
};
struct ph_entry {
uint32_t type;
uint32_t fa;
uint32_t vma;//must be page-aligned
uint32_t pma;//ignored
uint32_t fs;
uint32_t vms;
uint32_t flags;
uint32_t align;
} __attribute__ ((packed));
bool try_elf_run(const struct drive *d, const char *path) {
file_id_t h = d->get_file(d, path);
if (!h)
return false;
struct elf_header ehead;
fmcpy(&ehead, d, h, 0, sizeof(struct elf_header));
if ((ehead.magic != ELF_MAGIC) ||
(ehead.word_size != ELF_32) ||
(ehead.endianness != LITTLE_ENDIAN) ||
ehead.os_abi_version) {
d->free_file(d, h);
return false;
}
uint32_t phtable_size = ehead.phentry_size * ehead.phtable_count;
uint16_t phtable_pages = (phtable_size - 1) / 4096 + 1;
void *phtable = allocate_kernel_pages(phtable_pages);
fmcpy(phtable, d, h, ehead.phtable_fa, phtable_size);
void *pd = new_task_pd();
for (uint32_t phi = 0; phi < ehead.phtable_count; ++phi) {
struct ph_entry *entry = phtable + phi * ehead.phentry_size;
if (entry->type != PT_LOADME)
continue;
void *pma = pd_user_allocate(pd, entry->vma, (entry->vms - 1) / 4096 + 1, entry->flags & PH_WRITABLE);
fmcpy(pma, d, h, entry->fa, entry->fs);
}
free_pages(phtable, phtable_pages);
d->free_file(d, h);
struct task_state tstate;
tstate.page_directory = pd;
tstate.ret_addr = ehead.entry_vma;
new_task(tstate);
return true;
}
|