From dd850450cc970ea57414eb7a42b590fec1447e02 Mon Sep 17 00:00:00 2001 From: xwashere Date: Tue, 23 Apr 2024 13:30:26 -0400 Subject: [PATCH] [lcrash] ADD: Dynamic linker for cckernel --- lcrash/elf/elf.h | 69 ++++++++++++++++++++++++++++++++++- lcrash/lcrash.ld | 11 +++++- lcrash/setup/compressed/elf.c | 33 +++++++++++++++++ 3 files changed, 111 insertions(+), 2 deletions(-) diff --git a/lcrash/elf/elf.h b/lcrash/elf/elf.h index 0c9dd59..2030f9e 100644 --- a/lcrash/elf/elf.h +++ b/lcrash/elf/elf.h @@ -17,6 +17,24 @@ #define PT_PHDR 6 #define PT_TLS 7 +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 +#define SHT_FINI_ARRAY 15 +#define SHT_PREINIT_ARRAY 16 +#define SHT_GROUP 17 +#define SHT_SYMTAB_SHNDX 18 + struct [[gnu::packed]] Elf64_Ehdr { c8 e_ident[16]; u16 e_type; @@ -30,7 +48,7 @@ struct [[gnu::packed]] Elf64_Ehdr { u16 e_phentsize; u16 e_phnum; u16 e_shentsize; - u16 e_shentnum; + u16 e_shnum; u16 e_shstrndx; }; @@ -45,4 +63,53 @@ struct [[gnu::packed]] Elf64_Phdr { u64 p_align; }; +struct [[gnu::packed]] Elf64_Shdr { + u32 sh_name; + u32 sh_type; + u64 sh_flags; + u64 sh_addr; + u64 sh_offset; + u64 sh_size; + u32 sh_link; + u32 sh_info; + u64 sh_addralign; + u64 sh_entsize; +}; +#define ELF64_R_SYM(info) ((info)>>32); +#define ELF64_R_TYPE(info) ((u32)info) +#define ELF64_R_AMD64_NONE 0 +#define ELF64_R_AMD64_64 1 +#define ELF64_R_AMD64_PC32 2 +#define ELF64_R_AMD64_GOT32 3 +#define ELF64_R_AMD64_PLT32 4 +#define ELF64_R_AMD64_COPY 5 +#define ELF64_R_AMD64_GLOB_DAT 6 +#define ELF64_R_AMD64_JUMP_SLOT 7 +#define ELF64_R_AMD64_RELATIVE 8 +#define ELF64_R_AMD64_GOTPCREL 9 +#define ELF64_R_AMD64_32 10 +#define ELF64_R_AMD64_32S 11 +#define ELF64_R_AMD64_16 12 +#define ELF64_R_AMD64_PC16 13 +#define ELF64_R_AMD64_8 14 +#define ELF64_R_AMD64_PC8 15 +#define ELF64_R_AMD64_PC64 24 +#define ELF64_R_AMD64_GOTOFF64 25 +#define ELF64_R_AMD64_GOTPC32 26 +#define ELF64_R_AMD64_SIZE32 32 +#define ELF64_R_AMD64_SIZE64 33 +struct [[gnu::packed]] Elf64_Rela { + u64 r_offset; + u64 r_info; + s64 r_addend; +}; + +struct [[gnu::packed]] Elf64_Sym { + u32 st_name; + u8 st_info; + u8 st_other; + u16 st_shndx; + u64 st_value; + u64 st_size; +}; diff --git a/lcrash/lcrash.ld b/lcrash/lcrash.ld index ca8efe6..18a5622 100644 --- a/lcrash/lcrash.ld +++ b/lcrash/lcrash.ld @@ -5,6 +5,15 @@ ENTRY(entry64) SECTIONS { . = 0; + .dynsym : { *(.dynsym); } + + .rela.dyn : { + *(.rela.text); + *(.rela.rodata); + *(.rela.data .rela.data.*); + *(.rela.bss); + } + .text : { _text = .; *(.text); @@ -19,7 +28,7 @@ SECTIONS { .data : { _data = .; - *(.data); + *(.data .data.*); _edata = .; } diff --git a/lcrash/setup/compressed/elf.c b/lcrash/setup/compressed/elf.c index 7bf360d..d528e33 100644 --- a/lcrash/setup/compressed/elf.c +++ b/lcrash/setup/compressed/elf.c @@ -33,6 +33,39 @@ void ElfExecute(void* Binary, void* LoadAddr, struct boot_params* BootParams) { ProgramHeaders += ElfHeader->e_phentsize; } + // Dynamically link ourself + void* SectionHeaders = Binary + ElfHeader->e_shoff; + for (int i = 0; i < ElfHeader->e_shnum; i++) { + struct Elf64_Shdr* SectionHeader = (struct Elf64_Shdr*)SectionHeaders; + + // Find RELA segments + if (SectionHeader->sh_type == SHT_RELA) { + struct Elf64_Shdr* SymbolTable = (struct Elf64_Shdr*)(Binary + ElfHeader->e_shoff + ElfHeader->e_shentsize * SectionHeader->sh_link); + + void* RelocTab = Binary + SectionHeader->sh_offset; + void* SymblTab = Binary + SymbolTable->sh_offset; + + for (int RelocOffset = 0; RelocOffset < SectionHeader->sh_size; RelocOffset += SectionHeader->sh_entsize) { + struct Elf64_Rela* Reloc = RelocTab + RelocOffset; + [[maybe_unused]] struct Elf64_Sym* Symbol = SymblTab + SymbolTable->sh_entsize * ELF64_R_SYM(Reloc->r_info); + + void* Target = LoadAddr + Reloc->r_offset; + + switch (ELF64_R_TYPE(Reloc->r_info)) { + case ELF64_R_AMD64_RELATIVE: { + *((u64*)Target) = (u64)(LoadAddr + Reloc->r_addend); + break; + } + default: { + while (1) {} + } + } + } + } + + SectionHeaders += ElfHeader->e_shentsize; + } + // Collect entry point [[noreturn]] void fake_dont_call(struct boot_params*); // stupid hack typeof(fake_dont_call)* KernelEntry = LoadAddr + ElfHeader->e_entry;