Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for illumos systems #416

Merged
merged 1 commit into from
Apr 16, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions src/symbolize/gimli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ cfg_if::cfg_if! {
target_os = "macos",
target_os = "openbsd",
target_os = "solaris",
target_os = "illumos",
))] {
#[path = "gimli/mmap_unix.rs"]
mod mmap;
Expand Down Expand Up @@ -359,6 +360,110 @@ cfg_if::cfg_if! {
bias: slide,
})
}
} else if #[cfg(target_os = "illumos")] {
use mystd::os::unix::prelude::*;
use mystd::ffi::{OsStr, CStr};
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>;

mod elf;
use self::elf::Object;

#[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;
}

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 = std::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
}
} else if #[cfg(all(
any(
target_os = "linux",
Expand Down