diff --git a/src/ld_so/debug.rs b/src/ld_so/debug.rs new file mode 100644 index 0000000000000000000000000000000000000000..8780cc1f268f6b5e15170363834a2909e770f145 --- /dev/null +++ b/src/ld_so/debug.rs @@ -0,0 +1,117 @@ +use crate::{c_str::CString, platform::types::*}; +use alloc::boxed::Box; + +#[repr(C)] +pub enum RTLDState { + /// Mapping change is complete. + RT_CONSISTENT, + /// Beginning to add a new object. + RT_ADD, + /// Beginning to remove an object mapping. + RT_DELETE, +} + +/// Data structure for sharing debugging information from the +/// run-time dynamic linker for loaded ELF shared objects. +#[repr(C)] +pub struct RTLDDebug { + /// Version number for this protocol. + r_version: i32, + /// Head of the chain of loaded objects. + r_map: *mut LinkMap, + //struct link_map *r_map; + /// This is the address of a function internal to the run-time linker, + /// that will always be called when the linker begins to map in a + /// library or unmap it, and again when the mapping change is complete. + /// The debugger can set a breakpoint at this address if it wants to + /// notice shared object mapping changes. + pub r_brk: extern "C" fn(), + + /// This state value describes the mapping change taking place when + /// the `r_brk' address is called. + pub state: RTLDState, + + /// Base address the linker is loaded at. + pub r_ldbase: usize, +} + +impl RTLDDebug { + const NEW: Self = RTLDDebug { + r_version: 1, + r_map: 0 as *mut LinkMap, + r_brk: _dl_debug_state, + state: RTLDState::RT_CONSISTENT, + r_ldbase: 0, + }; + + pub fn insert(&mut self, l_addr: usize, name: &str, l_ld: usize) { + if self.r_map.is_null() { + self.r_map = LinkMap::new_with_args(l_addr, name, l_ld); + } else { + unsafe { (*self.r_map).add_object(l_addr, name, l_ld) }; + } + return; + } +} + +#[repr(C)] +struct LinkMap { + /* These members are part of the protocol with the debugger. + This is the same format used in SVR4. */ + /// Difference between the address in the ELF + /// file and the addresses in memory. + l_addr: usize, + /// Absolute file name object was found in. + l_name: *const c_char, + /// Dynamic section of the shared object. + l_ld: usize, + l_next: *mut LinkMap, + l_prev: *mut LinkMap, +} + +impl LinkMap { + fn new() -> *mut Self { + let map = Box::new(LinkMap { + l_addr: 0, + l_name: 0 as *const c_char, + l_ld: 0, + l_next: 0 as *mut LinkMap, + l_prev: 0 as *mut LinkMap, + }); + Box::into_raw(map) + } + + fn new_with_args(l_addr: usize, name: &str, l_ld: usize) -> *mut Self { + let map = LinkMap::new(); + unsafe { + (*map).l_addr = l_addr; + (*map).l_ld = l_ld; + let c_name = CString::new(name).unwrap(); + (*map).l_name = c_name.into_raw() as *const c_char; + } + map + } + + fn add_object(&mut self, l_addr: usize, name: &str, l_ld: usize) { + let node = LinkMap::new_with_args(l_addr, name, l_ld); + let mut last = self; + while !last.l_next.is_null() { + last = unsafe { last.l_next.as_mut() }.unwrap(); + } + unsafe { + (*node).l_prev = last; + (*last).l_next = node; + } + } +} + +/* + * Gdb may be looking for this fuction with that exact name and set + * break point there + */ +#[linkage = "weak"] +#[no_mangle] +pub extern "C" fn _dl_debug_state() {} + +#[no_mangle] +pub static mut _r_debug: RTLDDebug = RTLDDebug::NEW; diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs index cbc27567bc503bffb8645fd90e8d9b23cb72ceba..1d06541ac15dfc6fcbeaac4a7498d1e503fb0486 100644 --- a/src/ld_so/mod.rs +++ b/src/ld_so/mod.rs @@ -5,10 +5,10 @@ use crate::start::Stack; pub const PAGE_SIZE: usize = 4096; +pub mod debug; pub mod linker; pub mod start; pub mod tcb; - pub fn static_init(sp: &'static Stack) { let mut phdr_opt = None; let mut phent_opt = None;