Skip to content

Commit b4d77d5

Browse files
committed
Add AnalysisContext FFI for SectionMap queries.
1 parent d3d4d43 commit b4d77d5

File tree

5 files changed

+219
-1
lines changed

5 files changed

+219
-1
lines changed

binaryninjaapi.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11483,6 +11483,15 @@ namespace BinaryNinja {
1148311483
Ref<Segment> GetSegmentAt(uint64_t addr);
1148411484
std::vector<BNAddressRange> GetMappedAddressRanges();
1148511485
std::vector<BNAddressRange> GetBackedAddressRanges();
11486+
11487+
// Section map access - lock-free access to cached SectionMap
11488+
bool IsOffsetCodeSemantics(uint64_t offset);
11489+
bool IsOffsetExternSemantics(uint64_t offset);
11490+
bool IsOffsetWritableSemantics(uint64_t offset);
11491+
bool IsOffsetReadOnlySemantics(uint64_t offset);
11492+
std::vector<Ref<Section>> GetSections();
11493+
Ref<Section> GetSectionByName(const std::string& name);
11494+
std::vector<Ref<Section>> GetSectionsAt(uint64_t addr);
1148611495
};
1148711496

1148811497
// Explicit template specialization declarations for AnalysisContext::GetSetting<T>

binaryninjacore.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
// Current ABI version for linking to the core. This is incremented any time
3838
// there are changes to the API that affect linking, including new functions,
3939
// new types, or modifications to existing functions or types.
40-
#define BN_CURRENT_CORE_ABI_VERSION 149
40+
#define BN_CURRENT_CORE_ABI_VERSION 150
4141

4242
// Minimum ABI version that is supported for loading of plugins. Plugins that
4343
// are linked to an ABI version less than this will not be able to load and
@@ -5945,6 +5945,13 @@ extern "C"
59455945
BINARYNINJACOREAPI bool BNAnalysisContextIsOffsetWritable(BNAnalysisContext* analysisContext, uint64_t offset);
59465946
BINARYNINJACOREAPI bool BNAnalysisContextIsOffsetExecutable(BNAnalysisContext* analysisContext, uint64_t offset);
59475947
BINARYNINJACOREAPI bool BNAnalysisContextIsOffsetBackedByFile(BNAnalysisContext* analysisContext, uint64_t offset);
5948+
BINARYNINJACOREAPI bool BNAnalysisContextIsOffsetCodeSemantics(BNAnalysisContext* analysisContext, uint64_t offset);
5949+
BINARYNINJACOREAPI bool BNAnalysisContextIsOffsetExternSemantics(BNAnalysisContext* analysisContext, uint64_t offset);
5950+
BINARYNINJACOREAPI bool BNAnalysisContextIsOffsetWritableSemantics(BNAnalysisContext* analysisContext, uint64_t offset);
5951+
BINARYNINJACOREAPI bool BNAnalysisContextIsOffsetReadOnlySemantics(BNAnalysisContext* analysisContext, uint64_t offset);
5952+
BINARYNINJACOREAPI BNSection** BNAnalysisContextGetSections(BNAnalysisContext* analysisContext, size_t* count);
5953+
BINARYNINJACOREAPI BNSection* BNAnalysisContextGetSectionByName(BNAnalysisContext* analysisContext, const char* name);
5954+
BINARYNINJACOREAPI BNSection** BNAnalysisContextGetSectionsAt(BNAnalysisContext* analysisContext, uint64_t addr, size_t* count);
59485955
BINARYNINJACOREAPI uint64_t BNAnalysisContextGetStart(BNAnalysisContext* analysisContext);
59495956
BINARYNINJACOREAPI uint64_t BNAnalysisContextGetEnd(BNAnalysisContext* analysisContext);
59505957
BINARYNINJACOREAPI uint64_t BNAnalysisContextGetLength(BNAnalysisContext* analysisContext);

python/workflow.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,83 @@ def is_offset_backed_by_file(self, offset: int) -> bool:
293293
"""
294294
return core.BNAnalysisContextIsOffsetBackedByFile(self.handle, offset)
295295

296+
def is_offset_code_semantics(self, offset: int) -> bool:
297+
"""
298+
Check if an offset has code semantics in the cached section map.
299+
300+
:param offset: Offset to check
301+
:return: True if offset has code semantics
302+
"""
303+
return core.BNAnalysisContextIsOffsetCodeSemantics(self.handle, offset)
304+
305+
def is_offset_extern_semantics(self, offset: int) -> bool:
306+
"""
307+
Check if an offset has external semantics in the cached section map.
308+
309+
:param offset: Offset to check
310+
:return: True if offset has external semantics
311+
"""
312+
return core.BNAnalysisContextIsOffsetExternSemantics(self.handle, offset)
313+
314+
def is_offset_writable_semantics(self, offset: int) -> bool:
315+
"""
316+
Check if an offset has writable semantics in the cached section map.
317+
318+
:param offset: Offset to check
319+
:return: True if offset has writable semantics
320+
"""
321+
return core.BNAnalysisContextIsOffsetWritableSemantics(self.handle, offset)
322+
323+
def is_offset_readonly_semantics(self, offset: int) -> bool:
324+
"""
325+
Check if an offset has read-only semantics in the cached section map.
326+
327+
:param offset: Offset to check
328+
:return: True if offset has read-only semantics
329+
"""
330+
return core.BNAnalysisContextIsOffsetReadOnlySemantics(self.handle, offset)
331+
332+
def get_sections(self) -> List['binaryninja.binaryview.Section']:
333+
"""
334+
Get all sections from the cached section map.
335+
336+
:return: List of all sections
337+
"""
338+
count = ctypes.c_ulonglong()
339+
sections = core.BNAnalysisContextGetSections(self.handle, count)
340+
result = []
341+
for i in range(count.value):
342+
result.append(binaryninja.binaryview.Section(core.BNNewSectionReference(sections[i])))
343+
core.BNFreeSectionList(sections, count.value)
344+
return result
345+
346+
def get_section_by_name(self, name: str) -> Optional['binaryninja.binaryview.Section']:
347+
"""
348+
Get a section by name from the cached section map.
349+
350+
:param name: Section name
351+
:return: Section with the given name, or None if not found
352+
"""
353+
section = core.BNAnalysisContextGetSectionByName(self.handle, name)
354+
if not section:
355+
return None
356+
return binaryninja.binaryview.Section(section)
357+
358+
def get_sections_at(self, addr: int) -> List['binaryninja.binaryview.Section']:
359+
"""
360+
Get all sections containing the given address from the cached section map.
361+
362+
:param addr: Address to query
363+
:return: List of sections containing the address
364+
"""
365+
count = ctypes.c_ulonglong()
366+
sections = core.BNAnalysisContextGetSectionsAt(self.handle, addr, count)
367+
result = []
368+
for i in range(count.value):
369+
result.append(binaryninja.binaryview.Section(core.BNNewSectionReference(sections[i])))
370+
core.BNFreeSectionList(sections, count.value)
371+
return result
372+
296373
def get_start(self) -> int:
297374
"""
298375
Get the start address from the cached memory map.

rust/src/workflow.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::high_level_il::HighLevelILFunction;
1212
use crate::low_level_il::{LowLevelILMutableFunction, LowLevelILRegularFunction};
1313
use crate::medium_level_il::MediumLevelILFunction;
1414
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Guard, Ref, RefCountable};
15+
use crate::section::Section;
1516
use crate::segment::{Segment, SegmentFlags};
1617
use crate::string::{BnString, IntoCStr};
1718
use std::ffi::c_char;
@@ -215,6 +216,71 @@ impl AnalysisContext {
215216
unsafe { BNAnalysisContextIsOffsetBackedByFile(self.handle.as_ptr(), offset) }
216217
}
217218

219+
/// Check if an offset has code semantics in the cached section map.
220+
///
221+
/// NOTE: This is a lock-free alternative to [`BinaryView::is_offset_code_semantics`].
222+
pub fn is_offset_code_semantics(&self, offset: u64) -> bool {
223+
unsafe { BNAnalysisContextIsOffsetCodeSemantics(self.handle.as_ptr(), offset) }
224+
}
225+
226+
/// Check if an offset has external semantics in the cached section map.
227+
///
228+
/// NOTE: This is a lock-free alternative to [`BinaryView::is_offset_extern_semantics`].
229+
pub fn is_offset_extern_semantics(&self, offset: u64) -> bool {
230+
unsafe { BNAnalysisContextIsOffsetExternSemantics(self.handle.as_ptr(), offset) }
231+
}
232+
233+
/// Check if an offset has writable semantics in the cached section map.
234+
///
235+
/// NOTE: This is a lock-free alternative to [`BinaryView::is_offset_writable_semantics`].
236+
pub fn is_offset_writable_semantics(&self, offset: u64) -> bool {
237+
unsafe { BNAnalysisContextIsOffsetWritableSemantics(self.handle.as_ptr(), offset) }
238+
}
239+
240+
/// Check if an offset has read-only semantics in the cached section map.
241+
///
242+
/// NOTE: This is a lock-free alternative to [`BinaryView::is_offset_readonly_semantics`].
243+
pub fn is_offset_readonly_semantics(&self, offset: u64) -> bool {
244+
unsafe { BNAnalysisContextIsOffsetReadOnlySemantics(self.handle.as_ptr(), offset) }
245+
}
246+
247+
/// Get all sections from the cached section map.
248+
///
249+
/// NOTE: This is a lock-free alternative to [`BinaryView::sections`].
250+
pub fn sections(&self) -> Array<Section> {
251+
unsafe {
252+
let mut count = 0;
253+
let sections = BNAnalysisContextGetSections(self.handle.as_ptr(), &mut count);
254+
Array::new(sections, count, ())
255+
}
256+
}
257+
258+
/// Get a section by name from the cached section map.
259+
///
260+
/// NOTE: This is a lock-free alternative to [`BinaryView::section_by_name`].
261+
pub fn section_by_name(&self, name: impl IntoCStr) -> Option<Ref<Section>> {
262+
unsafe {
263+
let raw_name = name.to_cstr();
264+
let name_ptr = raw_name.as_ptr();
265+
let raw_section_ptr = BNAnalysisContextGetSectionByName(self.handle.as_ptr(), name_ptr);
266+
match raw_section_ptr.is_null() {
267+
false => Some(Section::ref_from_raw(raw_section_ptr)),
268+
true => None,
269+
}
270+
}
271+
}
272+
273+
/// Get all sections containing the given address from the cached section map.
274+
///
275+
/// NOTE: This is a lock-free alternative to [`BinaryView::sections_at`].
276+
pub fn sections_at(&self, addr: u64) -> Array<Section> {
277+
unsafe {
278+
let mut count = 0;
279+
let sections = BNAnalysisContextGetSectionsAt(self.handle.as_ptr(), addr, &mut count);
280+
Array::new(sections, count, ())
281+
}
282+
}
283+
218284
/// Get the start address (the lowest address) from the cached [`MemoryMap`].
219285
///
220286
/// NOTE: This is a lock-free alternative to [`BinaryView::start`].

workflow.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,65 @@ bool AnalysisContext::IsOffsetBackedByFile(uint64_t offset)
235235
}
236236

237237

238+
bool AnalysisContext::IsOffsetCodeSemantics(uint64_t offset)
239+
{
240+
return BNAnalysisContextIsOffsetCodeSemantics(m_object, offset);
241+
}
242+
243+
244+
bool AnalysisContext::IsOffsetExternSemantics(uint64_t offset)
245+
{
246+
return BNAnalysisContextIsOffsetExternSemantics(m_object, offset);
247+
}
248+
249+
250+
bool AnalysisContext::IsOffsetWritableSemantics(uint64_t offset)
251+
{
252+
return BNAnalysisContextIsOffsetWritableSemantics(m_object, offset);
253+
}
254+
255+
256+
bool AnalysisContext::IsOffsetReadOnlySemantics(uint64_t offset)
257+
{
258+
return BNAnalysisContextIsOffsetReadOnlySemantics(m_object, offset);
259+
}
260+
261+
262+
vector<Ref<Section>> AnalysisContext::GetSections()
263+
{
264+
size_t count;
265+
BNSection** sections = BNAnalysisContextGetSections(m_object, &count);
266+
vector<Ref<Section>> result;
267+
result.reserve(count);
268+
for (size_t i = 0; i < count; i++)
269+
result.push_back(new Section(BNNewSectionReference(sections[i])));
270+
BNFreeSectionList(sections, count);
271+
return result;
272+
}
273+
274+
275+
Ref<Section> AnalysisContext::GetSectionByName(const string& name)
276+
{
277+
BNSection* section = BNAnalysisContextGetSectionByName(m_object, name.c_str());
278+
if (!section)
279+
return nullptr;
280+
return new Section(section);
281+
}
282+
283+
284+
vector<Ref<Section>> AnalysisContext::GetSectionsAt(uint64_t addr)
285+
{
286+
size_t count;
287+
BNSection** sections = BNAnalysisContextGetSectionsAt(m_object, addr, &count);
288+
vector<Ref<Section>> result;
289+
result.reserve(count);
290+
for (size_t i = 0; i < count; i++)
291+
result.push_back(new Section(BNNewSectionReference(sections[i])));
292+
BNFreeSectionList(sections, count);
293+
return result;
294+
}
295+
296+
238297
uint64_t AnalysisContext::GetStart()
239298
{
240299
return BNAnalysisContextGetStart(m_object);

0 commit comments

Comments
 (0)