Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
spawn.c
Go to the documentation of this file.
1// #include "spawn.h"
2// #include "task.h"
3// #include <hal/cpu/paging.h>
4// #include <libk/executable/elf.h>
5// #include <libk/serial.h>
6// #include <str.h>
7// #include <memory/memory_utils.h>
8// #include <memory/phys_base_allocator.h>
9// #include <sys/library.h>
10// #include <vfs/vfs.h>
11
12// extern boolean_t is_running_program;
13// extern void __memcopy(void* dest, void* src, uint32_t size);
14
15// uint64_t setup_user_stack(uint64_t argc, uint64_t vaddr, uint64_t* rsp,
16// char** argv, char** envp) {
17// uint64_t stack_top_vadr = vaddr;
18
19// // Push NULL terminator for envp
20// *--rsp = 0;
21// stack_top_vadr -= sizeof(uint64_t);
22// for (int i = 0; envp[i]; i++) {
23// *--rsp = (uint64_t) envp[i];
24// stack_top_vadr -= sizeof(uint64_t);
25// }
26
27// // Push NULL terminator for argv
28// *--rsp = 0;
29// stack_top_vadr -= sizeof(uint64_t);
30// for (int i = argc - 1; i >= 0; i--) {
31// *--rsp = (uint64_t) argv[i];
32// stack_top_vadr -= sizeof(uint64_t);
33// }
34
35// // Push argc
36// *--rsp = argc;
37// stack_top_vadr -= sizeof(uint64_t);
38
39// *(--rsp) = (uint64_t) 0x0240000000;
40// stack_top_vadr -= sizeof(uint64_t);
41// return stack_top_vadr;
42// }
43
44// void setup_stack(uintptr_t stack_addr) {
45// serial_trace("stack addr : 0x%x\n", stack_addr);
46// // setup stack
47// uint64_t* rsp = (uint64_t*) stack_addr;
48
49// // set rsp
50// asm("mov %0, %%rsp" ::"r"(rsp + 4096));
51// asm("and $-16, %rsp");
52// }
53
54// #define PAGE_PRESENT 0x1
55// #define PAGE_WRITE (0b1 << 2)
56// #define PAGE_EXECUTE (0b1 << 63)
57// #define PAGE_USER (0b1 << 3)
58
59// #define PROT_READ 4
60// #define PROT_WRITE 0x2
61// #define PROT_EXEC 1
62
63// uint64_t pflags_to_page_flags(uint32_t pflags) {
64// uint64_t flags = 0;
65// if (pflags & PROT_READ)
66// flags |= PAGE_PRESENT;
67// if (pflags & PROT_WRITE)
68// flags |= PAGE_PRESENT | PAGE_WRITE;
69// if (pflags & PROT_EXEC)
70// flags |= PAGE_PRESENT | PAGE_EXECUTE;
71// return flags | PAGE_USER;
72// }
73
74// // extern void __r();
75// extern void jump_usermode(uint64_t entry, uint64_t stack);
76
77// int spawn(const char* path, char* argv[], char* envp[]) {
78// serial_trace("\nspawn %s\n", path);
79// // auto fd = vxFileInternalOpen(path, 0);
80// // struct vfs_file_stats stats;
81// // int fs_resp = vxVFSFileStat(fd, &stats);
82// // serial_trace("file size : %d\n", stats.size);
83
84// // uint8_t *file = (uint8_t *)(vxPhysBaseAlloc(2 + stats.size / 4096));
85// // int read = vxVFSRead(fd, file, stats.size);
86// // if (read != 0)
87// // serial_trace("error reading file\n");
88// uint8_t* file = 0;
89
90// Elf64_Ehdr* ehdr = (Elf64_Ehdr*) file;
91// serial_trace("version : %d", ehdr->e_version);
92// serial_trace("entry : 0x%x", ehdr->e_entry);
93
94// Elf64_Phdr* phdr = (Elf64_Phdr*) ((uint64_t) ehdr + ehdr->e_phoff);
95// Elf64_Shdr* shdr = (Elf64_Shdr*) ((uint64_t) ehdr + ehdr->e_shoff);
96
97// page_t page_ = (page_t) PHYS2VIRT(VMM_PAGE);
98// serial_trace("page_ : 0x%x\n", page_);
99// paging_setup(page_);
100
101// uint8_t* str_tab =
102// (uint8_t*) ((uint64_t) ehdr + shdr[ehdr->e_shstrndx].sh_offset);
103// Elf64_Shdr* symtab = NULL;
104// for (int i = 0; i < ehdr->e_shnum; i++) {
105// if (strncmp((char*) (str_tab + shdr[i].sh_name), ".symtab", 7)
106// == 0) {
107// serial_trace("symtab found at %d\n", i);
108// symtab = &shdr[i];
109// break;
110// }
111// }
112
113// Elf64_Sym* symbols = (Elf64_Sym*) ((uint64_t) file + symtab->sh_offset);
114// // for (int i = 0; i < symtab->sh_size / sizeof (Elf64_Sym); i++)
115// // {
116// // serial_trace (
117// // "Function %s: Start: 0x%x, Size: %d bytes, end : 0x%x\n",
118// // str_tab + symbols[i].st_name, symbols[i].st_value,
119// // symbols[i].st_size, symbols[i].st_value +
120// // symbols[i].st_size);
121// // }
122
123// for (uint64_t i = 0; i < ehdr->e_phnum; i++) {
124// phdr = (Elf64_Phdr*) ((uint64_t) phdr + ehdr->e_phentsize);
125// }
126
127// serial_trace("\n");
128
129// for (uint64_t i = 0; i < ehdr->e_shnum; i++) {
130// char* name = (char*) (str_tab + shdr->sh_name);
131// if (strncmp(name, ".dynamic", 5) == 0) {
132// serial_trace("dynamic section found\n");
133
134// break;
135// }
136// serial_trace("shdr name : %s , ", name);
137// serial_trace("shdr addr : 0x%x\n", shdr->sh_addr);
138// shdr = (Elf64_Shdr*) ((uint64_t) shdr + ehdr->e_shentsize);
139// }
140
141// // program entry offset
142// uint64_t entry = ehdr->e_entry;
143// serial_trace("entry : 0x%x\n", entry);
144
145// // load program to memory
146// Elf64_Phdr* phdr2 = (Elf64_Phdr*) ((uint64_t) ehdr + ehdr->e_phoff);
147// Elf64_Dyn* dyn = 0;
148
149// int loop = 0;
150// uint64_t base = 0;
151// for (uint64_t i = 0; i < ehdr->e_phnum; i++) {
152// if (phdr2->p_type == PT_DYNAMIC) {
153// serial_trace("dynamic pheader found\n");
154// dyn = (Elf64_Dyn*) ((uint8_t*) (file
155// + phdr2->p_offset));
156// } else if (phdr2->p_type == PT_LOAD) {
157// void* a = (void*) (vxPhysBaseAlloc(
158// 1 + phdr2->p_memsz / 4096));
159// uintptr_t allignment_vadr = phdr2->p_vaddr & ~0xFFF;
160// uintptr_t offset_page =
161// phdr2->p_vaddr - allignment_vadr;
162
163// // if ((uint64_t)a % 0x1000 != 0) {
164// // serial_trace("ERROR: PADDRNOT ALIGNMENT AT
165// // 4KB\n");
166// // }
167// // if (phdr2->p_vaddr % 0x1000 != 0) {
168// // serial_trace("ERROR: VADDR NOT ALIGNMENT AT
169// // 4KB\n"); serial_trace("alignment vaddr : 0x%x\n",
170// // allignment_vadr);
171// // }
172// uint64_t round_up_size =
173// (phdr->p_memsz + 0xFFF) & ~0xFFF;
174
175// serial_trace("mapping 0x%x to 0x%x size %d until 0x%x "
176// "(real end 0x%x)\n",
177// allignment_vadr, a, phdr2->p_memsz,
178// allignment_vadr + phdr2->p_memsz,
179// allignment_vadr + 4096);
180
181// if (base == 0) {
182// base = phdr2->p_vaddr - phdr2->p_offset;
183// }
184
185// // chec apakah a aligned 4kb
186// // serial_trace("a : 0x%x\n", a);
187
188// for (uint64_t j = 0; j < phdr2->p_memsz; j++) {
189// *(uint8_t*) ((uint64_t) a + offset_page + j) =
190// *(uint8_t*) (file + phdr2->p_offset
191// + j);
192// }
193// vxMultipleMmap(page_, phdr2->p_vaddr,
194// VIRT2PHYS((uintptr_t) a),
195// round_up_size / 4096, 0b111);
196
197// paging_reload((page_t) VIRT2PHYS((uint64_t) page_));
198// serial_trace("mapped addr : 0x%x\n",
199// vaddr_to_paddr((page_t) ((uint64_t) page_),
200// phdr2->p_vaddr));
201// }
202// // phdr2 = (Elf64_Phdr *)((uint64_t)phdr2 + ehdr->e_phentsize);
203// }
204// serial_trace("base : 0x%x\n", base);
205// serial_trace("entry : 0x%x\n", entry);
206
207// // dnynamic linking part
208// uint8_t* init_func_addr = 0;
209// if (dyn != 0) {
210// uint64_t plt_relz = 0;
211// Elf64_Rela* plt_rela = 0;
212// uint8_t* strtab = NULL;
213// uint64_t dyn_needed = 0;
214// Elf64_Sym* symbols = 0;
215
216// for (int i = 0; dyn[i].d_tag != DT_NULL; i++) {
217// switch (dyn[i].d_tag) {
218// case DT_STRTAB:
219// strtab =
220// (uint8_t*) ((uint64_t) file
221// + dyn[i].d_un.d_ptr - base);
222// serial_trace("strtab : 0x%x\n", strtab);
223// break;
224
225// case DT_NEEDED:
226// dyn_needed = dyn[i].d_un.d_val;
227// break;
228
229// case DT_PLTRELSZ:
230// plt_relz =
231// dyn[i].d_un.d_val / sizeof(Elf64_Rela);
232// serial_trace("relsz : %d\n", plt_relz);
233// break;
234
235// case DT_PLTGOT:
236// serial_trace("pltgot : 0x%x\n",
237// dyn[i].d_un.d_ptr);
238// void* c = (void*) (vxPhysBaseAlloc(
239// 1
240// + plt_relz * sizeof(Elf64_Rela)
241// / 4096));
242// uintptr_t allignment_vadr =
243// dyn[i].d_un.d_ptr & ~0xFFF;
244
245// if ((uint64_t) c % 0x1000 != 0) {
246// serial_trace("ERROR: PADDRNOT "
247// "ALIGNMENT AT 4KB\n");
248// }
249// if (dyn[i].d_un.d_ptr % 0x1000 != 0) {
250// serial_trace("ERROR: VADDR NOT "
251// "ALIGNMENT AT 4KB\n");
252// }
253// uint64_t round_up_size =
254// (phdr->p_memsz + 0xFFF) & ~0xFFF;
255
256// vxMmap(page_, allignment_vadr,
257// VIRT2PHYS((uint64_t) c), 0b111);
258// // paging_reload(VIRT2PHYS(page_));
259// break;
260
261// case DT_JMPREL:
262// serial_trace("jmprel : 0x%x\n",
263// dyn[i].d_un.d_ptr);
264// plt_rela = (Elf64_Rela*) (file
265// + (dyn[i].d_un.d_ptr
266// - base));
267// break;
268
269// case DT_SYMTAB:
270// serial_trace("symtab : 0x%x\n",
271// dyn[i].d_un.d_ptr);
272// symbols = (Elf64_Sym*) ((uint64_t) file
273// + (dyn[i].d_un.d_ptr
274// - base));
275// break;
276
277// default:
278// break;
279// }
280// }
281
282// Elf64_Sym* lib_dynsym = 0;
283// uint8_t* dynstr = 0;
284// uint64_t lib_dynsym_size = 0;
285
286// // read shared library part
287// struct Library* lib = 0;
288// if (strtab && dyn_needed) {
289// serial_trace("strtab 0x%x neded %d\n", strtab,
290// dyn_needed);
291// const char* library_name =
292// (const char*) (strtab + dyn_needed);
293// serial_trace("needed : %s\n", library_name);
294// serial_trace("\n");
295
296// lib = library_load(library_name);
297// if (lib == 0) {
298// serial_trace("error loading library\n");
299// return -1;
300// }
301// Elf64_Ehdr* ehdr = (Elf64_Ehdr*) lib->entry;
302// // cek apakah ini shared library
303// if (ehdr->e_type == ET_DYN) {
304// serial_trace("ini adalah shared library\n");
305// }
306// Elf64_Phdr* phdr =
307// (Elf64_Phdr*) ((uint64_t) ehdr + ehdr->e_phoff);
308// Elf64_Shdr* shdr =
309// (Elf64_Shdr*) ((uint64_t) ehdr + ehdr->e_shoff);
310
311// uint8_t* lib_strtab =
312// (uint8_t*) ((uint64_t) ehdr
313// + shdr[ehdr->e_shstrndx].sh_offset);
314
315// // parse secton header pada library
316// for (uint64_t i = 0; i < ehdr->e_shnum; i++) {
317// char* name =
318// (char*) (lib_strtab + shdr->sh_name);
319// if (strncmp(name, ".dynsym", 7) == 0) {
320// serial_trace("dynamic symbol found\n");
321// serial_trace("size : %d\n",
322// shdr->sh_size);
323// lib_dynsym =
324// (Elf64_Sym*) (lib->entry
325// + shdr->sh_offset);
326// lib_dynsym_size = shdr->sh_size;
327// } else if (strncmp(name, ".dynstr", 7) == 0) {
328// serial_trace("dynamic string found\n");
329// dynstr = (uint8_t*) (lib->entry
330// + shdr->sh_offset);
331// }
332
333// // serial_trace ("shdr name : %s , ", name);
334// // serial_trace ("shdr addr : 0x%x\n",
335// // shdr->sh_addr);
336// shdr = (Elf64_Shdr*) ((uint64_t) shdr
337// + ehdr->e_shentsize);
338// }
339
340// // read .dynsym
341// if (lib_dynsym != 0) {
342// for (int i = 0;
343// i < lib_dynsym_size / sizeof(Elf64_Sym);
344// i++) {
345// serial_trace(
346// "Function %s: Start: 0x%x, "
347// "Size: %d bytes, end : 0x%x\n",
348// dynstr + lib_dynsym[i].st_name,
349// lib_dynsym[i].st_value,
350// lib_dynsym[i].st_size,
351// lib_dynsym[i].st_value
352// + lib_dynsym[i]
353// .st_size);
354// }
355// }
356
357// // read progra header
358// Elf64_Dyn* libdyn = 0;
359// for (uint64_t i = 0; i < ehdr->e_phnum; i++) {
360// if (phdr->p_type == PT_DYNAMIC) {
361// serial_trace("dynamic pheader found\n");
362// libdyn = (Elf64_Dyn*) ((
363// uint8_t*) (lib->entry
364// + phdr->p_offset));
365// } else if (phdr->p_type == PT_LOAD) {
366// void* a = (void*) (vxPhysBaseAlloc(
367// 1 + phdr->p_memsz / 4096));
368// uintptr_t allignment_vadr =
369// phdr->p_vaddr & ~0xFFF;
370// uintptr_t offset_page =
371// phdr->p_vaddr - allignment_vadr;
372
373// if ((uint64_t) a % 0x1000 != 0) {
374// serial_trace("ERROR: PADDRNOT "
375// "ALIGNMENT "
376// "AT 4KB\n");
377// }
378// if (phdr->p_vaddr % 0x1000 != 0) {
379// serial_trace(
380// "ERROR: VADDR NOT "
381// "ALIGNMENT AT 4KB\n");
382// }
383// uint64_t round_up_size =
384// (phdr->p_memsz + 0xFFF)
385// & ~0xFFF;
386// vxMultipleMmap(page_, allignment_vadr,
387// VIRT2PHYS((uint64_t) a),
388// (round_up_size / 4096),
389// 0b111);
390// // }
391// serial_trace("mapping 0x%x to "
392// "0x%x\n",
393// allignment_vadr,
394// VIRT2PHYS((uint64_t) a)
395// + offset_page);
396// // paging_reload(VIRT2PHYS((uint64_t)page_));
397// // serial_trace("mapped addr : 0x%x\n",
398// // vaddr_to_paddr(((uint64_t)page_),
399// // phdr->p_vaddr));
400
401// for (uint64_t j = 0; j < phdr->p_memsz;
402// j++) {
403// *(uint8_t*) ((uint64_t) a
404// + offset_page
405// + j) =
406// *(uint8_t*) ((uint64_t) lib
407// ->entry
408// + phdr->p_offset
409// + j);
410// }
411// }
412// serial_trace("phdr type : %d\n", phdr->p_type);
413
414// phdr = (Elf64_Phdr*) ((uint64_t) phdr
415// + ehdr->e_phentsize);
416// }
417
418// // paging_reload (page_);
419// // read dynamic section
420// if (libdyn != 0) {
421// for (int i = 0; libdyn[i].d_tag != DT_NULL;
422// i++) {
423// switch (libdyn[i].d_tag) {
424// case DT_INIT:
425// // case DT_INIT_ARRAY:
426// serial_trace(
427// "dt init : 0x%x\n",
428// libdyn[i].d_un.d_ptr);
429// init_func_addr =
430// (uint8_t*) (libdyn[i]
431// .d_un
432// .d_ptr);
433// // void (*init) ()
434// // = (void (*) ())lib->entry
435// // + libdyn[i].d_un.d_ptr;
436// // init ();
437// break;
438// default:
439// break;
440// }
441// }
442// }
443// }
444
445// paging_reload((page_t) VIRT2PHYS((uint64_t) page_));
446// // relocation
447// if (plt_rela != 0) {
448// for (int i = 0; i < plt_relz; i++) {
449// // void *a = (void *)(phys_base_alloc(1));
450// // paging_mmap(page_, plt_rela[i].r_offset,
451// // VIRT2PHYS((uint64_t)a), 0b111);
452// // paging_reload(VIRT2PHYS((uint64_t)page_));
453
454// serial_trace("relocation offset : 0x%x\n",
455// plt_rela[i].r_offset);
456// // serial_trace("mapped addr : 0x%x\n",
457// // vaddr_to_paddr(
458// // ((uint64_t)page_),
459// // plt_rela[i].r_offset));
460// serial_trace("relocation info : 0x%x\n",
461// plt_rela[i].r_info);
462// serial_trace("relocation addend : 0x%x\n",
463// plt_rela[i].r_addend);
464// serial_trace("relocation type : 0x%x\n",
465// Elf64_R_TYPE(plt_rela[i].r_info));
466// Elf64_Sym* sym = &symbols[Elf64_R_SYM(
467// plt_rela[i].r_info)];
468// char* sym_name =
469// (char*) (strtab + sym->st_name);
470// serial_trace("relocation symbol : %s\n",
471// sym_name);
472
473// // rellocation proccess
474// if (lib_dynsym != 0) {
475// for (int k = 0;
476// k < lib_dynsym_size
477// / sizeof(Elf64_Sym);
478// k++) {
479// const char* lib_dynsym_name =
480// (const char*) (dynstr
481// + lib_dynsym[k]
482// .st_name);
483// if (strncmp(lib_dynsym_name,
484// sym_name,
485// strlen(sym_name))
486// == 0) {
487// serial_trace(
488// "found symbol "
489// "%s\n",
490// lib_dynsym_name);
491// serial_trace(
492// "symbol value "
493// ": "
494// "0x%x\n",
495// lib_dynsym[k]
496// .st_value);
497// serial_trace(
498// "relocation "
499// "value "
500// ": "
501// "0x%x\n",
502// lib_dynsym[k].st_value
503// + plt_rela[i]
504// .r_addend);
505// serial_trace(
506// "mapped addr : "
507// "0x%x\n",
508// vaddr_to_paddr(
509// (page_t) ((
510// uint64_t) page_),
511// lib_dynsym[k].st_value
512// + plt_rela[i]
513// .r_addend));
514
515// serial_trace(
516// "ok 0x%x\n",
517// *(uint64_t*) (plt_rela[i]
518// .r_offset));
519// *(uint64_t*) (plt_rela[i]
520// .r_offset) =
521// (uint64_t) (lib_dynsym[k]
522// .st_value
523// + plt_rela[i]
524// .r_addend);
525
526// break;
527// }
528// }
529// }
530// }
531// }
532// }
533// serial_trace("init func addr : 0x%x\n", init_func_addr);
534// // signal to IDT that program is running
535// is_running_program = 1;
536
537// // TODO: stup correctly stack consider shared library
538
539// uintptr_t s = (uintptr_t) (vxPhysBaseAlloc(2049));
540// memset((void*) s, 0, 2049 * 4096);
541
542// char* argva[1] = {"a"};
543// char* envpa[1] = {"a"};
544// // setup_user_stack (s, 0, 0);
545// // mapping to 2GB
546// vxMultipleMmap(page_, 256 * GB, VIRT2PHYS((uint64_t) s), 2049, 0b111);
547
548// uint64_t argc = 0;
549// while (argv[argc])
550// argc++;
551
552// uint64_t aligned_stack = (uintptr_t) 256 * GB + 2048 * 0x1000;
553// uint64_t* stack_top = (uint64_t*) ((uintptr_t) s + 2048 * 0x1000);
554// aligned_stack =
555// setup_user_stack(argc, aligned_stack, stack_top, argv, envp);
556// // *()set returning address on stack
557// // *(--stack_top) = (uint64_t)0x0240000000;
558// // aligned_stack -= sizeof(uintptr_t);
559
560// serial_trace("aligned stack : 0x%x\n", aligned_stack);
561
562// struct program_paramater param = {
563// .argv = argv,
564// .envp = envp,
565// .argc = argc,
566// };
567// task_add(path, entry, TASK_READY, TASK_PRIORITY_MEDIUM,
568// (page_t) VIRT2PHYS(page_), aligned_stack, param);
569
570// return 1;
571// }