1use std::fmt;
18use std::hash::{Hash, Hasher};
19use std::ops::Range;
20
21use binaryninjacore_sys::*;
22
23use crate::binary_view::BinaryView;
24use crate::rc::*;
25use crate::string::*;
26
27#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)]
28pub enum Semantics {
29 #[default]
30 DefaultSection,
31 ReadOnlyCode,
32 ReadOnlyData,
33 ReadWriteData,
34 External,
35}
36
37impl From<BNSectionSemantics> for Semantics {
38 fn from(bn: BNSectionSemantics) -> Self {
39 use self::BNSectionSemantics::*;
40
41 match bn {
42 DefaultSectionSemantics => Semantics::DefaultSection,
43 ReadOnlyCodeSectionSemantics => Semantics::ReadOnlyCode,
44 ReadOnlyDataSectionSemantics => Semantics::ReadOnlyData,
45 ReadWriteDataSectionSemantics => Semantics::ReadWriteData,
46 ExternalSectionSemantics => Semantics::External,
47 }
48 }
49}
50
51impl From<Semantics> for BNSectionSemantics {
52 fn from(semantics: Semantics) -> Self {
53 use self::BNSectionSemantics::*;
54
55 match semantics {
56 Semantics::DefaultSection => DefaultSectionSemantics,
57 Semantics::ReadOnlyCode => ReadOnlyCodeSectionSemantics,
58 Semantics::ReadOnlyData => ReadOnlyDataSectionSemantics,
59 Semantics::ReadWriteData => ReadWriteDataSectionSemantics,
60 Semantics::External => ExternalSectionSemantics,
61 }
62 }
63}
64
65pub struct Section {
66 handle: *mut BNSection,
67}
68
69impl Section {
70 unsafe fn from_raw(handle: *mut BNSection) -> Self {
71 debug_assert!(!handle.is_null());
72 Self { handle }
73 }
74
75 pub(crate) unsafe fn ref_from_raw(handle: *mut BNSection) -> Ref<Self> {
76 debug_assert!(!handle.is_null());
77 Ref::new(Self { handle })
78 }
79
80 pub fn builder(name: String, range: Range<u64>) -> SectionBuilder {
89 SectionBuilder::new(name, range)
90 }
91
92 pub fn name(&self) -> BnString {
93 unsafe { BnString::from_raw(BNSectionGetName(self.handle)) }
94 }
95
96 pub fn section_type(&self) -> String {
97 unsafe { BnString::into_string(BNSectionGetType(self.handle)) }
98 }
99
100 pub fn start(&self) -> u64 {
101 unsafe { BNSectionGetStart(self.handle) }
102 }
103
104 pub fn end(&self) -> u64 {
105 unsafe { BNSectionGetEnd(self.handle) }
106 }
107
108 pub fn len(&self) -> usize {
109 unsafe { BNSectionGetLength(self.handle) as usize }
110 }
111
112 pub fn is_empty(&self) -> bool {
113 self.len() == 0
114 }
115
116 pub fn address_range(&self) -> Range<u64> {
117 self.start()..self.end()
118 }
119
120 pub fn semantics(&self) -> Semantics {
121 unsafe { BNSectionGetSemantics(self.handle).into() }
122 }
123
124 pub fn linked_section(&self) -> BnString {
125 unsafe { BnString::from_raw(BNSectionGetLinkedSection(self.handle)) }
126 }
127
128 pub fn info_section(&self) -> BnString {
129 unsafe { BnString::from_raw(BNSectionGetInfoSection(self.handle)) }
130 }
131
132 pub fn info_data(&self) -> u64 {
133 unsafe { BNSectionGetInfoData(self.handle) }
134 }
135
136 pub fn align(&self) -> u64 {
137 unsafe { BNSectionGetAlign(self.handle) }
138 }
139
140 pub fn entry_size(&self) -> usize {
141 unsafe { BNSectionGetEntrySize(self.handle) as usize }
142 }
143
144 pub fn auto_defined(&self) -> bool {
145 unsafe { BNSectionIsAutoDefined(self.handle) }
146 }
147}
148
149impl fmt::Debug for Section {
150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151 f.debug_struct("Section")
152 .field("name", &self.name())
153 .field("address_range", &self.address_range())
154 .field("section_type", &self.section_type())
155 .field("semantics", &self.semantics())
156 .field("linked_section", &self.linked_section())
157 .field("align", &self.align())
158 .field("entry_size", &self.entry_size())
159 .field("auto_defined", &self.auto_defined())
160 .finish()
161 }
162}
163
164impl PartialEq for Section {
165 fn eq(&self, other: &Self) -> bool {
166 self.name() == other.name()
168 && self.address_range() == other.address_range()
169 && self.semantics() == other.semantics()
170 && self.linked_section() == other.linked_section()
171 && self.info_section() == other.info_section()
172 && self.info_data() == other.info_data()
173 && self.align() == other.align()
174 && self.entry_size() == other.entry_size()
175 && self.auto_defined() == other.auto_defined()
176 }
177}
178
179impl Eq for Section {}
180
181impl Hash for Section {
182 fn hash<H: Hasher>(&self, state: &mut H) {
183 self.name().hash(state);
184 self.address_range().hash(state);
185 }
186}
187
188impl ToOwned for Section {
189 type Owned = Ref<Self>;
190
191 fn to_owned(&self) -> Self::Owned {
192 unsafe { RefCountable::inc_ref(self) }
193 }
194}
195
196unsafe impl RefCountable for Section {
197 unsafe fn inc_ref(handle: &Self) -> Ref<Self> {
198 Ref::new(Self {
199 handle: BNNewSectionReference(handle.handle),
200 })
201 }
202
203 unsafe fn dec_ref(handle: &Self) {
204 BNFreeSection(handle.handle);
205 }
206}
207
208impl CoreArrayProvider for Section {
209 type Raw = *mut BNSection;
210 type Context = ();
211 type Wrapped<'a> = Guard<'a, Section>;
212}
213
214unsafe impl CoreArrayProviderInner for Section {
215 unsafe fn free(raw: *mut Self::Raw, count: usize, _context: &Self::Context) {
216 BNFreeSectionList(raw, count);
217 }
218
219 unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
220 Guard::new(Section::from_raw(*raw), context)
221 }
222}
223
224#[must_use]
225#[derive(Clone, Debug, PartialEq, Eq, Hash)]
226pub struct SectionBuilder {
227 is_auto: bool,
228 name: String,
229 range: Range<u64>,
230 semantics: Semantics,
231 ty: String,
232 align: u64,
233 entry_size: u64,
234 linked_section: String,
235 info_section: String,
236 info_data: u64,
237}
238
239impl SectionBuilder {
240 pub fn new(name: String, range: Range<u64>) -> Self {
241 Self {
242 is_auto: false,
243 name,
244 range,
245 semantics: Semantics::DefaultSection,
246 ty: "".to_string(),
247 align: 1,
248 entry_size: 1,
249 linked_section: "".to_string(),
250 info_section: "".to_string(),
251 info_data: 0,
252 }
253 }
254
255 pub fn semantics(mut self, semantics: Semantics) -> Self {
256 self.semantics = semantics;
257 self
258 }
259
260 pub fn section_type(mut self, ty: String) -> Self {
261 self.ty = ty;
262 self
263 }
264
265 pub fn align(mut self, align: u64) -> Self {
266 self.align = align;
267 self
268 }
269
270 pub fn entry_size(mut self, entry_size: u64) -> Self {
271 self.entry_size = entry_size;
272 self
273 }
274
275 pub fn linked_section(mut self, linked_section: String) -> Self {
276 self.linked_section = linked_section;
277 self
278 }
279
280 pub fn info_section(mut self, info_section: String) -> Self {
281 self.info_section = info_section;
282 self
283 }
284
285 pub fn info_data(mut self, info_data: u64) -> Self {
286 self.info_data = info_data;
287 self
288 }
289
290 pub fn is_auto(mut self, is_auto: bool) -> Self {
291 self.is_auto = is_auto;
292 self
293 }
294
295 pub(crate) fn create(self, view: &BinaryView) {
296 let name = self.name.to_cstr();
297 let ty = self.ty.to_cstr();
298 let linked_section = self.linked_section.to_cstr();
299 let info_section = self.info_section.to_cstr();
300
301 let start = self.range.start;
302 let len = self.range.end.wrapping_sub(start);
303
304 unsafe {
305 if self.is_auto {
306 BNAddAutoSection(
307 view.handle,
308 name.as_ptr(),
309 start,
310 len,
311 self.semantics.into(),
312 ty.as_ptr(),
313 self.align,
314 self.entry_size,
315 linked_section.as_ptr(),
316 info_section.as_ptr(),
317 self.info_data,
318 );
319 } else {
320 BNAddUserSection(
321 view.handle,
322 name.as_ptr(),
323 start,
324 len,
325 self.semantics.into(),
326 ty.as_ptr(),
327 self.align,
328 self.entry_size,
329 linked_section.as_ptr(),
330 info_section.as_ptr(),
331 self.info_data,
332 );
333 }
334 }
335 }
336}
337
338impl<T: AsRef<Section>> From<T> for SectionBuilder {
339 fn from(value: T) -> Self {
340 let value = value.as_ref();
341 let name = value.name().to_string_lossy().to_string();
342 let ty = value.section_type().to_string();
343 let linked_section = value.linked_section().to_string_lossy().to_string();
344 let info_section = value.info_section().to_string_lossy().to_string();
345
346 Self {
347 is_auto: value.auto_defined(),
348 name,
349 range: value.address_range(),
350 semantics: value.semantics(),
351 ty,
352 align: value.align(),
353 entry_size: value.entry_size() as u64,
354 linked_section,
355 info_section,
356 info_data: value.info_data(),
357 }
358 }
359}