From 73647dabbb27376fae29a06c6ea883e8c4ac3375 Mon Sep 17 00:00:00 2001 From: Niels Sascha Reedijk Date: Tue, 2 Mar 2021 11:14:55 +0000 Subject: [PATCH] Haiku: add support for finding libraries and mapping library segments With the new native bindings in libc 0.2.87, it is now possible to iterate over all loaded images (the executable, shared libraries and libraries using dlopen()), and map the loaded segments to the right files, so that the debuginfo of the files can be used. This adds stacktrace support for Haiku. --- Cargo.toml | 2 +- src/symbolize/gimli.rs | 57 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a508c24e3..505df2732 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ exclude = ['crates/without_debuginfo', 'crates/macos_frames_test', 'crates/line- cfg-if = "1.0" rustc-demangle = "0.1.4" backtrace-sys = { path = "crates/backtrace-sys", version = "0.1.35", optional = true, default_features = false } -libc = { version = "0.2.81", default-features = false } +libc = { version = "0.2.87", default-features = false } # Optionally enable the ability to serialize a `Backtrace`, controlled through # the `serialize-*` features below. diff --git a/src/symbolize/gimli.rs b/src/symbolize/gimli.rs index 48524ee69..3dc6b8761 100644 --- a/src/symbolize/gimli.rs +++ b/src/symbolize/gimli.rs @@ -34,6 +34,7 @@ cfg_if::cfg_if! { target_os = "android", target_os = "freebsd", target_os = "fuchsia", + target_os = "haiku", target_os = "ios", target_os = "linux", target_os = "macos", @@ -447,6 +448,62 @@ cfg_if::cfg_if! { ret } + } else if #[cfg(target_os = "haiku")] { + // Haiku implements the image_info struct and the get_next_image_info() + // functions to iterate through the loaded executable images. The + // image_info struct contains a pointer to the start of the .text + // section within the virtual address space, as well as the size of + // that section. All the read-only segments of the ELF-binary are in + // that part of the address space. + + use mystd::os::unix::prelude::*; + use mystd::ffi::{OsStr, CStr}; + + mod elf; + use self::elf::Object; + + fn native_libraries() -> Vec { + let mut libraries: Vec = Vec::new(); + + unsafe { + let mut info = mem::MaybeUninit::::zeroed(); + let mut cookie: i32 = 0; + // Load the first image to get a valid info struct + let mut status = libc::get_next_image_info( + libc::B_CURRENT_TEAM, + &mut cookie, + info.as_mut_ptr(), + ); + if status != libc::B_OK { + return libraries; + } + let mut info = info.assume_init(); + + while status == libc::B_OK { + let mut segments = Vec::new(); + segments.push(LibrarySegment { + stated_virtual_memory_address: 0, + len: info.text_size as usize, + }); + + let bytes = CStr::from_ptr(info.name.as_ptr()).to_bytes(); + let name = OsStr::from_bytes(bytes).to_owned(); + libraries.push(Library{ + name: name, + segments: segments, + bias: info.text as usize + }); + + status = libc::get_next_image_info( + libc::B_CURRENT_TEAM, + &mut cookie, + &mut info + ); + } + } + + libraries + } } else { // Everything else should use ELF, but doesn't know how to load native // libraries.