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;
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 }
void * memset(void *ptr, char value, size_t num)
Заполнение массива указанными символами
Definition: string.c:203
int strcpy(char *dest, const char *src)
Копирование строк
Definition: string.c:282
list_t process_list
Список процессов
Definition: scheduler.c:14
list_t thread_list
Список потоков
Definition: scheduler.c:15
thread_t * _thread_create_unwrapped(process_t *proc, void *entry_point, size_t stack_size, bool kernel, bool suspend)
Создание потока
Definition: scheduler.c:147
uint32_t next_pid
Следующий ID задачи (PID)
Definition: scheduler.c:17
ssize_t fseek(FILE *stream, ssize_t offset, uint8_t whence)
Установка позиции в потоке данных относительно текущей позиции
Definition: stdio.c:315
void fclose(FILE *stream)
Закончить работу с файлом
Definition: stdio.c:213
FILE * fopen(const char *filename, const char *_mode)
Открывает файл
Definition: stdio.c:166
int fread(FILE *stream, size_t count, size_t size, void *buffer)
Чтение файла
Definition: stdio.c:250
Definition: elf.h:87
Elf32_Addr e_entry
Точка входа в процесс
Definition: elf.h:92
Elf32_Half e_shnum
Количество записей в заголовке раздела
Definition: elf.h:100
Elf32_Half e_phnum
Количество записей заголовка программы
Definition: elf.h:98
Elf32_Half e_type
Тип объектного файла
Definition: elf.h:89
Elf32_Half e_shentsize
Размер записи заголовка раздела
Definition: elf.h:99
Elf32_Half e_mashine
Тип архитектуры
Definition: elf.h:90
unsigned char e_ident[EI_NIDENT]
Идентификационные данные ELF.
Definition: elf.h:88
Elf32_Half e_phentsize
Размер записи заголовка программы
Definition: elf.h:97
Elf32_Off e_shoff
Смещение заголовка таблицы разделов
Definition: elf.h:94
Elf32_Off e_phoff
Смещение заголовка программы
Definition: elf.h:93
Elf32_Word e_version
Версия объектного файла
Definition: elf.h:91
Elf32_Word e_flags
Флаги, специфичные для процессора
Definition: elf.h:95
Elf32_Addr p_paddr
Физический адрес заголовка программы
Definition: elf.h:130
Elf32_Word p_type
Тип заголовка программы
Definition: elf.h:127
Elf32_Word p_filesz
Число байтов в сегменте файла
Definition: elf.h:131
Elf32_Off p_offset
Смещение заголовка программы
Definition: elf.h:128
Elf32_Word p_memsz
...
Definition: elf.h:132
Elf32_Addr p_vaddr
Виртуальный адрес заголовка программы
Definition: elf.h:129
Структура файла. Требуется для работы с VFS.
Definition: stdio.h:21
FILE * file
Ссылка на файл
Definition: elf.h:143
Elf32_Ehdr elf_header
ELF заголовок
Definition: elf.h:139
Elf32_Phdr * p_header
Программный заголовок
Definition: elf.h:141
Elf32_Shdr * section
Секции
Definition: elf.h:140
Definition: list.h:16