Skip to content

Commit c6e5bff

Browse files
authored
Haiku: add support for finding libraries and mapping library segments (#411)
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.
1 parent 83e1c37 commit c6e5bff

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ exclude = ['crates/without_debuginfo', 'crates/macos_frames_test', 'crates/line-
2222
cfg-if = "1.0"
2323
rustc-demangle = "0.1.4"
2424
backtrace-sys = { path = "crates/backtrace-sys", version = "0.1.35", optional = true, default_features = false }
25-
libc = { version = "0.2.81", default-features = false }
25+
libc = { version = "0.2.87", default-features = false }
2626

2727
# Optionally enable the ability to serialize a `Backtrace`, controlled through
2828
# the `serialize-*` features below.

src/symbolize/gimli.rs

+57
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ cfg_if::cfg_if! {
3434
target_os = "android",
3535
target_os = "freebsd",
3636
target_os = "fuchsia",
37+
target_os = "haiku",
3738
target_os = "ios",
3839
target_os = "linux",
3940
target_os = "macos",
@@ -447,6 +448,62 @@ cfg_if::cfg_if! {
447448

448449
ret
449450
}
451+
} else if #[cfg(target_os = "haiku")] {
452+
// Haiku implements the image_info struct and the get_next_image_info()
453+
// functions to iterate through the loaded executable images. The
454+
// image_info struct contains a pointer to the start of the .text
455+
// section within the virtual address space, as well as the size of
456+
// that section. All the read-only segments of the ELF-binary are in
457+
// that part of the address space.
458+
459+
use mystd::os::unix::prelude::*;
460+
use mystd::ffi::{OsStr, CStr};
461+
462+
mod elf;
463+
use self::elf::Object;
464+
465+
fn native_libraries() -> Vec<Library> {
466+
let mut libraries: Vec<Library> = Vec::new();
467+
468+
unsafe {
469+
let mut info = mem::MaybeUninit::<libc::image_info>::zeroed();
470+
let mut cookie: i32 = 0;
471+
// Load the first image to get a valid info struct
472+
let mut status = libc::get_next_image_info(
473+
libc::B_CURRENT_TEAM,
474+
&mut cookie,
475+
info.as_mut_ptr(),
476+
);
477+
if status != libc::B_OK {
478+
return libraries;
479+
}
480+
let mut info = info.assume_init();
481+
482+
while status == libc::B_OK {
483+
let mut segments = Vec::new();
484+
segments.push(LibrarySegment {
485+
stated_virtual_memory_address: 0,
486+
len: info.text_size as usize,
487+
});
488+
489+
let bytes = CStr::from_ptr(info.name.as_ptr()).to_bytes();
490+
let name = OsStr::from_bytes(bytes).to_owned();
491+
libraries.push(Library{
492+
name: name,
493+
segments: segments,
494+
bias: info.text as usize
495+
});
496+
497+
status = libc::get_next_image_info(
498+
libc::B_CURRENT_TEAM,
499+
&mut cookie,
500+
&mut info
501+
);
502+
}
503+
}
504+
505+
libraries
506+
}
450507
} else {
451508
// Everything else should use ELF, but doesn't know how to load native
452509
// libraries.

0 commit comments

Comments
 (0)