twizzler_rt_abi/
debug.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
//! Functions for interfacing with debug info from the runtime.

use core::mem::MaybeUninit;

use crate::object::ObjectHandle;

/// Information about loaded image program headers.
pub type DlPhdrInfo = crate::bindings::dl_phdr_info;
/// Loaded image identifier.
pub type LoadedImageId = crate::bindings::loaded_image_id;

/// A loaded runtime program component, and the associated image (executable or library) file.
/// Contains debugging info and program header info.
#[repr(transparent)]
pub struct LoadedImage(crate::bindings::loaded_image);

/// The ID of the root (executable, probably) loaded image.
pub use crate::bindings::TWZ_RT_EXEID;

impl LoadedImage {
    /// Get a byte slice of the image.
    pub fn image(&self) -> &[u8] {
        // Safety: the runtime ensures that these are valid for a byte slice.
        unsafe { core::slice::from_raw_parts(self.0.image_start.cast(), self.0.image_len) }
    }

    /// Get an owned object handle for the image.
    pub fn handle(&self) -> ObjectHandle {
        // Since the internal object handle is from the C ffi, we need
        // to manually manage the refcounts. The phantom handle represents
        // our handle (self.0.handle), so we will forget it to ensure its
        // drop impl doesn't run.
        let phantom_handle = ObjectHandle(self.0.image_handle);
        // This handle is the one we are handing out.
        let handle = phantom_handle.clone();
        core::mem::forget(phantom_handle);
        handle
    }

    /// Get the runtime ID of the loaded image.
    pub fn id(&self) -> LoadedImageId {
        self.0.id
    }

    /// Get the [DlPhdrInfo] for this loaded image.
    pub fn dl_info(&self) -> &DlPhdrInfo {
        &self.0.dl_info
    }
}

impl Clone for LoadedImage {
    fn clone(&self) -> Self {
        // See LoadedImage::handle above for an explanation.
        let phantom_handle = ObjectHandle(self.0.image_handle);
        let handle = phantom_handle.clone();
        core::mem::forget(phantom_handle);
        // This time, we forget the handle so its drop doesn't run,
        // since that will be our cloned handle.
        core::mem::forget(handle);
        Self(self.0)
    }
}

impl Drop for LoadedImage {
    fn drop(&mut self) {
        let _handle = ObjectHandle(self.0.image_handle);
        // Drop the object handle, since it's stored
        // as a C type.
    }
}

/// Return the [LoadedImage] associated with the given [LoadedImageId] in the runtime.
/// If no such ID exists, return None.
pub fn twz_rt_get_loaded_image(id: LoadedImageId) -> Option<LoadedImage> {
    unsafe {
        let mut li = MaybeUninit::uninit();
        if !crate::bindings::twz_rt_get_loaded_image(id, li.as_mut_ptr()) {
            return None;
        }

        // Safety: the call above returning true ensures the value is initialized.
        Some(LoadedImage(li.assume_init()))
    }
}

/*
/// Iterate over the loaded program components known to the runtime. This function has similar semantics
/// to C's dl_iter_phdr. This function will call f with a [DlPhdrInfo] for each known loaded component,
/// until all components are processed, or until f returns a non-zero value (which this function then returns).
pub fn twz_rt_iter_phdr(f: &dyn Fn(&DlPhdrInfo) -> i32) -> i32 {
    // The twz_rt_iter_phdr call acts like dl_iter_phdr, so we'll need to trampoline to call f.
    extern "C-unwind" fn trampoline(info: *const DlPhdrInfo, size: usize, data: *mut core::ffi::c_void) -> i32 {
        unsafe {
            // Safety: the value of data is passed in by us below, and the contract with the runtime says that
            // the pointer to info is valid.
            let f: Box<&dyn Fn(&DlPhdrInfo) -> i32> = data.cast::<*mut Box<_>>().as_mut().unwrap();
            f(&*info)
        }
    }

    let mut data = Box::new(f);
    unsafe { crate::bindings::twz_rt_iter_phdr(Some(trampoline), &mut data as *mut _) }
}
*/