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}