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
// }
kernel
procc
spawn.c
Generated on Sat May 30 2026 11:09:57 for Voxia OS by
1.13.2