idalib/
segment.rs

1use std::marker::PhantomData;
2use std::mem;
3use std::pin::Pin;
4
5use autocxx::moveit::Emplace;
6use bitflags::bitflags;
7
8use crate::ffi::range_t;
9use crate::ffi::segment::*;
10use crate::idb::IDB;
11use crate::Address;
12
13pub struct Segment<'a> {
14    ptr: *mut segment_t,
15    _lock: Pin<Box<lock_segment>>,
16    _marker: PhantomData<&'a IDB>,
17}
18
19pub type SegmentId = usize;
20
21bitflags! {
22    #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
23    pub struct SegmentPermissions: u8 {
24        const EXEC = SEGPERM_EXEC as _;
25        const WRITE = SEGPERM_WRITE as _;
26        const READ = SEGPERM_READ as _;
27    }
28}
29
30#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
31#[repr(u8)]
32pub enum SegmentAlignment {
33    Abs = saAbs as _,
34    RelByte = saRelByte as _,
35    RelWord = saRelWord as _,
36    RelPara = saRelPara as _,
37    RelPage = saRelPage as _,
38    RelDble = saRelDble as _,
39    Rel4K = saRel4K as _,
40    Group = saGroup as _,
41    Rel32Bytes = saRel32Bytes as _,
42    Rel64Bytes = saRel64Bytes as _,
43    RelQword = saRelQword as _,
44    Rel128Bytes = saRel128Bytes as _,
45    Rel512Bytes = saRel512Bytes as _,
46    Rel1024Bytes = saRel1024Bytes as _,
47    Rel2048Bytes = saRel2048Bytes as _,
48}
49
50#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
51#[repr(u8)]
52pub enum SegmentType {
53    NORM = SEG_NORM as _,
54    XTRN = SEG_XTRN as _,
55    CODE = SEG_CODE as _,
56    DATA = SEG_DATA as _,
57    IMP = SEG_IMP as _,
58    GRP = SEG_GRP as _,
59    NULL = SEG_NULL as _,
60    UNDF = SEG_UNDF as _,
61    BSS = SEG_BSS as _,
62    ABSSYM = SEG_ABSSYM as _,
63    COMM = SEG_COMM as _,
64    IMEM = SEG_IMEM as _,
65}
66
67impl<'a> Segment<'a> {
68    pub(crate) fn from_ptr(ptr: *mut segment_t) -> Self {
69        let lock = unsafe { Box::emplace(lock_segment::new(ptr)) };
70        Self {
71            ptr,
72            _lock: lock,
73            _marker: PhantomData,
74        }
75    }
76
77    fn as_range_t(&self) -> *const range_t {
78        self.ptr.cast()
79    }
80
81    pub fn start_address(&self) -> Address {
82        unsafe { (*self.as_range_t()).start_ea.into() }
83    }
84
85    pub fn end_address(&self) -> Address {
86        unsafe { (*self.as_range_t()).end_ea.into() }
87    }
88
89    pub fn len(&self) -> usize {
90        unsafe { (*self.as_range_t()).size().0 as _ }
91    }
92
93    pub fn is_empty(&self) -> bool {
94        self.len() == 0
95    }
96
97    pub fn contains_address(&self, addr: Address) -> bool {
98        unsafe { (*self.as_range_t()).contains(addr.into()) }
99    }
100
101    pub fn name(&self) -> Option<String> {
102        let name = unsafe { idalib_segm_name(self.ptr) }.ok()?;
103
104        if name.is_empty() {
105            None
106        } else {
107            Some(name)
108        }
109    }
110
111    pub fn alignment(&self) -> SegmentAlignment {
112        unsafe { mem::transmute(idalib_segm_align(self.ptr)) }
113    }
114
115    pub fn permissions(&self) -> SegmentPermissions {
116        let bits = unsafe { idalib_segm_perm(self.ptr) };
117        SegmentPermissions::from_bits_retain(bits)
118    }
119
120    pub fn bitness(&self) -> usize {
121        (unsafe { idalib_segm_bitness(self.ptr) }) as usize
122    }
123
124    pub fn r#type(&self) -> SegmentType {
125        unsafe { mem::transmute(idalib_segm_type(self.ptr)) }
126    }
127
128    pub fn bytes(&self) -> Vec<u8> {
129        let size = self.len();
130        let mut buf = Vec::with_capacity(size);
131
132        let Ok(new_len) = (unsafe { idalib_segm_bytes(self.ptr, &mut buf) }) else {
133            return Vec::with_capacity(0);
134        };
135
136        unsafe {
137            buf.set_len(new_len);
138        }
139
140        buf
141    }
142
143    pub fn address_bits(&self) -> u32 {
144        unsafe { (*self.ptr).abits().0 as _ }
145    }
146
147    pub fn address_bytes(&self) -> usize {
148        unsafe { (*self.ptr).abytes().0 as _ }
149    }
150
151    pub fn is_16bit(&self) -> bool {
152        unsafe { (*self.ptr).is_16bit() }
153    }
154
155    pub fn is_32bit(&self) -> bool {
156        unsafe { (*self.ptr).is_32bit() }
157    }
158
159    pub fn is_64bit(&self) -> bool {
160        unsafe { (*self.ptr).is_64bit() }
161    }
162
163    pub fn is_hidden(&self) -> bool {
164        unsafe { (*self.ptr).is_hidden_segtype() }
165    }
166
167    pub fn is_loader(&self) -> bool {
168        unsafe { (*self.ptr).is_loader_segm() }
169    }
170
171    pub fn is_header(&self) -> bool {
172        unsafe { (*self.ptr).is_header_segm() }
173    }
174
175    pub fn is_ephemeral(&self) -> bool {
176        unsafe { (*self.ptr).is_ephemeral_segm() }
177    }
178
179    pub fn is_debugger(&self) -> bool {
180        unsafe { (*self.ptr).is_debugger_segm() }
181    }
182
183    pub fn is_visible(&self) -> bool {
184        unsafe { (*self.ptr).is_visible_segm() }
185    }
186}