aboutsummaryrefslogtreecommitdiff
path: root/vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
committerValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
commit1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch)
tree7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs
parent5ecd8cf2cba827454317368b68571df0d13d7842 (diff)
downloadfparkan-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.rs71
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
+}