diff options
author | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
---|---|---|
committer | Valentin Popov <valentin@popov.link> | 2024-01-08 00:21:28 +0300 |
commit | 1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch) | |
tree | 7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs | |
parent | 5ecd8cf2cba827454317368b68571df0d13d7842 (diff) | |
download | fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip |
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs')
-rw-r--r-- | vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs b/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs new file mode 100644 index 0000000..9f0304c --- /dev/null +++ b/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs @@ -0,0 +1,71 @@ +// Other Unix (e.g. Linux) platforms use ELF as an object file format +// and typically implement an API called `dl_iterate_phdr` to load +// native libraries. + +use super::mystd::borrow::ToOwned; +use super::mystd::env; +use super::mystd::ffi::{CStr, OsStr}; +use super::mystd::os::unix::prelude::*; +use super::{Library, LibrarySegment, OsString, Vec}; +use core::slice; + +pub(super) fn native_libraries() -> Vec<Library> { + let mut ret = Vec::new(); + unsafe { + libc::dl_iterate_phdr(Some(callback), &mut ret as *mut Vec<_> as *mut _); + } + return ret; +} + +fn infer_current_exe(base_addr: usize) -> OsString { + if let Ok(entries) = super::parse_running_mmaps::parse_maps() { + let opt_path = entries + .iter() + .find(|e| e.ip_matches(base_addr) && e.pathname().len() > 0) + .map(|e| e.pathname()) + .cloned(); + if let Some(path) = opt_path { + return path; + } + } + env::current_exe().map(|e| e.into()).unwrap_or_default() +} + +// `info` should be a valid pointers. +// `vec` should be a valid pointer to a `std::Vec`. +unsafe extern "C" fn callback( + info: *mut libc::dl_phdr_info, + _size: libc::size_t, + vec: *mut libc::c_void, +) -> libc::c_int { + let info = &*info; + let libs = &mut *(vec as *mut Vec<Library>); + let is_main_prog = info.dlpi_name.is_null() || *info.dlpi_name == 0; + let name = if is_main_prog { + // The man page for dl_iterate_phdr says that the first object visited by + // callback is the main program; so the first time we encounter a + // nameless entry, we can assume its the main program and try to infer its path. + // After that, we cannot continue that assumption, and we use an empty string. + if libs.is_empty() { + infer_current_exe(info.dlpi_addr as usize) + } else { + OsString::new() + } + } else { + let bytes = CStr::from_ptr(info.dlpi_name).to_bytes(); + OsStr::from_bytes(bytes).to_owned() + }; + let headers = slice::from_raw_parts(info.dlpi_phdr, info.dlpi_phnum as usize); + libs.push(Library { + name, + segments: headers + .iter() + .map(|header| LibrarySegment { + len: (*header).p_memsz as usize, + stated_virtual_memory_address: (*header).p_vaddr as usize, + }) + .collect(), + bias: info.dlpi_addr as usize, + }); + 0 +} |