SayoriOS 0.3.3

elf.c
См. документацию.
1
10 #include <mem/pmm.h>
11 #include <elf/elf.h>
12 #include <io/ports.h>
13 #include <lib/stdio.h>
14 #include <lib/math.h>
15 #include "sys/scheduler.h"
16
17 elf_t* load_elf(const char* name){
18 /* Allocate ELF file structure */
19 elf_t* elf = kcalloc(sizeof(elf_t), 1);
20
21 /* Open ELF file */
22 FILE *file_elf = fopen(name, "r");
23
24 if (file_elf->err) {
25 qemu_err("Failed to open ELF file: %s / %d", name, file_elf->err);
26 return nullptr;
27 }
28
29 /* Read ELF header */
30 fread(file_elf, 1, sizeof(Elf32_Ehdr), &elf->elf_header);
31
32 /* Read program header */
33 const Elf32_Half proc_entries = elf->elf_header.e_phnum;
34 const uint32_t proc_size = elf->elf_header.e_phentsize;
35
36 elf->p_header = (Elf32_Phdr*)kcalloc(proc_size, proc_entries);
37
38 fseek(file_elf, (ssize_t)elf->elf_header.e_phoff, SEEK_SET);
39
40 fread(file_elf, proc_entries, proc_size, elf->p_header);
41
42 /* Read ELF sections */
43 Elf32_Half sec_entries = elf->elf_header.e_shnum;
44
45 elf->section = (Elf32_Shdr*)kcalloc(sizeof(Elf32_Shdr), sec_entries);
46
47 fseek(file_elf, (ssize_t)elf->elf_header.e_shoff, SEEK_SET);
48
49 fread(file_elf, sec_entries, sizeof(Elf32_Shdr), elf->section);
50
51 elf->file = file_elf;
52
53 return elf;
54 }
55
56 void unload_elf(elf_t* elf) {
57 kfree(elf->p_header);
58 kfree(elf->section);
59 fclose(elf->file);
60
61 kfree(elf);
62 }
63
64 int32_t run_elf_file(const char *name, int argc, char* eargv[]) {
65 elf_t* elf_file = load_elf(name);
66
67 // TODO: Did you know you can optimize that function without using additional 12288 bytes of RAM?
68 uint32_t vmm_allocated[4096] = {0};
69 uint32_t vmm_mapped[4096] = {0};
70 uint32_t vmm_sizes[4096] = {0};
71
72 if (elf_file == nullptr) {
73 qemu_err("[DBG] Error opening file %s\n", name);
74 return -1;
75 }
76
77 qemu_log("Ident: %s", elf_file->elf_header.e_ident);
78 qemu_log("Type: %x", elf_file->elf_header.e_type);
79 qemu_log("Machine: %x", elf_file->elf_header.e_mashine);
80 qemu_log("Version: %x", elf_file->elf_header.e_version);
81 qemu_log("Entry point: %x", elf_file->elf_header.e_entry);
82 qemu_log("Program Header Offset: %x", elf_file->elf_header.e_phoff);
83 qemu_log("Section Header Offset: %x", elf_file->elf_header.e_shoff);
84 qemu_log("Flags: %x", elf_file->elf_header.e_flags);
85 qemu_log("Program Header Size: %d", elf_file->elf_header.e_phentsize);
86 qemu_log("Program Header Entries: %d", elf_file->elf_header.e_phnum);
87 qemu_log("Section Header Size: %d", elf_file->elf_header.e_shentsize);
88 qemu_log("Section Header Entries: %d", elf_file->elf_header.e_shnum);
89
90 uint32_t vmm_allocated_count = 0;
91
92 for (int32_t i = 0; i < elf_file->elf_header.e_phnum; i++) {
93 Elf32_Phdr *phdr = elf_file->p_header + i;
94
95 if (phdr->p_type != PT_LOAD)
96 continue;
97
98 qemu_log(" - TYPE: %s OFFSET: %x VADDR: %x PADDR:%x FSIZE: %x MSIZE: %xx ",
99 (phdr->p_type == PT_LOAD ? "LOAD" : "UNKNOWN"),
100 phdr->p_offset,
101 phdr->p_vaddr,
102 phdr->p_paddr,
103 phdr->p_filesz,
104 phdr->p_memsz);
105
106 qemu_log("Loading %x bytes to %x", phdr->p_memsz, phdr->p_vaddr);
107 //
108 size_t pagecount = MAX((ALIGN(phdr->p_memsz, PAGE_SIZE) / PAGE_SIZE), 1);
109
110 physical_addr_t addrto = phys_alloc_multi_pages(pagecount);
111 qemu_log("Page count allocated now: %d (memsz: %d; PAGE SIZE: %d)",
112 pagecount, phdr->p_memsz, PAGE_SIZE);
113
114 map_pages(
115 get_kernel_page_directory(),
116 addrto,
117 phdr->p_vaddr,
118 pagecount * 4096,
119 (PAGE_PRESENT | PAGE_USER | PAGE_WRITEABLE) // 0x07
120 );
121
122 vmm_allocated[vmm_allocated_count] = addrto;
123 vmm_sizes[vmm_allocated_count] = pagecount;
124 vmm_mapped[vmm_allocated_count] = phdr->p_vaddr;
125 vmm_allocated_count++;
126
127 memset((void*)phdr->p_vaddr, 0, phdr->p_memsz);
128 qemu_log("Set %x - %x to zero.", (int)((void*)phdr->p_vaddr), (int)((void*)phdr->p_vaddr) + phdr->p_memsz);
129
130 fseek(elf_file->file, (ssize_t)phdr->p_offset, SEEK_SET);
131 fread(elf_file->file, phdr->p_filesz, 1, (char *) phdr->p_vaddr);
132
133 qemu_log("Loaded");
134 }
135
136 int(*entry_point)(int argc, char* eargv[]) = (int(*)(int, char**))elf_file->elf_header.e_entry;
137 qemu_log("ELF entry point: %x", elf_file->elf_header.e_entry);
138
139 qemu_log("Executing");
140 int _result = entry_point(argc, eargv);
141
142 qemu_log("Program returned: %d", _result);
143 qemu_log("Cleaning VMM:");
144
145 for (int32_t i = 0; i < vmm_allocated_count; i++){
146 qemu_log("\tCleaning %d: %x [%d]", i, vmm_allocated[i], vmm_sizes[i]);
147 for(int j = 0; j < vmm_sizes[i]; j++) {
148 unmap_single_page(get_kernel_page_directory(), vmm_mapped[i] + (j * PAGE_SIZE));
149 }
150 phys_free_single_page(vmm_allocated[i]);
151 }
152
153 qemu_log("Cleaned %d pages", vmm_allocated_count);
154
155 // FREE ELF DATA
156
157 unload_elf(elf_file);
158
159 return 0;
160 }
161
162 int32_t spawn(const char *name, int argc, char* eargv[]) {
163 __asm__ volatile("cli");
164
165 elf_t* elf_file = load_elf(name);
166
167 if (elf_file == nullptr) {
168 qemu_err("[DBG] Error opening file %s\n", name);
169 return -1;
170 }
171
172 extern uint32_t next_pid;
173 extern list_t process_list, thread_list;
174
175 // vmm_debug_switch(true);
176 process_t* proc = (process_t*)kcalloc(1, sizeof(process_t));
177 // vmm_debug_switch(false);
178
179 proc->pid = next_pid++;
180 proc->list_item.list = nullptr; // No nested processes hehe :)
181 proc->threads_count = 0;
182
183 strcpy(proc->name, name);
184 proc->suspend = false;
185
186 for (int32_t i = 0; i < elf_file->elf_header.e_phnum; i++) {
187 Elf32_Phdr *phdr = elf_file->p_header + i;
188
189 if (phdr->p_type != PT_LOAD)
190 continue;
191
192 size_t pagecount = MAX((ALIGN(phdr->p_memsz, PAGE_SIZE) / PAGE_SIZE), 1);
193
194 physical_addr_t addrto = phys_alloc_multi_pages(pagecount);
195
196 map_pages(
197 get_kernel_page_directory(),
198 addrto,
199 phdr->p_vaddr,
200 pagecount * PAGE_SIZE,
201 (PAGE_PRESENT | PAGE_USER | PAGE_WRITEABLE) // 0x07
202 );
203
204 memset((void*)phdr->p_vaddr, 0, phdr->p_memsz);
205 qemu_log("Set %x - %x to zero.", (int)((void*)phdr->p_vaddr), (int)((void*)phdr->p_vaddr) + phdr->p_memsz);
206
207 fseek(elf_file->file, (ssize_t)phdr->p_offset, SEEK_SET);
208 fread(elf_file->file, phdr->p_filesz, 1, (char *) phdr->p_vaddr);
209
210 qemu_log("Loaded");
211 }
212
213 int(*entry_point)(int argc, char* eargv[]) = (int(*)(int, char**))elf_file->elf_header.e_entry;
214 qemu_log("ELF entry point: %x", elf_file->elf_header.e_entry);
215
216 thread_t* thread = _thread_create_unwrapped(proc, entry_point, DEFAULT_STACK_SIZE, true, false);
217
218 list_add(&thread_list, &thread->list_item);
219
220 void* virt = clone_kernel_page_directory(proc->page_tables_virts);
221 uint32_t phys = virt2phys(get_kernel_page_directory(), (virtual_addr_t) virt);
222
223 proc->page_dir = phys;
224
225 list_add(&process_list, &proc->list_item);
226
227 qemu_log("PROCESS CREATED");
228
229 for (int32_t i = 0; i < elf_file->elf_header.e_phnum; i++) {
230 Elf32_Phdr *phdr = elf_file->p_header + i;
231
232 if(phdr->p_type != PT_LOAD)
233 continue;
234
235 size_t pagecount = MAX((ALIGN(phdr->p_memsz, PAGE_SIZE) / PAGE_SIZE), 1);
236
237 qemu_log("\t??? Cleaning %d: %x [%d]", i, phdr->p_vaddr, pagecount * PAGE_SIZE);
238
239 for(size_t x = 0; x < pagecount; x++) {
240 unmap_single_page(
241 get_kernel_page_directory(),
242 phdr->p_vaddr + (x * PAGE_SIZE)
243 );
244 }
245 }
246
247 qemu_log("CLEANED %d pages", elf_file->elf_header.e_phnum);
248
249 // FREE ELF DATA
250
251 unload_elf(elf_file);
252
253 qemu_log("RESUMING...");
254
255 __asm__ volatile("sti");
256
257 return 0;
258 }
memset
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
Definition: string.c:203
strcpy
int strcpy(char *dest, const char *src)
Копирование строк
Definition: string.c:282
process_list
list_t process_list
Список процессов
Definition: scheduler.c:14
thread_list
list_t thread_list
Список потоков
Definition: scheduler.c:15
_thread_create_unwrapped
thread_t * _thread_create_unwrapped(process_t *proc, void *entry_point, size_t stack_size, bool kernel, bool suspend)
Создание потока
Definition: scheduler.c:147
next_pid
uint32_t next_pid
Следующий ID задачи (PID)
Definition: scheduler.c:17
fseek
ssize_t fseek(FILE *stream, ssize_t offset, uint8_t whence)
Установка позиции в потоке данных относительно текущей позиции
Definition: stdio.c:315
fclose
void fclose(FILE *stream)
Закончить работу с файлом
Definition: stdio.c:213
fopen
FILE * fopen(const char *filename, const char *_mode)
Открывает файл
Definition: stdio.c:166
fread
int fread(FILE *stream, size_t count, size_t size, void *buffer)
Чтение файла
Definition: stdio.c:250
Elf32_Ehdr
Definition: elf.h:87
Elf32_Ehdr::e_entry
Elf32_Addr e_entry
Точка входа в процесс
Definition: elf.h:92
Elf32_Ehdr::e_shnum
Elf32_Half e_shnum
Количество записей в заголовке раздела
Definition: elf.h:100
Elf32_Ehdr::e_phnum
Elf32_Half e_phnum
Количество записей заголовка программы
Definition: elf.h:98
Elf32_Ehdr::e_type
Elf32_Half e_type
Тип объектного файла
Definition: elf.h:89
Elf32_Ehdr::e_shentsize
Elf32_Half e_shentsize
Размер записи заголовка раздела
Definition: elf.h:99
Elf32_Ehdr::e_mashine
Elf32_Half e_mashine
Тип архитектуры
Definition: elf.h:90
Elf32_Ehdr::e_ident
unsigned char e_ident[EI_NIDENT]
Идентификационные данные ELF.
Definition: elf.h:88
Elf32_Ehdr::e_phentsize
Elf32_Half e_phentsize
Размер записи заголовка программы
Definition: elf.h:97
Elf32_Ehdr::e_shoff
Elf32_Off e_shoff
Смещение заголовка таблицы разделов
Definition: elf.h:94
Elf32_Ehdr::e_phoff
Elf32_Off e_phoff
Смещение заголовка программы
Definition: elf.h:93
Elf32_Ehdr::e_version
Elf32_Word e_version
Версия объектного файла
Definition: elf.h:91
Elf32_Ehdr::e_flags
Elf32_Word e_flags
Флаги, специфичные для процессора
Definition: elf.h:95
Elf32_Phdr
Definition: elf.h:126
Elf32_Phdr::p_paddr
Elf32_Addr p_paddr
Физический адрес заголовка программы
Definition: elf.h:130
Elf32_Phdr::p_type
Elf32_Word p_type
Тип заголовка программы
Definition: elf.h:127
Elf32_Phdr::p_filesz
Elf32_Word p_filesz
Число байтов в сегменте файла
Definition: elf.h:131
Elf32_Phdr::p_offset
Elf32_Off p_offset
Смещение заголовка программы
Definition: elf.h:128
Elf32_Phdr::p_memsz
Elf32_Word p_memsz
...
Definition: elf.h:132
Elf32_Phdr::p_vaddr
Elf32_Addr p_vaddr
Виртуальный адрес заголовка программы
Definition: elf.h:129
Elf32_Shdr
Definition: elf.h:108
FILE
Структура файла. Требуется для работы с VFS.
Definition: stdio.h:21
elf_sections
Definition: elf.h:138
elf_sections::file
FILE * file
Ссылка на файл
Definition: elf.h:143
elf_sections::elf_header
Elf32_Ehdr elf_header
ELF заголовок
Definition: elf.h:139
elf_sections::p_header
Elf32_Phdr * p_header
Программный заголовок
Definition: elf.h:141
elf_sections::section
Elf32_Shdr * section
Секции
Definition: elf.h:140
list_t
Definition: list.h:16