summaryrefslogtreecommitdiffstats
path: root/library/backtrace/src/symbolize/gimli/libs_illumos.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/backtrace/src/symbolize/gimli/libs_illumos.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/library/backtrace/src/symbolize/gimli/libs_illumos.rs b/library/backtrace/src/symbolize/gimli/libs_illumos.rs
new file mode 100644
index 000000000..e64975e0c
--- /dev/null
+++ b/library/backtrace/src/symbolize/gimli/libs_illumos.rs
@@ -0,0 +1,99 @@
+use super::mystd::borrow::ToOwned;
+use super::mystd::ffi::{CStr, OsStr};
+use super::mystd::os::unix::prelude::*;
+use super::{Library, LibrarySegment, Vec};
+use core::mem;
+use object::NativeEndian;
+
+#[cfg(target_pointer_width = "64")]
+use object::elf::{FileHeader64 as FileHeader, ProgramHeader64 as ProgramHeader};
+
+type EHdr = FileHeader<NativeEndian>;
+type PHdr = ProgramHeader<NativeEndian>;
+
+#[repr(C)]
+struct LinkMap {
+ l_addr: libc::c_ulong,
+ l_name: *const libc::c_char,
+ l_ld: *const libc::c_void,
+ l_next: *const LinkMap,
+ l_prev: *const LinkMap,
+ l_refname: *const libc::c_char,
+}
+
+const RTLD_SELF: *const libc::c_void = -3isize as *const libc::c_void;
+const RTLD_DI_LINKMAP: libc::c_int = 2;
+
+extern "C" {
+ fn dlinfo(
+ handle: *const libc::c_void,
+ request: libc::c_int,
+ p: *mut libc::c_void,
+ ) -> libc::c_int;
+}
+
+pub(super) fn native_libraries() -> Vec<Library> {
+ let mut libs = Vec::new();
+
+ // Request the current link map from the runtime linker:
+ let map = unsafe {
+ let mut map: *const LinkMap = mem::zeroed();
+ if dlinfo(
+ RTLD_SELF,
+ RTLD_DI_LINKMAP,
+ (&mut map) as *mut *const LinkMap as *mut libc::c_void,
+ ) != 0
+ {
+ return libs;
+ }
+ map
+ };
+
+ // Each entry in the link map represents a loaded object:
+ let mut l = map;
+ while !l.is_null() {
+ // Fetch the fully qualified path of the loaded object:
+ let bytes = unsafe { CStr::from_ptr((*l).l_name) }.to_bytes();
+ let name = OsStr::from_bytes(bytes).to_owned();
+
+ // The base address of the object loaded into memory:
+ let addr = unsafe { (*l).l_addr };
+
+ // Use the ELF header for this object to locate the program
+ // header:
+ let e: *const EHdr = unsafe { (*l).l_addr as *const EHdr };
+ let phoff = unsafe { (*e).e_phoff }.get(NativeEndian);
+ let phnum = unsafe { (*e).e_phnum }.get(NativeEndian);
+ let etype = unsafe { (*e).e_type }.get(NativeEndian);
+
+ let phdr: *const PHdr = (addr + phoff) as *const PHdr;
+ let phdr = unsafe { core::slice::from_raw_parts(phdr, phnum as usize) };
+
+ libs.push(Library {
+ name,
+ segments: phdr
+ .iter()
+ .map(|p| {
+ let memsz = p.p_memsz.get(NativeEndian);
+ let vaddr = p.p_vaddr.get(NativeEndian);
+ LibrarySegment {
+ len: memsz as usize,
+ stated_virtual_memory_address: vaddr as usize,
+ }
+ })
+ .collect(),
+ bias: if etype == object::elf::ET_EXEC {
+ // Program header addresses for the base executable are
+ // already absolute.
+ 0
+ } else {
+ // Other addresses are relative to the object base.
+ addr as usize
+ },
+ });
+
+ l = unsafe { (*l).l_next };
+ }
+
+ libs
+}