diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-17 13:44:55 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-04-17 14:10:42 -0400 |
commit | f8529d09bf1555c2dda61f5841b7ad4f42ce9715 (patch) | |
tree | 16e0cdede45741e945e663f72697665074b2b077 /kernel/mboot | |
parent | fmt (diff) | |
download | comus-f8529d09bf1555c2dda61f5841b7ad4f42ce9715.tar.gz comus-f8529d09bf1555c2dda61f5841b7ad4f42ce9715.tar.bz2 comus-f8529d09bf1555c2dda61f5841b7ad4f42ce9715.zip |
elf sym loading
Diffstat (limited to 'kernel/mboot')
-rw-r--r-- | kernel/mboot/elf.c | 77 | ||||
-rw-r--r-- | kernel/mboot/mboot.c | 7 | ||||
-rw-r--r-- | kernel/mboot/mmap.c | 2 |
3 files changed, 82 insertions, 4 deletions
diff --git a/kernel/mboot/elf.c b/kernel/mboot/elf.c new file mode 100644 index 0000000..88b61a7 --- /dev/null +++ b/kernel/mboot/elf.c @@ -0,0 +1,77 @@ +#include "lib/kio.h" +#include <lib.h> +#include <elf.h> +#include <comus/mboot.h> + +#include "mboot.h" + +#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9 + +struct multiboot_tag_elf_sections { + uint32_t type; + uint32_t size; + uint32_t num; + uint32_t entsize; + uint32_t shndx; + Elf64_Shdr sections[]; +}; + +static struct multiboot_tag_elf_sections *elf = NULL; +static Elf64_Shdr *symtab = NULL; +static Elf64_Shdr *symstrtab = NULL; + +static Elf64_Shdr *mboot_get_elf_sec(uint32_t sh_type) +{ + for (uint32_t i = 0; i < elf->num; i++) { + Elf64_Shdr *ent = &elf->sections[i]; + if (ent->sh_type == sh_type) + return ent; + } + + return NULL; +} + +static int mboot_load_elf(void) +{ + void *tag = locate_mboot_table(MULTIBOOT_TAG_TYPE_ELF_SECTIONS); + if (tag == NULL) + return 1; + + // found elf sections + elf = (struct multiboot_tag_elf_sections *)tag; + + // load symtab + if ((symtab = mboot_get_elf_sec(SHT_SYMTAB)) == NULL) + return 1; + + // load strsymtab + if ((symstrtab = mboot_get_elf_sec(symtab->sh_link)) == NULL) + return 1; + + return 0; +} + +const char *mboot_get_elf_sym(uint64_t addr) +{ + if (symstrtab == NULL) + if (mboot_load_elf()) + return NULL; + + // walk symbol table + Elf64_Sym *syms = (Elf64_Sym *)symtab->sh_addr; + Elf64_Sym *best = NULL; + for (uint32_t i = 0; i < symtab->sh_size / symtab->sh_entsize; i++) { + Elf64_Sym *sym = &syms[i]; + if (sym->st_value < addr) + continue; + if (best == NULL || (best->st_value < sym->st_value)) + best = sym; + } + + if (best != NULL) { + char *buf = (char *)symstrtab->sh_addr; + return &buf[best->st_name]; + } + + return "???"; +} diff --git a/kernel/mboot/mboot.c b/kernel/mboot/mboot.c index e10f33c..949337d 100644 --- a/kernel/mboot/mboot.c +++ b/kernel/mboot/mboot.c @@ -3,7 +3,7 @@ #include "mboot.h" -static volatile void *mboot; +static volatile void *mboot = NULL; void mboot_init(long magic, volatile void *ptr) { @@ -14,9 +14,12 @@ void mboot_init(long magic, volatile void *ptr) void *locate_mboot_table(uint32_t type) { + if (mboot == NULL) + return NULL; + struct multiboot *info = (struct multiboot *)mboot; - const char *mboot_end = ((char *)info) + info->total_size; + const char *mboot_end = ((char *)info) + info->total_size; char *tag_ptr = info->tags; while (tag_ptr < mboot_end) { diff --git a/kernel/mboot/mmap.c b/kernel/mboot/mmap.c index 8959c49..e0963ca 100644 --- a/kernel/mboot/mmap.c +++ b/kernel/mboot/mmap.c @@ -30,11 +30,9 @@ int mboot_get_mmap(struct memory_map *res) int idx = 0; uintptr_t i = (uintptr_t)mmap->entries; - char buf[20]; for (; i < (uintptr_t)mmap->entries + mmap->size; i += mmap->entry_size, idx++) { struct multiboot_mmap_entry *seg = (struct multiboot_mmap_entry *)i; - const char *type = NULL; res->entries[idx].addr = seg->addr; res->entries[idx].len = seg->len; res->entries[idx].type = seg->type; |