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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Describes modules

use crate::prelude::v1::*;

/// Module information structure
#[repr(C)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct ModuleInfo {
    /// Returns the address of the module header.
    ///
    /// # Remarks
    ///
    /// On Windows this will be the address where the [`PEB`](https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb) entry is stored.
    pub address: Address,
    /// The base address of the parent process.
    ///
    /// # Remarks
    ///
    /// This field is analog to the `ProcessInfo::address` field.
    pub parent_process: Address,
    /// The actual base address of this module.
    ///
    /// # Remarks
    ///
    /// The base address is contained in the virtual address range of the process
    /// this module belongs to.
    pub base: Address,
    /// Size of the module
    pub size: umem,
    /// Name of the module
    pub name: ReprCString,
    /// Path of the module
    pub path: ReprCString,
    /// Architecture of the module
    ///
    /// # Remarks
    ///
    /// Emulated processes often have 2 separate lists of modules, one visible to the emulated
    /// context (e.g. all 32-bit modules in a WoW64 process), and the other for all native modules
    /// needed to support the process emulation. This should be equal to either
    /// `ProcessInfo::proc_arch`, or `ProcessInfo::sys_arch` of the parent process.
    pub arch: ArchitectureIdent,
}

pub type ModuleInfoCallback<'a> = OpaqueCallback<'a, ModuleInfo>;

/// Pair of address and architecture used for callbacks
#[repr(C)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct ModuleAddressInfo {
    pub address: Address,
    pub arch: ArchitectureIdent,
}

pub type ModuleAddressCallback<'a> = OpaqueCallback<'a, ModuleAddressInfo>;

/// Import information structure
#[repr(C)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct ImportInfo {
    /// Name of the import
    pub name: ReprCString,
    /// Offset of this import from the containing modules base address
    pub offset: umem,
}

pub type ImportCallback<'a> = OpaqueCallback<'a, ImportInfo>;

/// Export information structure
#[repr(C)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct ExportInfo {
    /// Name of the export
    pub name: ReprCString,
    /// Offset of this export from the containing modules base address
    pub offset: umem,
}

pub type ExportCallback<'a> = OpaqueCallback<'a, ExportInfo>;

/// Section information structure
#[repr(C)]
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
#[cfg_attr(feature = "abi_stable", derive(::abi_stable::StableAbi))]
pub struct SectionInfo {
    /// Name of the section
    pub name: ReprCString,
    /// Virtual address of this section (essentially module_info.base + virtual_address)
    pub base: Address,
    /// Size of this section
    pub size: umem,
}

impl SectionInfo {
    /// Checks whether this section is of given name, ignoring '.' or '__' prefix.
    pub fn is_section(&self, name: &str) -> bool {
        let mut n = self.name.as_ref();
        if let Some(stripped) = n.strip_prefix('.') {
            n = stripped;
        } else if let Some(stripped) = n.strip_prefix("__") {
            n = stripped;
        } else {
            return false;
        }
        n == name
    }

    /// Checks whether given section is 'text', ignoring prefix.
    pub fn is_text(&self) -> bool {
        self.is_section("text")
    }
}

pub type SectionCallback<'a> = OpaqueCallback<'a, SectionInfo>;