twizzler_rt_abi/debug.rs
1//! Functions for interfacing with debug info from the runtime.
2
3use core::mem::MaybeUninit;
4
5use crate::object::ObjectHandle;
6
7/// Information about loaded image program headers.
8pub type DlPhdrInfo = crate::bindings::dl_phdr_info;
9/// Loaded image identifier.
10pub type LoadedImageId = crate::bindings::loaded_image_id;
11
12/// A loaded runtime program component, and the associated image (executable or library) file.
13/// Contains debugging info and program header info.
14#[repr(transparent)]
15pub struct LoadedImage(crate::bindings::loaded_image);
16
17/// The ID of the root (executable, probably) loaded image.
18pub use crate::bindings::TWZ_RT_EXEID;
19
20impl LoadedImage {
21 /// Get a byte slice of the image.
22 pub fn image(&self) -> &[u8] {
23 // Safety: the runtime ensures that these are valid for a byte slice.
24 unsafe { core::slice::from_raw_parts(self.0.image_start.cast(), self.0.image_len) }
25 }
26
27 /// Get an owned object handle for the image.
28 pub fn handle(&self) -> ObjectHandle {
29 // Since the internal object handle is from the C ffi, we need
30 // to manually manage the refcounts. The phantom handle represents
31 // our handle (self.0.handle), so we will forget it to ensure its
32 // drop impl doesn't run.
33 let phantom_handle = ObjectHandle(self.0.image_handle);
34 // This handle is the one we are handing out.
35 let handle = phantom_handle.clone();
36 core::mem::forget(phantom_handle);
37 handle
38 }
39
40 /// Get the runtime ID of the loaded image.
41 pub fn id(&self) -> LoadedImageId {
42 self.0.id
43 }
44
45 /// Get the [DlPhdrInfo] for this loaded image.
46 pub fn dl_info(&self) -> &DlPhdrInfo {
47 &self.0.dl_info
48 }
49}
50
51impl Clone for LoadedImage {
52 fn clone(&self) -> Self {
53 // See LoadedImage::handle above for an explanation.
54 let phantom_handle = ObjectHandle(self.0.image_handle);
55 let handle = phantom_handle.clone();
56 core::mem::forget(phantom_handle);
57 // This time, we forget the handle so its drop doesn't run,
58 // since that will be our cloned handle.
59 core::mem::forget(handle);
60 Self(self.0)
61 }
62}
63
64impl Drop for LoadedImage {
65 fn drop(&mut self) {
66 let _handle = ObjectHandle(self.0.image_handle);
67 // Drop the object handle, since it's stored
68 // as a C type.
69 }
70}
71
72/// Return the [LoadedImage] associated with the given [LoadedImageId] in the runtime.
73/// If no such ID exists, return None.
74pub fn twz_rt_get_loaded_image(id: LoadedImageId) -> Option<LoadedImage> {
75 unsafe {
76 let mut li = MaybeUninit::uninit();
77 if !crate::bindings::twz_rt_get_loaded_image(id, li.as_mut_ptr()) {
78 return None;
79 }
80
81 // Safety: the call above returning true ensures the value is initialized.
82 Some(LoadedImage(li.assume_init()))
83 }
84}
85
86#[repr(transparent)]
87#[derive(Debug, Copy, Clone)]
88pub struct LinkMap(pub crate::bindings::link_map);