Skip to content

Commit

Permalink
feat: implement ELF parser
Browse files Browse the repository at this point in the history
  • Loading branch information
alanjian85 committed Jul 24, 2024
1 parent f8e35ae commit 44883aa
Show file tree
Hide file tree
Showing 7 changed files with 32,812 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ add_executable(karg
src/drivers/plic.c
src/drivers/tty.c
src/drivers/uart.c
src/elf.c
src/errno.c
src/init.c
src/intr.c
src/kmain.c
src/mm/kalloc.c
Expand Down
3 changes: 3 additions & 0 deletions include/elf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

extern void *elf_entry;
5 changes: 5 additions & 0 deletions include/init.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include <types.h>

extern const u8 INIT_ELF[];
5 changes: 2 additions & 3 deletions include/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ typedef struct list_node {
struct list_node *prev, *next;
} list_node_t;

#define list_head_init(name) \
{ &name, &name }
#define list_head_init(name) {&name, &name}

static inline void list_init_head(list_node_t *head) {
head->prev = head;
Expand All @@ -32,7 +31,7 @@ static inline bool list_is_back(list_node_t *head, list_node_t *node) {
}

#define list_entry(node, type, member) \
((type *) ((u8 *) (node) -offsetof(type, member)))
((type *) ((u8 *) (node) - offsetof(type, member)))
#define list_first_entry(head, type, member) \
list_entry(list_front(head), type, member)
#define list_last_entry(head, type, member) \
Expand Down
102 changes: 102 additions & 0 deletions src/elf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#include <errno.h>
#include <init.h>
#include <module/init.h>
#include <module/log.h>
#include <module/module.h>
#include <utils/mem.h>

MODULE_NAME("elf");

typedef struct {
u8 ident[16];
u16 type;
u16 machine;
u32 version;
usize entry;
usize phoff;
usize shoff;
u32 flags;
u16 ehsize;
u16 phentsize;
u16 phnum;
u16 shentsize;
u16 shnum;
u16 shstrndx;
} elf_hdr_t;

typedef struct {
u32 type;
u32 flags;
usize offset;
usize vaddr;
usize paddr;
usize filesz;
usize memsz;
usize align;
} prog_hdr_t;

enum {
EI_MAG0,
EI_MAG1,
EI_MAG2,
EI_MAG3,
EI_CLASS,
EI_DATA,
EI_VERSION,
};

enum {
PT_LOAD = 0x00000001,
};

void *elf_entry;

static i32 check_ident(const u8 *ident) {
if (ident[EI_MAG0] != 0x7F)
return false;
if (ident[EI_MAG1] != 'E')
return false;
if (ident[EI_MAG2] != 'L')
return false;
if (ident[EI_MAG3] != 'F')
return false;
return true;
}

static i32 check_compat(const u8 *ident) {
if (ident[EI_CLASS] != 2)
return false;
if (ident[EI_DATA] != 1)
return false;
if (ident[EI_VERSION] != 1)
return false;
return true;
}

static i32 init(void) {
const elf_hdr_t *elf_hdr = (const elf_hdr_t *) INIT_ELF;
elf_entry = (void *) elf_hdr->entry;

if (!check_ident(elf_hdr->ident))
return -EACCES;

if (!check_compat(elf_hdr->ident) || elf_hdr->type != 2)
return -EINVAL;

const prog_hdr_t *prog_hdrs =
(const prog_hdr_t *) (INIT_ELF + elf_hdr->phoff);
for (u16 i = 0; i < elf_hdr->phnum; i++) {
const prog_hdr_t *prog_hdr = prog_hdrs + i;
if (prog_hdr->type != PT_LOAD)
continue;

const void *src = INIT_ELF + prog_hdr->offset;
void *dst = (void *) prog_hdr->paddr;
mem_set(dst, 0x00, prog_hdr->memsz);
mem_copy(dst, src, prog_hdr->filesz);
}

return 0;
}

module_post_init(init);
32,696 changes: 32,696 additions & 0 deletions src/init.c

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions src/kmain.c
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
#include <elf.h>
#include <errno.h>
#include <module/init.h>
#include <module/log.h>
#include <module/module.h>
#include <sched.h>

void init(void);

MODULE_NAME("kmain");

static proc_t init_proc;

[[noreturn]] void kmain(void) {
init_modules();
i32 res = proc_init(&init_proc, init, 0, nullptr, 0, nullptr);
i32 res = proc_init(&init_proc, elf_entry, 0, nullptr, 0, nullptr);
if (res < 0)
log_panic("errno %s is returned when initializing init process",
errno_name(-res));
Expand Down

0 comments on commit 44883aa

Please sign in to comment.