diff options
| author | Ada Christine <adachristine18@gmail.com> | 2021-12-19 01:16:51 +0000 |
|---|---|---|
| committer | Ada Christine <adachristine18@gmail.com> | 2021-12-19 01:16:51 +0000 |
| commit | bff63a4337eb3388617d230970c5eb2684d6a215 (patch) | |
| tree | f40891f45918b23dac0f31888142136434c7fc8c /lib | |
| parent | d5f485a4f6801f58cbb2bc9d8e80c955c79ff044 (diff) | |
i don't know what i'm doing anymore
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/component.ld | 75 | ||||
| -rw-r--r-- | lib/elf.c | 106 | ||||
| -rw-r--r-- | lib/elf64.c | 45 | ||||
| -rw-r--r-- | lib/entry_x86_64.S | 18 | ||||
| -rw-r--r-- | lib/reloc_x86_64.c | 69 |
5 files changed, 207 insertions, 106 deletions
diff --git a/lib/component.ld b/lib/component.ld new file mode 100644 index 0000000..3a48ae8 --- /dev/null +++ b/lib/component.ld @@ -0,0 +1,75 @@ +ENTRY(kc_entry) + +SECTIONS +{ + PROVIDE(kc_image_base = .); + + . = sizeof_headers; + + .rel : + { + *(.rel) + *(.rel.*) + } + + .rela : + { + *(.rel) + *(.rela.*) + } + + .hash : + { + *(.hash) + } + + .dynsym : + { + *(.dynsym) + } + + .dynstr : + { + *(.dynstr) + } + + .text : ALIGN(4K) + { + PROVIDE(kc_text_begin = .); + *(.text.start) + *(.text) + . = ALIGN(4K); + PROVIDE(kc_text_end = .); + } =0xcc + + .dynamic : ALIGN(4K) + { + *(.dynamic) + } + + .data : + { + PROVIDE(kc_data_begin = .); + *(.rodata) + *(.data) + } + + .data.rel : + { + *(.data.rel) + *(.data.rel.*) + } + + .bss : + { + *(.bss) + PROVIDE(kc_data_end = .); + } + + /DISCARD/ : + { + *(.eh_frame) + *(.comment) + } +} + diff --git a/lib/elf.c b/lib/elf.c deleted file mode 100644 index 551a5a5..0000000 --- a/lib/elf.c +++ /dev/null @@ -1,106 +0,0 @@ -#include "elf.h" - -bool elf64_validate(Elf64_Ehdr *ehdr, unsigned type, unsigned machine) -{ - if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || - ehdr->e_ident[EI_MAG1] != ELFMAG1 || - ehdr->e_ident[EI_MAG2] != ELFMAG2 || - ehdr->e_ident[EI_MAG3] != ELFMAG3 || - ehdr->e_ident[EI_CLASS] != ELFCLASS64 || - ehdr->e_ident[EI_DATA] != ELFDATA2LSB || - ehdr->e_ident[EI_VERSION] != EV_CURRENT || - ehdr->e_machine != machine || - ehdr->e_type != type) - { - return false; - } - - return true; -} - -size_t elf64_size(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs) -{ - size_t size = 0; - - for (int i = 0; i < ehdr->e_phnum; i++) - { - if (phdrs[i].p_type != PT_LOAD) - { - continue; - } - - if (phdrs[i].p_paddr + phdrs[i].p_memsz > size) - { - size = phdrs[i].p_paddr + phdrs[i].p_memsz; - if (phdrs[i].p_align > 1) - { - size = (size + phdrs[i].p_align - 1) & - ~(phdrs[i].p_align - 1); - } - } - } - - return size; -} - -void elf64_reloc(Elf64_Ehdr *ehdr) -{ - // locate the dynamic segment - Elf64_Phdr *phdrs = (Elf64_Phdr *)(ehdr->e_phoff + (uintptr_t)ehdr); - Elf64_Dyn *dyn = NULL; - Elf64_Rela *rela = NULL; - size_t rela_size; - int rela_count; - - for (int i = 0; i < ehdr->e_phnum; i++) - { - if (phdrs[i].p_type != PT_DYNAMIC) continue; - - dyn = (Elf64_Dyn *)(phdrs[i].p_offset + (uintptr_t)ehdr); - } - - // parse the dynamic segment - while (dyn->d_tag != DT_NULL) - { - switch (dyn->d_tag) - { - case DT_RELA: - rela = (Elf64_Rela *)(dyn->d_ptr + (uintptr_t)ehdr); - break; - case DT_RELASZ: - rela_size = dyn->d_val; - break; - case DT_RELAENT: - rela_count = rela_size / dyn->d_val; - break; - default: - break; - } - dyn++; - } - - // perform the actual relocations - - for (int i; i < rela_count; i++) - { - union - { - Elf_Byte word8; - Elf64_Half word16; - Elf64_Word word32; - Elf64_Xword word64; - } - *reloc_ptr = NULL; - - switch (ELF64_R_TYPE(rela[i].r_info)) - { - case R_AMD64_RELATIVE: - reloc_ptr = (void *)(rela[i].r_offset + (uintptr_t)ehdr); - reloc_ptr->word64 = (rela[i].r_addend + (uintptr_t)ehdr); - break; - default: - break; - } - } -} - diff --git a/lib/elf64.c b/lib/elf64.c new file mode 100644 index 0000000..2dee395 --- /dev/null +++ b/lib/elf64.c @@ -0,0 +1,45 @@ +#include "elf.h" + +bool elf64_validate(Elf64_Ehdr *ehdr, unsigned type, unsigned machine) +{ + if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || + ehdr->e_ident[EI_MAG1] != ELFMAG1 || + ehdr->e_ident[EI_MAG2] != ELFMAG2 || + ehdr->e_ident[EI_MAG3] != ELFMAG3 || + ehdr->e_ident[EI_CLASS] != ELFCLASS64 || + ehdr->e_ident[EI_DATA] != ELFDATA2LSB || + ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_machine != machine || + ehdr->e_type != type) + { + return false; + } + + return true; +} + +size_t elf64_size(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs) +{ + size_t size = 0; + + for (int i = 0; i < ehdr->e_phnum; i++) + { + if (phdrs[i].p_type != PT_LOAD) + { + continue; + } + + if (phdrs[i].p_offset + phdrs[i].p_memsz > size) + { + size = phdrs[i].p_offset + phdrs[i].p_memsz; + if (phdrs[i].p_align > 1) + { + size = (size + phdrs[i].p_align - 1) & + ~(phdrs[i].p_align - 1); + } + } + } + + return size; +} + diff --git a/lib/entry_x86_64.S b/lib/entry_x86_64.S new file mode 100644 index 0000000..231953a --- /dev/null +++ b/lib/entry_x86_64.S @@ -0,0 +1,18 @@ +.section .text.start +.extern kc_reloc +.extern kc_main +.extern _DYNAMIC +.extern kc_image_base + +.global kc_entry +.type kc_entry, @function +kc_entry: + push %rdi + lea _DYNAMIC(%rip), %rdi + lea kc_image_base(%rip), %rsi + call kc_reloc + pop %rdi + call kc_main + ret +.size kc_entry, . - kc_entry + diff --git a/lib/reloc_x86_64.c b/lib/reloc_x86_64.c new file mode 100644 index 0000000..0204700 --- /dev/null +++ b/lib/reloc_x86_64.c @@ -0,0 +1,69 @@ +#include <kernel/component.h> + +#include <elf/elf64.h> + +#include <stddef.h> + +#define STARTCODE __attribute__((section(".text.start"))) + +STARTCODE +static void do_rela(Elf64_Rela *rela, void *base) +{ + union + { + Elf_Byte word8; + Elf64_Half word16; + Elf64_Word word32; + Elf64_Xword word64; + } + *fixup; + + switch (ELF64_R_TYPE(rela->r_info)) + { + case R_AMD64_RELATIVE: + fixup = (void *)(rela->r_offset + (uintptr_t)base); + fixup->word64 = (rela->r_addend + (uintptr_t)base); + break; + default: + break; + } +} + +STARTCODE +void kc_reloc(Elf64_Dyn *dyn, void *base) +{ + struct + { + Elf64_Rela *entries; + size_t *size; + size_t *entsize; + } + rela = {NULL, NULL, NULL}; + + // parse the dynamic segment + while (dyn && dyn++->d_tag != DT_NULL) + { + switch (dyn->d_tag) + { + case DT_RELA: + rela.entries = (Elf64_Rela *)(dyn->d_ptr + (uintptr_t)base); + break; + case DT_RELASZ: + rela.size = &dyn->d_val; + break; + case DT_RELAENT: + rela.entsize = &dyn->d_val; + break; + default: + break; + } + } + + // perform the actual relocation + + for (size_t i = 0; rela.entries && (i < *rela.size / *rela.entsize); i++) + { + do_rela(&rela.entries[i], base); + } +} + |
