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;