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);