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