Skip to content

Commit 1c01b00

Browse files
committed
Move LLIL instruction retrieval into the LLIL function where it belongs
The python API was kept the same seeing as we are close to the release, will likely start deprecating some of those API's soon.
1 parent 99e4426 commit 1c01b00

File tree

9 files changed

+136
-164
lines changed

9 files changed

+136
-164
lines changed

binaryninjaapi.h

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11345,16 +11345,6 @@ namespace BinaryNinja {
1134511345
*/
1134611346
Ref<LowLevelILFunction> GetLowLevelILIfAvailable() const;
1134711347

11348-
/*! Get the Low Level IL Instruction start for an instruction at an address
11349-
11350-
\param arch Architecture for the instruction
11351-
\param addr Address of the instruction
11352-
\return Start address of the instruction
11353-
*/
11354-
size_t GetLowLevelILForInstruction(Architecture* arch, uint64_t addr);
11355-
std::set<size_t> GetLowLevelILInstructionsForAddress(Architecture* arch, uint64_t addr);
11356-
std::vector<size_t> GetLowLevelILExitsForInstruction(Architecture* arch, uint64_t addr);
11357-
1135811348
std::pair<DataBuffer, BNBuiltinType> GetConstantData(
1135911349
BNRegisterValueType state, uint64_t value, size_t size = 0);
1136011350

@@ -12289,6 +12279,9 @@ namespace BinaryNinja {
1228912279
uint64_t GetCurrentAddress() const;
1229012280
void SetCurrentAddress(Architecture* arch, uint64_t addr);
1229112281
size_t GetInstructionStart(Architecture* arch, uint64_t addr);
12282+
std::set<size_t> GetInstructionsAt(Architecture* arch, uint64_t addr);
12283+
12284+
std::vector<size_t> GetExitsForInstruction(size_t i);
1229212285

1229312286
void ClearIndirectBranches();
1229412287
void SetIndirectBranches(const std::vector<ArchAndAddr>& branches);

binaryninjacore.h

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@
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 123
40+
#define BN_CURRENT_CORE_ABI_VERSION 124
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
4444
// will require rebuilding. The minimum version is increased when there are
4545
// incompatible changes that break binary compatibility, such as changes to
4646
// existing types or functions.
47-
#define BN_MINIMUM_CORE_ABI_VERSION 121
47+
#define BN_MINIMUM_CORE_ABI_VERSION 124
4848

4949
#ifdef __GNUC__
5050
#ifdef BINARYNINJACORE_LIBRARY
@@ -4787,11 +4787,6 @@ extern "C"
47874787

47884788
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelIL(BNFunction* func);
47894789
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelILIfAvailable(BNFunction* func);
4790-
BINARYNINJACOREAPI size_t BNGetLowLevelILForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr);
4791-
BINARYNINJACOREAPI size_t* BNGetLowLevelILInstructionsForAddress(
4792-
BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count);
4793-
BINARYNINJACOREAPI size_t* BNGetLowLevelILExitsForInstruction(
4794-
BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count);
47954790
BINARYNINJACOREAPI void BNFreeILInstructionList(size_t* list);
47964791
BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelIL(BNFunction* func);
47974792
BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelILIfAvailable(BNFunction* func);
@@ -4837,9 +4832,6 @@ extern "C"
48374832

48384833
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLiftedIL(BNFunction* func);
48394834
BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLiftedILIfAvailable(BNFunction* func);
4840-
BINARYNINJACOREAPI size_t BNGetLiftedILForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr);
4841-
BINARYNINJACOREAPI size_t* BNGetLiftedILInstructionsForAddress(
4842-
BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count);
48434835
BINARYNINJACOREAPI size_t* BNGetLiftedILFlagUsesForDefinition(
48444836
BNFunction* func, size_t i, uint32_t flag, size_t* count);
48454837
BINARYNINJACOREAPI size_t* BNGetLiftedILFlagDefinitionsForUse(
@@ -5967,6 +5959,10 @@ extern "C"
59675959
BINARYNINJACOREAPI void BNLowLevelILSetCurrentSourceBlock(BNLowLevelILFunction* func, BNBasicBlock* source);
59685960
BINARYNINJACOREAPI size_t BNLowLevelILGetInstructionStart(
59695961
BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr);
5962+
BINARYNINJACOREAPI size_t* BNLowLevelILGetInstructionsAt(
5963+
BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count);
5964+
BINARYNINJACOREAPI size_t* BNLowLevelILGetExitsForInstruction(
5965+
BNLowLevelILFunction* func, size_t instr, size_t* count);
59705966
BINARYNINJACOREAPI void BNLowLevelILClearIndirectBranches(BNLowLevelILFunction* func);
59715967
BINARYNINJACOREAPI void BNLowLevelILSetIndirectBranches(
59725968
BNLowLevelILFunction* func, BNArchitectureAndAddress* branches, size_t count);

function.cpp

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -460,39 +460,6 @@ Ref<LowLevelILFunction> Function::GetLowLevelILIfAvailable() const
460460
}
461461

462462

463-
size_t Function::GetLowLevelILForInstruction(Architecture* arch, uint64_t addr)
464-
{
465-
return BNGetLowLevelILForInstruction(m_object, arch->GetObject(), addr);
466-
}
467-
468-
469-
set<size_t> Function::GetLowLevelILInstructionsForAddress(Architecture* arch, uint64_t addr)
470-
{
471-
size_t count;
472-
size_t* instrs = BNGetLowLevelILInstructionsForAddress(m_object, arch->GetObject(), addr, &count);
473-
474-
set<size_t> result;
475-
for (size_t i = 0; i < count; i++)
476-
result.insert(instrs[i]);
477-
478-
BNFreeILInstructionList(instrs);
479-
return result;
480-
}
481-
482-
483-
vector<size_t> Function::GetLowLevelILExitsForInstruction(Architecture* arch, uint64_t addr)
484-
{
485-
size_t count;
486-
size_t* exits = BNGetLowLevelILExitsForInstruction(m_object, arch->GetObject(), addr, &count);
487-
488-
vector<size_t> result;
489-
result.insert(result.end(), exits, &exits[count]);
490-
491-
BNFreeILInstructionList(exits);
492-
return result;
493-
}
494-
495-
496463
RegisterValue RegisterValue::FromAPIObject(const BNRegisterValue& value)
497464
{
498465
RegisterValue result;
@@ -795,26 +762,6 @@ Ref<LowLevelILFunction> Function::GetLiftedILIfAvailable() const
795762
}
796763

797764

798-
size_t Function::GetLiftedILForInstruction(Architecture* arch, uint64_t addr)
799-
{
800-
return BNGetLiftedILForInstruction(m_object, arch->GetObject(), addr);
801-
}
802-
803-
804-
set<size_t> Function::GetLiftedILInstructionsForAddress(Architecture* arch, uint64_t addr)
805-
{
806-
size_t count;
807-
size_t* instrs = BNGetLiftedILInstructionsForAddress(m_object, arch->GetObject(), addr, &count);
808-
809-
set<size_t> result;
810-
for (size_t i = 0; i < count; i++)
811-
result.insert(instrs[i]);
812-
813-
BNFreeILInstructionList(instrs);
814-
return result;
815-
}
816-
817-
818765
set<size_t> Function::GetLiftedILFlagUsesForDefinition(size_t i, uint32_t flag)
819766
{
820767
size_t count;

lowlevelil.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,29 @@ size_t LowLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr
9696
return BNLowLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr);
9797
}
9898

99+
std::set<size_t> LowLevelILFunction::GetInstructionsAt(Architecture *arch, uint64_t addr)
100+
{
101+
size_t count;
102+
size_t* instructions = BNLowLevelILGetInstructionsAt(m_object, arch ? arch->GetObject() : nullptr, addr, &count);
103+
std::set<size_t> result;
104+
for (size_t i = 0; i < count; i++)
105+
result.insert(instructions[i]);
106+
BNFreeILInstructionList(instructions);
107+
return result;
108+
}
109+
110+
std::vector<size_t> LowLevelILFunction::GetExitsForInstruction(size_t i)
111+
{
112+
size_t count;
113+
size_t* instructions = BNLowLevelILGetExitsForInstruction(m_object, i, &count);
114+
std::vector<size_t> result;
115+
result.reserve(count);
116+
for (size_t j = 0; j < count; j++)
117+
result.push_back(instructions[j]);
118+
BNFreeILInstructionList(instructions);
119+
return result;
120+
}
121+
99122

100123
void LowLevelILFunction::ClearIndirectBranches()
101124
{

plugins/efi_resolver/src/Resolver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ vector<HighLevelILInstruction> Resolver::HighLevelILExprsAt(Ref<Function> func,
308308
auto mlil = func->GetMediumLevelIL();
309309
auto hlil = func->GetHighLevelIL();
310310

311-
size_t llilIdx = func->GetLowLevelILForInstruction(arch, addr);
311+
size_t llilIdx = llil->GetInstructionStart(arch, addr);
312312
size_t llilExprIdx = llil->GetIndexForInstruction(llilIdx);
313313
auto mlilIdxes = llil->GetMediumLevelILExprIndexes(llilExprIdx);
314314

python/function.py

Lines changed: 23 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1852,15 +1852,12 @@ def get_low_level_il_at(
18521852
>>> func.get_low_level_il_at(func.start)
18531853
<il: push(rbp)>
18541854
"""
1855-
if arch is None:
1856-
arch = self.arch
1857-
1858-
idx = core.BNGetLowLevelILForInstruction(self.handle, arch.handle, addr)
1859-
18601855
llil = self.llil
1861-
if llil is None or idx == len(llil):
1856+
if llil is None:
1857+
return None
1858+
idx = llil.get_instruction_start(addr, arch)
1859+
if idx is None:
18621860
return None
1863-
18641861
return llil[idx]
18651862

18661863
def get_low_level_ils_at(self, addr: int,
@@ -1881,19 +1878,7 @@ def get_low_level_ils_at(self, addr: int,
18811878
llil = self.llil
18821879
if llil is None:
18831880
return []
1884-
1885-
if arch is None:
1886-
arch = self.arch
1887-
count = ctypes.c_ulonglong()
1888-
instrs = core.BNGetLowLevelILInstructionsForAddress(self.handle, arch.handle, addr, count)
1889-
assert instrs is not None, "core.BNGetLowLevelILInstructionsForAddress returned None"
1890-
try:
1891-
result = []
1892-
for i in range(0, count.value):
1893-
result.append(llil[instrs[i]])
1894-
return result
1895-
finally:
1896-
core.BNFreeILInstructionList(instrs)
1881+
return [llil[i] for i in llil.get_instructions_at(addr, arch)]
18971882

18981883
def get_llil_at(self, addr: int,
18991884
arch: Optional['architecture.Architecture'] = None) -> Optional['lowlevelil.LowLevelILInstruction']:
@@ -1929,33 +1914,16 @@ def get_llils_at(self, addr: int,
19291914
llil = self.llil
19301915
if llil is None:
19311916
return []
1932-
1933-
if arch is None:
1934-
arch = self.arch
1935-
count = ctypes.c_ulonglong()
1936-
instrs = core.BNGetLowLevelILInstructionsForAddress(self.handle, arch.handle, addr, count)
1937-
assert instrs is not None, "core.BNGetLowLevelILInstructionsForAddress returned None"
1938-
try:
1939-
result = []
1940-
for i in range(0, count.value):
1941-
result.append(llil[instrs[i]])
1942-
return result
1943-
finally:
1944-
core.BNFreeILInstructionList(instrs)
1917+
return [llil[i] for i in llil.get_instructions_at(addr, arch)]
19451918

19461919
def get_low_level_il_exits_at(self, addr: int, arch: Optional['architecture.Architecture'] = None) -> List[int]:
1947-
if arch is None:
1948-
arch = self.arch
1949-
count = ctypes.c_ulonglong()
1950-
exits = core.BNGetLowLevelILExitsForInstruction(self.handle, arch.handle, addr, count)
1951-
assert exits is not None, "core.BNGetLowLevelILExitsForInstruction returned None"
1952-
try:
1953-
result = []
1954-
for i in range(0, count.value):
1955-
result.append(exits[i])
1956-
return result
1957-
finally:
1958-
core.BNFreeILInstructionList(exits)
1920+
llil = self.llil
1921+
if llil is None:
1922+
return []
1923+
idx = llil.get_instruction_start(addr, arch)
1924+
if idx is None:
1925+
return []
1926+
return llil.get_exits_for_instr(idx)
19591927

19601928
def get_constant_data(self, state: RegisterValueType, value: int, size: int = 0) -> databuffer.DataBuffer:
19611929
return databuffer.DataBuffer(handle=core.BNGetConstantData(self.handle, state, value, size, None))
@@ -2144,15 +2112,13 @@ def get_stack_vars_referenced_by_address_if_available(
21442112
def get_lifted_il_at(
21452113
self, addr: int, arch: Optional['architecture.Architecture'] = None
21462114
) -> Optional['lowlevelil.LowLevelILInstruction']:
2147-
if arch is None:
2148-
arch = self.arch
2149-
2150-
idx = core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr)
2151-
2152-
if idx == len(self.lifted_il):
2115+
lifted_il = self.lifted_il
2116+
if lifted_il is None:
21532117
return None
2154-
2155-
return self.lifted_il[idx]
2118+
idx = lifted_il.get_instruction_start(addr, arch)
2119+
if idx is None:
2120+
return None
2121+
return lifted_il[idx]
21562122

21572123
def get_lifted_ils_at(
21582124
self, addr: int, arch: Optional['architecture.Architecture'] = None
@@ -2168,16 +2134,10 @@ def get_lifted_ils_at(
21682134
>>> func.get_lifted_ils_at(func.start)
21692135
[<il: push(rbp)>]
21702136
"""
2171-
if arch is None:
2172-
arch = self.arch
2173-
count = ctypes.c_ulonglong()
2174-
instrs = core.BNGetLiftedILInstructionsForAddress(self.handle, arch.handle, addr, count)
2175-
assert instrs is not None, "core.BNGetLiftedILInstructionsForAddress returned None"
2176-
result = []
2177-
for i in range(0, count.value):
2178-
result.append(self.lifted_il[instrs[i]])
2179-
core.BNFreeILInstructionList(instrs)
2180-
return result
2137+
lifted_il = self.lifted_il
2138+
if lifted_il is None:
2139+
return []
2140+
return [lifted_il[i] for i in lifted_il.get_instructions_at(addr, arch)]
21812141

21822142
def get_constants_referenced_by(self, addr: int,
21832143
arch: Optional['architecture.Architecture'] = None) -> List[variable.ConstantReference]:

python/lowlevelil.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3799,6 +3799,45 @@ def get_instruction_start(self, addr: int, arch: Optional['architecture.Architec
37993799
return None
38003800
return InstructionIndex(result)
38013801

3802+
def get_instructions_at(self, addr: int, arch: Optional['architecture.Architecture'] = None) -> List[InstructionIndex]:
3803+
"""
3804+
``get_instructions_at`` gets the InstructionIndex(s) corresponding to the given virtual address
3805+
See the `docs for mappings between ils <https://dev-docs.binary.ninja/dev/concepts.html#mapping-between-ils>`_ for more information.
3806+
3807+
:param int addr: virtual address of the instruction to be queried
3808+
:param Architecture arch: (optional) Architecture for the given function
3809+
:rtype: list(InstructionIndex)
3810+
:Example:
3811+
3812+
>>> func = next(bv.functions)
3813+
>>> func.llil.get_instructions_at(func.start)
3814+
[0]
3815+
"""
3816+
if arch is None:
3817+
arch = self.arch
3818+
count = ctypes.c_ulonglong()
3819+
instrs = core.BNLowLevelILGetInstructionsAt(self.handle, arch.handle, addr, count)
3820+
assert instrs is not None, "core.BNLowLevelILGetInstructionsAt returned None"
3821+
try:
3822+
result = []
3823+
for i in range(0, count.value):
3824+
result.append(instrs[i])
3825+
return result
3826+
finally:
3827+
core.BNFreeILInstructionList(instrs)
3828+
3829+
def get_exits_for_instr(self, idx: InstructionIndex) -> List[InstructionIndex]:
3830+
count = ctypes.c_ulonglong()
3831+
exits = core.BNLowLevelILGetExitsForInstruction(self.handle, idx, count)
3832+
assert exits is not None, "core.BNLowLevelILGetExitsForInstruction returned None"
3833+
try:
3834+
result = []
3835+
for i in range(0, count.value):
3836+
result.append(exits[i])
3837+
return result
3838+
finally:
3839+
core.BNFreeILInstructionList(exits)
3840+
38023841
def clear_indirect_branches(self) -> None:
38033842
core.BNLowLevelILClearIndirectBranches(self.handle)
38043843

0 commit comments

Comments
 (0)