diff --git a/userspace/dyn-loader/src/error.rs b/userspace/dyn-loader/src/error.rs index b539027a..56194205 100644 --- a/userspace/dyn-loader/src/error.rs +++ b/userspace/dyn-loader/src/error.rs @@ -8,6 +8,8 @@ pub enum Error { ElfParse(#[from] elf::ParseError), #[error("Memory mapping error: {0:?}")] MemoryMap(yggdrasil_rt::Error), + #[error("Unsupported object data")] + UnhandledObject, #[error("Object not loaded yet")] NotLoaded, #[error("Unsupported ELF type: {0:#06x}")] diff --git a/userspace/dyn-loader/src/main.rs b/userspace/dyn-loader/src/main.rs index 89ee6aa6..deabdec7 100644 --- a/userspace/dyn-loader/src/main.rs +++ b/userspace/dyn-loader/src/main.rs @@ -129,9 +129,8 @@ unsafe fn enter(entry: extern "C" fn(usize), argument: usize) -> ! { } #[cfg(any(target_arch = "riscv64", rust_analyzer))] { - let _ = entry; - let _ = argument; - todo!() + entry(argument); + unreachable!() } #[cfg(any(target_arch = "aarch64", target_arch = "x86_64", rust_analyzer))] { diff --git a/userspace/dyn-loader/src/object.rs b/userspace/dyn-loader/src/object.rs index 3205fa01..0d452d88 100644 --- a/userspace/dyn-loader/src/object.rs +++ b/userspace/dyn-loader/src/object.rs @@ -12,10 +12,7 @@ use std::{ use elf::{ abi::{ - DF_1_PIE, DT_FINI, DT_FINI_ARRAY, DT_FINI_ARRAYSZ, DT_FLAGS_1, DT_INIT, DT_INIT_ARRAY, - DT_INIT_ARRAYSZ, DT_NEEDED, DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ, ET_DYN, ET_EXEC, - PT_DYNAMIC, PT_GNU_EH_FRAME, PT_GNU_RELRO, PT_GNU_STACK, PT_INTERP, PT_LOAD, PT_NOTE, - PT_NULL, PT_PHDR, PT_TLS, SHN_UNDEF, SHT_REL, SHT_RELA, STB_GLOBAL, STB_LOCAL, STB_WEAK, + DF_1_PIE, DT_FINI, DT_FINI_ARRAY, DT_FINI_ARRAYSZ, DT_FLAGS_1, DT_INIT, DT_INIT_ARRAY, DT_INIT_ARRAYSZ, DT_NEEDED, DT_PREINIT_ARRAY, DT_PREINIT_ARRAYSZ, ET_DYN, ET_EXEC, PT_DYNAMIC, PT_GNU_EH_FRAME, PT_GNU_RELRO, PT_GNU_STACK, PT_INTERP, PT_LOAD, PT_NOTE, PT_NULL, PT_PHDR, PT_RISCV_ATTRIBUTES, PT_TLS, SHN_UNDEF, SHT_REL, SHT_RELA, STB_GLOBAL, STB_LOCAL, STB_WEAK }, endian::AnyEndian, parse::ParsingIterator, @@ -289,10 +286,15 @@ impl Object { } // Handled separately PT_TLS => (), + // TODO handle .riscv.attributes and extract float ABI + PT_RISCV_ATTRIBUTES => (), // TODO handle GNU_STACK PT_DYNAMIC | PT_GNU_RELRO | PT_GNU_STACK | PT_INTERP | PT_PHDR | PT_GNU_EH_FRAME | PT_NOTE => (), - _ => todo!("Unhandled segment type"), + _ => { + log::error!("Unhandled segment type: {:#x}", segment.p_type); + return Err(Error::UnhandledObject); + }, } } diff --git a/userspace/dyn-loader/src/relocation/riscv64.rs b/userspace/dyn-loader/src/relocation/riscv64.rs index 4f004d1a..780ec7b8 100644 --- a/userspace/dyn-loader/src/relocation/riscv64.rs +++ b/userspace/dyn-loader/src/relocation/riscv64.rs @@ -1,4 +1,7 @@ -use elf::relocation::{Rel, Rela}; +use elf::{ + abi::{R_RISCV_64, R_RISCV_JUMP_SLOT, R_RISCV_RELATIVE, R_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPREL64}, + relocation::{Rel, Rela}, +}; use crate::{error::Error, object::ResolvedSymbol, state::State}; @@ -14,7 +17,7 @@ impl Relocation for Rel { _symbol: &ResolvedSymbol, _load_base: usize, ) -> Result, Error> { - todo!() + Err(Error::UnhandledObject) } } @@ -23,11 +26,48 @@ impl Relocation for Rela { fn resolve( &self, - _state: &State, - _name: &str, - _symbol: &ResolvedSymbol, - _load_base: usize, + state: &State, + name: &str, + symbol: &ResolvedSymbol, + load_base: usize, ) -> Result, Error> { - todo!() + match *symbol { + ResolvedSymbol::Tls(tls) => match self.r_type { + R_RISCV_TLS_DTPMOD64 => Ok(Some(RelaValue::QWord(tls.module_id as _))), + R_RISCV_TLS_DTPREL64 => Ok(Some(RelaValue::QWord(tls.offset as _))), + _ => { + log::error!( + "Unhandled riscv64 relocation against TLS symbol: {:#x}", + self.r_type + ); + Err(Error::UnhandledObject) + } + }, + ResolvedSymbol::Null(object_id) => match self.r_type { + R_RISCV_TLS_DTPMOD64 => Ok(Some(RelaValue::QWord((object_id + 1) as _))), + R_RISCV_RELATIVE => Ok(Some(RelaValue::QWord(load_base as i64 + self.r_addend))), + _ => { + log::error!( + "Unhandled riscv64 relocation against NULL: {:#x}", + self.r_type + ); + Err(Error::UnhandledObject) + } + }, + _ => { + let s = symbol.value(); + if s == 0 { + todo!() + } + match self.r_type { + R_RISCV_64 => Ok(Some(RelaValue::QWord(s + self.r_addend))), + R_RISCV_JUMP_SLOT => Ok(Some(RelaValue::QWord(s))), + _ => { + log::error!("Unhandled riscv64 relocation: {:#x}", self.r_type); + Err(Error::UnhandledObject) + } + } + } + } } }