]> git.proxmox.com Git - rustc.git/blob - vendor/backtrace/src/symbolize/gimli/libs_dl_iterate_phdr.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / vendor / backtrace / src / symbolize / gimli / libs_dl_iterate_phdr.rs
1 // Other Unix (e.g. Linux) platforms use ELF as an object file format
2 // and typically implement an API called `dl_iterate_phdr` to load
3 // native libraries.
4
5 use super::mystd::borrow::ToOwned;
6 use super::mystd::env;
7 use super::mystd::ffi::{CStr, OsStr};
8 use super::mystd::os::unix::prelude::*;
9 use super::{Library, LibrarySegment, OsString, Vec};
10 use core::slice;
11
12 pub(super) fn native_libraries() -> Vec<Library> {
13 let mut ret = Vec::new();
14 unsafe {
15 libc::dl_iterate_phdr(Some(callback), &mut ret as *mut Vec<_> as *mut _);
16 }
17 return ret;
18 }
19
20 // `info` should be a valid pointers.
21 // `vec` should be a valid pointer to a `std::Vec`.
22 unsafe extern "C" fn callback(
23 info: *mut libc::dl_phdr_info,
24 _size: libc::size_t,
25 vec: *mut libc::c_void,
26 ) -> libc::c_int {
27 let info = &*info;
28 let libs = &mut *(vec as *mut Vec<Library>);
29 let is_main_prog = info.dlpi_name.is_null() || *info.dlpi_name == 0;
30 let name = if is_main_prog {
31 if libs.is_empty() {
32 env::current_exe().map(|e| e.into()).unwrap_or_default()
33 } else {
34 OsString::new()
35 }
36 } else {
37 let bytes = CStr::from_ptr(info.dlpi_name).to_bytes();
38 OsStr::from_bytes(bytes).to_owned()
39 };
40 let headers = slice::from_raw_parts(info.dlpi_phdr, info.dlpi_phnum as usize);
41 libs.push(Library {
42 name,
43 segments: headers
44 .iter()
45 .map(|header| LibrarySegment {
46 len: (*header).p_memsz as usize,
47 stated_virtual_memory_address: (*header).p_vaddr as usize,
48 })
49 .collect(),
50 bias: info.dlpi_addr as usize,
51 });
52 0
53 }