From 95a7be141a07a20b8465981b01116fcafb6b5f41 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 3 Oct 2017 23:07:48 -0400 Subject: Adding support for register stacks in IL (for x87) --- architecture.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'architecture.cpp') diff --git a/architecture.cpp b/architecture.cpp index eb588394..56af3f80 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -359,6 +359,34 @@ uint32_t* Architecture::GetGlobalRegistersCallback(void* ctxt, size_t* count) } +char* Architecture::GetRegisterStackNameCallback(void* ctxt, uint32_t regStack) +{ + Architecture* arch = (Architecture*)ctxt; + string result = arch->GetRegisterStackName(regStack); + return BNAllocString(result.c_str()); +} + + +uint32_t* Architecture::GetAllRegisterStacksCallback(void* ctxt, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector regs = arch->GetAllRegisterStacks(); + *count = regs.size(); + + uint32_t* result = new uint32_t[regs.size()]; + for (size_t i = 0; i < regs.size(); i++) + result[i] = regs[i]; + return result; +} + + +void Architecture::GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result) +{ + Architecture* arch = (Architecture*)ctxt; + *result = arch->GetRegisterStackInfo(regStack); +} + + bool Architecture::AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors) { Architecture* arch = (Architecture*)ctxt; @@ -467,6 +495,9 @@ void Architecture::Register(Architecture* arch) callbacks.getStackPointerRegister = GetStackPointerRegisterCallback; callbacks.getLinkRegister = GetLinkRegisterCallback; callbacks.getGlobalRegisters = GetGlobalRegistersCallback; + callbacks.getRegisterStackName = GetRegisterStackNameCallback; + callbacks.getAllRegisterStacks = GetAllRegisterStacksCallback; + callbacks.getRegisterStackInfo = GetRegisterStackInfoCallback; callbacks.assemble = AssembleCallback; callbacks.isNeverBranchPatchAvailable = IsNeverBranchPatchAvailableCallback; callbacks.isAlwaysBranchPatchAvailable = IsAlwaysBranchPatchAvailableCallback; @@ -682,6 +713,36 @@ bool Architecture::IsGlobalRegister(uint32_t reg) } +string Architecture::GetRegisterStackName(uint32_t regStack) +{ + char regStr[32]; + sprintf(regStr, "reg_stack_%" PRIu32, regStack); + return regStr; +} + + +vector Architecture::GetAllRegisterStacks() +{ + return vector(); +} + + +BNRegisterStackInfo Architecture::GetRegisterStackInfo(uint32_t) +{ + BNRegisterStackInfo result; + result.firstStorageReg = BN_INVALID_REGISTER; + result.count = 0; + result.stackTopReg = BN_INVALID_REGISTER; + return result; +} + + +uint32_t Architecture::GetRegisterStackForRegister(uint32_t reg) +{ + return BNGetArchitectureRegisterStackForRegister(m_object, reg); +} + + vector Architecture::GetModifiedRegistersOnWrite(uint32_t reg) { size_t count; @@ -1116,6 +1177,35 @@ vector CoreArchitecture::GetGlobalRegisters() } +string CoreArchitecture::GetRegisterStackName(uint32_t regStack) +{ + char* name = BNGetArchitectureRegisterStackName(m_object, regStack); + string result = name; + BNFreeString(name); + return result; +} + + +vector CoreArchitecture::GetAllRegisterStacks() +{ + size_t count; + uint32_t* regs = BNGetAllArchitectureRegisterStacks(m_object, &count); + + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(regs[i]); + + BNFreeRegisterList(regs); + return result; +} + + +BNRegisterStackInfo CoreArchitecture::GetRegisterStackInfo(uint32_t regStack) +{ + return BNGetArchitectureRegisterStackInfo(m_object, regStack); +} + + bool CoreArchitecture::Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) { char* errorStr = nullptr; -- cgit v1.3.1 From d5db0ddb807265b295bb6b4ff07613776945c92b Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 23 Oct 2017 21:45:37 -0400 Subject: Top relative register stack access as a normal register --- architecture.cpp | 4 +++- binaryninjacore.h | 4 ++-- lowlevelilinstruction.cpp | 2 +- python/architecture.py | 28 +++++++++++++++++++++++----- python/function.py | 3 ++- 5 files changed, 31 insertions(+), 10 deletions(-) (limited to 'architecture.cpp') diff --git a/architecture.cpp b/architecture.cpp index 56af3f80..169a8c0c 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -731,7 +731,9 @@ BNRegisterStackInfo Architecture::GetRegisterStackInfo(uint32_t) { BNRegisterStackInfo result; result.firstStorageReg = BN_INVALID_REGISTER; - result.count = 0; + result.topRelativeCount = BN_INVALID_REGISTER; + result.storageCount = 0; + result.topRelativeCount = 0; result.stackTopReg = BN_INVALID_REGISTER; return result; } diff --git a/binaryninjacore.h b/binaryninjacore.h index f50c28c8..c32d42e3 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -679,8 +679,8 @@ extern "C" struct BNRegisterStackInfo { - uint32_t firstStorageReg; - uint32_t count; + uint32_t firstStorageReg, firstTopRelativeReg; + uint32_t storageCount, topRelativeCount; uint32_t stackTopReg; }; diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 4130dd2a..91af36b1 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -2179,7 +2179,7 @@ ExprId LowLevelILFunction::SetRegisterStackTopRelativeSSA(size_t size, uint32_t ExprId LowLevelILFunction::SetRegisterStackAbsoluteSSA(size_t size, uint32_t regStack, size_t destVersion, size_t srcVersion, uint32_t reg, ExprId val, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_SET_REG_STACK_REL_SSA, loc, size, 0, + return AddExprWithLocation(LLIL_SET_REG_STACK_ABS_SSA, loc, size, 0, AddExprWithLocation(LLIL_REG_STACK_DEST_SSA, loc, size, 0, regStack, destVersion, srcVersion), reg, val); } diff --git a/python/architecture.py b/python/architecture.py index 289b0abd..04179e7f 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -225,10 +225,13 @@ class Architecture(object): name = core.BNGetArchitectureRegisterStackName(self.handle, regs[i]) info = core.BNGetArchitectureRegisterStackInfo(self.handle, regs[i]) storage = [] - for j in xrange(0, info.count): + for j in xrange(0, info.storageCount): storage.append(core.BNGetArchitectureRegisterName(self.handle, info.firstStorageReg + j)) + top_rel = [] + for j in xrange(0, info.topRelativeCount): + top_rel.append(core.BNGetArchitectureRegisterName(self.handle, info.firstTopRelativeReg + j)) top = core.BNGetArchitectureRegisterName(self.handle, info.stackTopReg) - self.reg_stacks[name] = function.RegisterStackInfo(storage, top) + self.reg_stacks[name] = function.RegisterStackInfo(storage, top_rel, top) core.BNFreeRegisterList(regs) else: startup._init_plugins() @@ -310,6 +313,11 @@ class Architecture(object): self._regs_by_index[reg_index] = reg self.regs[reg].index = reg_index reg_index += 1 + for reg in info.top_relative_regs: + self._all_regs[reg] = reg_index + self._regs_by_index[reg_index] = reg + self.regs[reg].index = reg_index + reg_index += 1 if reg_stack not in self._all_reg_stacks: self._all_reg_stacks[reg_stack] = reg_stack_index self._reg_stacks_by_index[reg_stack_index] = reg_stack @@ -808,17 +816,27 @@ class Architecture(object): try: if reg_stack not in self._reg_stacks_by_index: result[0].firstStorageReg = 0 - result[0].count = 0 + result[0].firstTopRelativeReg = 0 + result[0].storageCount = 0 + result[0].topRelativeCount = 0 result[0].stackTopReg = 0 return info = self.__class__.regs[self._reg_stacks_by_index[reg_stack]] result[0].firstStorageReg = self._all_regs[info.storage_regs[0]] - result[0].count = len(info.storage_regs) + result[0].storageCount = len(info.storage_regs) + if len(info.top_relative_regs) > 0: + result[0].firstTopRelativeReg = self._all_regs[info.top_relative_regs[0]] + result[0].topRelativeCount = len(info.top_relative_regs) + else: + result[0].firstTopRelativeReg = 0 + result[0].topRelativeCount = 0 result[0].stackTopReg = self._all_regs[info.stack_top_reg] except KeyError: log.log_error(traceback.format_exc()) result[0].firstStorageReg = 0 - result[0].count = 0 + result[0].firstTopRelativeReg = 0 + result[0].storageCount = 0 + result[0].topRelativeCount = 0 result[0].stackTopReg = 0 def _assemble(self, ctxt, code, addr, result, errors): diff --git a/python/function.py b/python/function.py index eb8796f1..ba00147e 100644 --- a/python/function.py +++ b/python/function.py @@ -1727,8 +1727,9 @@ class RegisterInfo(object): class RegisterStackInfo(object): - def __init__(self, storage_regs, stack_top_reg): + def __init__(self, storage_regs, top_relative_regs, stack_top_reg): self.storage_regs = storage_regs + self.top_relative_regs = top_relative_regs self.stack_top_reg = stack_top_reg def __repr__(self): -- cgit v1.3.1 From 0cc77206c79257d49013c3a3ed1bf889c85b10d1 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Sun, 14 Jan 2018 03:42:04 -0500 Subject: Container Memory Reservations. --- architecture.cpp | 11 +++++++++++ backgroundtask.cpp | 1 + basicblock.cpp | 4 ++++ binaryview.cpp | 20 ++++++++++++++++++++ binaryviewtype.cpp | 2 ++ function.cpp | 11 +++++++++-- functiongraph.cpp | 2 ++ functiongraphblock.cpp | 3 +++ lowlevelil.cpp | 8 ++++---- lowlevelilinstruction.cpp | 7 ++++--- mediumlevelil.cpp | 9 +++++---- mediumlevelilinstruction.cpp | 6 +++--- metadata.cpp | 1 + platform.cpp | 6 ++++++ plugin.cpp | 1 + settings.cpp | 1 + transform.cpp | 2 ++ type.cpp | 12 ++++++------ update.cpp | 2 ++ 19 files changed, 87 insertions(+), 22 deletions(-) (limited to 'architecture.cpp') diff --git a/architecture.cpp b/architecture.cpp index 821f4c7b..7b74e43b 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -507,6 +507,7 @@ vector> Architecture::GetList() archs = BNGetArchitectureList(&count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreArchitecture(archs[i])); @@ -703,6 +704,7 @@ vector Architecture::GetModifiedRegistersOnWrite(uint32_t reg) uint32_t* regs = BNGetModifiedArchitectureRegistersOnWrite(m_object, reg, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -814,6 +816,7 @@ vector> Architecture::GetCallingConventions() BNCallingConvention** list = BNGetArchitectureCallingConventions(m_object, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreCallingConvention(BNNewCallingConventionReference(list[i]))); @@ -957,6 +960,7 @@ bool CoreArchitecture::GetInstructionText(const uint8_t* data, uint64_t addr, si if (!BNGetInstructionText(m_object, data, addr, &len, &tokens, &count)) return false; + result.reserve(count); for (size_t i = 0; i < count; i++) { result.emplace_back(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, @@ -1007,6 +1011,7 @@ vector CoreArchitecture::GetFullWidthRegisters() uint32_t* regs = BNGetFullWidthArchitectureRegisters(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -1021,6 +1026,7 @@ vector CoreArchitecture::GetAllRegisters() uint32_t* regs = BNGetAllArchitectureRegisters(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -1035,6 +1041,7 @@ vector CoreArchitecture::GetAllFlags() uint32_t* regs = BNGetAllArchitectureFlags(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -1049,6 +1056,7 @@ vector CoreArchitecture::GetAllFlagWriteTypes() uint32_t* regs = BNGetAllArchitectureFlagWriteTypes(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); @@ -1069,6 +1077,7 @@ vector CoreArchitecture::GetFlagsRequiredForFlagCondition(BNLowLevelIL uint32_t* flags = BNGetArchitectureFlagsRequiredForFlagCondition(m_object, cond, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(flags[i]); @@ -1083,6 +1092,7 @@ vector CoreArchitecture::GetFlagsWrittenByFlagWriteType(uint32_t write uint32_t* flags = BNGetArchitectureFlagsWrittenByFlagWriteType(m_object, writeType, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(flags[i]); @@ -1129,6 +1139,7 @@ vector CoreArchitecture::GetGlobalRegisters() uint32_t* regs = BNGetArchitectureGlobalRegisters(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(regs[i]); diff --git a/backgroundtask.cpp b/backgroundtask.cpp index aebf980c..b2d4a738 100644 --- a/backgroundtask.cpp +++ b/backgroundtask.cpp @@ -67,6 +67,7 @@ vector> BackgroundTask::GetRunningTasks() BNBackgroundTask** tasks = BNGetRunningBackgroundTasks(&count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BackgroundTask(BNNewBackgroundTaskReference(tasks[i]))); diff --git a/basicblock.cpp b/basicblock.cpp index 89ace134..d42a1038 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -120,6 +120,7 @@ vector BasicBlock::GetOutgoingEdges() const BNBasicBlockEdge* array = BNGetBasicBlockOutgoingEdges(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { BasicBlockEdge edge; @@ -140,6 +141,7 @@ vector BasicBlock::GetIncomingEdges() const BNBasicBlockEdge* array = BNGetBasicBlockIncomingEdges(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { BasicBlockEdge edge; @@ -269,10 +271,12 @@ vector BasicBlock::GetDisassemblyText(DisassemblySettings* BNDisassemblyTextLine* lines = BNGetBasicBlockDisassemblyText(m_object, settings->GetObject(), &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { DisassemblyTextLine line; line.addr = lines[i].addr; + line.tokens.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { InstructionTextToken token; diff --git a/binaryview.cpp b/binaryview.cpp index 00cd294f..0ee428e1 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -670,6 +670,7 @@ vector BinaryView::GetModification(uint64_t offset, size_t len = BNGetModificationArray(m_object, offset, mod, len); vector result; + result.reserve(len); for (size_t i = 0; i < len; i++) result.push_back(mod[i]); @@ -988,6 +989,7 @@ vector> BinaryView::GetAnalysisFunctionList() BNFunction** list = BNGetAnalysisFunctionList(m_object, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Function(BNNewFunctionReference(list[i]))); @@ -1026,6 +1028,7 @@ vector> BinaryView::GetAnalysisFunctionsForAddress(uint64_t addr) BNFunction** list = BNGetAnalysisFunctionsForAddress(m_object, addr, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Function(BNNewFunctionReference(list[i]))); @@ -1058,6 +1061,7 @@ vector> BinaryView::GetBasicBlocksForAddress(uint64_t addr) BNBasicBlock** blocks = BNGetBasicBlocksForAddress(m_object, addr, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -1072,6 +1076,7 @@ vector> BinaryView::GetBasicBlocksStartingAtAddress(uint64_t add BNBasicBlock** blocks = BNGetBasicBlocksStartingAtAddress(m_object, addr, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -1086,6 +1091,7 @@ vector BinaryView::GetCodeReferences(uint64_t addr) BNReferenceSource* refs = BNGetCodeReferences(m_object, addr, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { ReferenceSource src; @@ -1106,6 +1112,7 @@ vector BinaryView::GetCodeReferences(uint64_t addr, uint64_t le BNReferenceSource* refs = BNGetCodeReferencesInRange(m_object, addr, len, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { ReferenceSource src; @@ -1144,6 +1151,7 @@ vector> BinaryView::GetSymbolsByName(const string& name) BNSymbol** syms = BNGetSymbolsByName(m_object, name.c_str(), &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1158,6 +1166,7 @@ vector> BinaryView::GetSymbols() BNSymbol** syms = BNGetSymbols(m_object, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1172,6 +1181,7 @@ vector> BinaryView::GetSymbols(uint64_t start, uint64_t len) BNSymbol** syms = BNGetSymbolsInRange(m_object, start, len, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1186,6 +1196,7 @@ vector> BinaryView::GetSymbolsOfType(BNSymbolType type) BNSymbol** syms = BNGetSymbolsOfType(m_object, type, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1200,6 +1211,7 @@ vector> BinaryView::GetSymbolsOfType(BNSymbolType type, uint64_t sta BNSymbol** syms = BNGetSymbolsOfTypeInRange(m_object, type, start, len, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); @@ -1412,6 +1424,7 @@ vector BinaryView::GetPreviousLinearDisassemblyLines(Line settings ? settings->GetObject() : nullptr, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { LinearDisassemblyLine line; @@ -1420,6 +1433,7 @@ vector BinaryView::GetPreviousLinearDisassemblyLines(Line line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; + line.contents.tokens.reserve(lines[i].contents.count); for (size_t j = 0; j < lines[i].contents.count; j++) { InstructionTextToken token; @@ -1458,6 +1472,7 @@ vector BinaryView::GetNextLinearDisassemblyLines(LinearDi settings ? settings->GetObject() : nullptr, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { LinearDisassemblyLine line; @@ -1466,6 +1481,7 @@ vector BinaryView::GetNextLinearDisassemblyLines(LinearDi line.block = lines[i].block ? new BasicBlock(BNNewBasicBlockReference(lines[i].block)) : nullptr; line.lineOffset = lines[i].lineOffset; line.contents.addr = lines[i].contents.addr; + line.contents.tokens.reserve(lines[i].contents.count); for (size_t j = 0; j < lines[i].contents.count; j++) { InstructionTextToken token; @@ -1704,6 +1720,7 @@ vector BinaryView::GetSegments() BNSegment* segments = BNGetSegments(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { Segment segment; @@ -1777,6 +1794,7 @@ vector
BinaryView::GetSections() BNSection* sections = BNGetSections(m_object, &count); vector
result; + result.reserve(count); for (size_t i = 0; i < count; i++) { Section section; @@ -1804,6 +1822,7 @@ vector
BinaryView::GetSectionsAt(uint64_t addr) BNSection* sections = BNGetSectionsAt(m_object, addr, &count); vector
result; + result.reserve(count); for (size_t i = 0; i < count; i++) { Section section; @@ -1855,6 +1874,7 @@ vector BinaryView::GetUniqueSectionNames(const vector& names) char** outgoingNames = BNGetUniqueSectionNames(m_object, incomingNames, names.size()); vector result; + result.reserve(names.size()); for (size_t i = 0; i < names.size(); i++) result.push_back(outgoingNames[i]); diff --git a/binaryviewtype.cpp b/binaryviewtype.cpp index e23838f6..e8ef4f53 100644 --- a/binaryviewtype.cpp +++ b/binaryviewtype.cpp @@ -83,6 +83,7 @@ vector> BinaryViewType::GetViewTypes() types = BNGetBinaryViewTypes(&count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreBinaryViewType(types[i])); @@ -98,6 +99,7 @@ vector> BinaryViewType::GetViewTypesForData(BinaryView* data types = BNGetBinaryViewTypesForData(data->GetObject(), &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreBinaryViewType(types[i])); diff --git a/function.cpp b/function.cpp index 1226e399..cb4377b2 100644 --- a/function.cpp +++ b/function.cpp @@ -174,6 +174,7 @@ vector> Function::GetBasicBlocks() const BNBasicBlock** blocks = BNGetFunctionBasicBlockList(m_object, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -379,6 +380,7 @@ vector Function::GetStackVariablesReferencedByInstructio BNStackVariableReference* refs = BNGetStackVariablesReferencedByInstruction(m_object, arch->GetObject(), addr, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { StackVariableReference ref; @@ -502,10 +504,9 @@ Confidence> Function::GetParameterVariables() const { BNParameterVariablesWithConfidence vars = BNGetFunctionParameterVariables(m_object); vector varList; + varList.reserve(vars.count); for (size_t i = 0; i < vars.count; i++) - { varList.emplace_back(vars.vars[i].type, vars.vars[i].index, vars.vars[i].storage); - } Confidence> result(varList, vars.confidence); BNFreeParameterVariables(&vars); return result; @@ -897,6 +898,7 @@ vector Function::GetIndirectBranches() BNIndirectBranchInfo* branches = BNGetIndirectBranches(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { IndirectBranchInfo b; @@ -919,6 +921,7 @@ vector Function::GetIndirectBranchesAt(Architecture* arch, u BNIndirectBranchInfo* branches = BNGetIndirectBranchesAt(m_object, arch->GetObject(), addr, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { IndirectBranchInfo b; @@ -941,9 +944,11 @@ vector> Function::GetBlockAnnotations(Architecture* BNInstructionTextLine* lines = BNGetFunctionBlockAnnotations(m_object, arch->GetObject(), addr, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { vector line; + line.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { InstructionTextToken token; @@ -1155,10 +1160,12 @@ vector Function::GetTypeTokens(DisassemblySettings* setting settings ? settings->GetObject() : nullptr, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { DisassemblyTextLine line; line.addr = lines[i].addr; + line.tokens.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { InstructionTextToken token; diff --git a/functiongraph.cpp b/functiongraph.cpp index 7e5ec079..77754913 100644 --- a/functiongraph.cpp +++ b/functiongraph.cpp @@ -110,6 +110,7 @@ vector> FunctionGraph::GetBlocks() BNFunctionGraphBlock** blocks = BNGetFunctionGraphBlocks(m_graph, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { auto block = m_cachedBlocks.find(blocks[i]); @@ -148,6 +149,7 @@ vector> FunctionGraph::GetBlocksInRegion(int left, int t BNFunctionGraphBlock** blocks = BNGetFunctionGraphBlocksInRegion(m_graph, left, top, right, bottom, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) { auto block = m_cachedBlocks.find(blocks[i]); diff --git a/functiongraphblock.cpp b/functiongraphblock.cpp index 20b2515b..06a35eee 100644 --- a/functiongraphblock.cpp +++ b/functiongraphblock.cpp @@ -89,10 +89,12 @@ const vector& FunctionGraphBlock::GetLines() BNDisassemblyTextLine* lines = BNGetFunctionGraphBlockLines(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { DisassemblyTextLine line; line.addr = lines[i].addr; + line.tokens.reserve(lines[i].count); for (size_t j = 0; j < lines[i].count; j++) { InstructionTextToken token; @@ -125,6 +127,7 @@ const vector& FunctionGraphBlock::GetOutgoingEdges() BNFunctionGraphEdge* edges = BNGetFunctionGraphBlockOutgoingEdges(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { FunctionGraphEdge edge; diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 6c59b704..5e985a8e 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -176,6 +176,7 @@ vector LowLevelILFunction::GetOperandList(ExprId expr, size_t listOper size_t count; uint64_t* operands = BNLowLevelILGetOperandList(m_object, expr, listOperand, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(operands[i]); BNLowLevelILFreeOperandList(operands); @@ -390,11 +391,10 @@ bool LowLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector> LowLevelILFunction::GetBasicBlocks() const BNBasicBlock** blocks = BNGetLowLevelILBasicBlockList(m_object, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index d85e4f17..53b1e390 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -178,15 +178,16 @@ unordered_map> }; -static unordered_map> - GetOperandIndexForOperandUsages() +static unordered_map> GetOperandIndexForOperandUsages() { unordered_map> result; + result.reserve(LowLevelILInstructionBase::operationOperandUsage.size()); for (auto& operation : LowLevelILInstructionBase::operationOperandUsage) { result[operation.first] = unordered_map(); size_t operand = 0; + result[operation.first].reserve(operation.second.size()); for (auto usage : operation.second) { result[operation.first][usage] = operand; @@ -377,7 +378,7 @@ uint64_t LowLevelILIntegerList::ListIterator::operator*() LowLevelILIntegerList::LowLevelILIntegerList(LowLevelILFunction* func, - const BNLowLevelILInstruction& instr, size_t count) +const BNLowLevelILInstruction& instr, size_t count) { m_start.function = func; #ifdef BINARYNINJACORE_LIBRARY diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 2cd5a233..0a28bd49 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -157,6 +157,7 @@ vector MediumLevelILFunction::GetOperandList(ExprId expr, size_t listO size_t count; uint64_t* operands = BNMediumLevelILGetOperandList(m_object, expr, listOperand, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(operands[i]); BNMediumLevelILFreeOperandList(operands); @@ -338,11 +339,10 @@ bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector< return false; tokens.clear(); + tokens.reserve(count); for (size_t i = 0; i < count; i++) - { tokens.emplace_back(list[i].type, list[i].context, list[i].text, list[i].address, list[i].value, list[i].size, list[i].operand, list[i].confidence); - } BNFreeInstructionText(list, count); return true; @@ -359,11 +359,10 @@ bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arc return false; tokens.clear(); + tokens.reserve(count); for (size_t i = 0; i < count; i++) - { tokens.emplace_back(list[i].type, list[i].context, list[i].text, list[i].address, list[i].value, list[i].size, list[i].operand, list[i].confidence); - } BNFreeInstructionText(list, count); return true; @@ -396,6 +395,7 @@ vector> MediumLevelILFunction::GetBasicBlocks() const BNBasicBlock** blocks = BNGetMediumLevelILBasicBlockList(m_object, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); @@ -680,6 +680,7 @@ unordered_map MediumLevelILFunction::GetAllBranchD BNILBranchInstructionAndDependence* deps = BNGetAllMediumLevelILBranchDependence(m_object, instr, &count); unordered_map result; + result.reserve(count); for (size_t i = 0; i < count; i++) result[deps[i].branch] = deps[i].dependence; diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index ec6aa1c6..bb4d205a 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -205,14 +205,14 @@ unordered_map> }; -static unordered_map> - GetOperandIndexForOperandUsages() +static unordered_map> GetOperandIndexForOperandUsages() { unordered_map> result; + result.reserve(MediumLevelILInstructionBase::operationOperandUsage.size()); for (auto& operation : MediumLevelILInstructionBase::operationOperandUsage) { result[operation.first] = unordered_map(); - + result[operation.first].reserve(operation.second.size()); size_t operand = 0; for (auto usage : operation.second) { diff --git a/metadata.cpp b/metadata.cpp index f9c48b04..c111233f 100644 --- a/metadata.cpp +++ b/metadata.cpp @@ -144,6 +144,7 @@ vector> Metadata::GetArray() size_t size = 0; BNMetadata** data = BNMetadataGetArray(m_object, &size); vector> result; + result.reserve(size); for (size_t i = 0; i < size; i++) result.push_back(new Metadata(data[i])); return result; diff --git a/platform.cpp b/platform.cpp index a9ab888f..724901fe 100644 --- a/platform.cpp +++ b/platform.cpp @@ -72,6 +72,7 @@ vector> Platform::GetList() BNPlatform** list = BNGetPlatformList(&count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Platform(BNNewPlatformReference(list[i]))); @@ -86,6 +87,7 @@ vector> Platform::GetList(Architecture* arch) BNPlatform** list = BNGetPlatformListByArchitecture(arch->GetObject(), &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Platform(BNNewPlatformReference(list[i]))); @@ -100,6 +102,7 @@ vector> Platform::GetList(const string& os) BNPlatform** list = BNGetPlatformListByOS(os.c_str(), &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Platform(BNNewPlatformReference(list[i]))); @@ -114,6 +117,7 @@ vector> Platform::GetList(const string& os, Architecture* arch) BNPlatform** list = BNGetPlatformListByOSAndArchitecture(os.c_str(), arch->GetObject(), &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new Platform(BNNewPlatformReference(list[i]))); @@ -128,6 +132,7 @@ vector Platform::GetOSList() char** list = BNGetPlatformOSList(&count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(list[i]); @@ -178,6 +183,7 @@ vector> Platform::GetCallingConventions() const BNCallingConvention** list = BNGetPlatformCallingConventions(m_object, &count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreCallingConvention(BNNewCallingConventionReference(list[i]))); diff --git a/plugin.cpp b/plugin.cpp index 2378fdab..972ce28b 100644 --- a/plugin.cpp +++ b/plugin.cpp @@ -211,6 +211,7 @@ vector PluginCommand::GetList() vector result; size_t count; BNPluginCommand* commands = BNGetAllPluginCommands(&count); + result.reserve(count); for (size_t i = 0; i < count; i++) result.emplace_back(commands[i]); BNFreePluginCommandList(commands); diff --git a/settings.cpp b/settings.cpp index 6b9c4e3a..b5899e38 100644 --- a/settings.cpp +++ b/settings.cpp @@ -51,6 +51,7 @@ std::vector Setting::GetStringList(const std::string& pluginName, char** outBuffer = (char**)BNSettingGetStringList(pluginName.c_str(), name.c_str(), (const char**)buffer, &size); vector result; + result.reserve(size); for (size_t i = 0; i < size; i++) result.emplace_back(outBuffer[i]); diff --git a/transform.cpp b/transform.cpp index 29a665d0..0a6fdfe6 100644 --- a/transform.cpp +++ b/transform.cpp @@ -157,6 +157,7 @@ vector> Transform::GetTransformTypes() BNTransform** list = BNGetTransformTypeList(&count); vector> result; + result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreTransform(list[i])); @@ -229,6 +230,7 @@ vector CoreTransform::GetParameters() const BNTransformParameterInfo* list = BNGetTransformParameterList(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { TransformParameter param; diff --git a/type.cpp b/type.cpp index c158f53e..08b64713 100644 --- a/type.cpp +++ b/type.cpp @@ -355,6 +355,7 @@ vector Type::GetParameters() const BNFunctionParameter* types = BNGetTypeParameters(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { FunctionParameter param; @@ -474,11 +475,10 @@ vector Type::GetTokens(Platform* platform, uint8_t baseCon platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) - { result.emplace_back(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, tokens[i].value, tokens[i].size, tokens[i].operand, tokens[i].confidence); - } BNFreeTokenList(tokens, count); return result; @@ -492,11 +492,10 @@ vector Type::GetTokensBeforeName(Platform* platform, uint8 platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) - { result.emplace_back(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, tokens[i].value, tokens[i].size, tokens[i].operand, tokens[i].confidence); - } BNFreeTokenList(tokens, count); return result; @@ -510,11 +509,10 @@ vector Type::GetTokensAfterName(Platform* platform, uint8_ platform ? platform->GetObject() : nullptr, baseConfidence, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) - { result.emplace_back(tokens[i].type, tokens[i].context, tokens[i].text, tokens[i].address, tokens[i].value, tokens[i].size, tokens[i].operand, tokens[i].confidence); - } BNFreeTokenList(tokens, count); return result; @@ -882,6 +880,7 @@ vector Structure::GetMembers() const BNStructureMember* members = BNGetStructureMembers(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { StructureMember member; @@ -1001,6 +1000,7 @@ vector Enumeration::GetMembers() const BNEnumerationMember* members = BNGetEnumerationMembers(m_object, &count); vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { EnumerationMember member; diff --git a/update.cpp b/update.cpp index 0ec69892..ecdf4162 100644 --- a/update.cpp +++ b/update.cpp @@ -53,6 +53,7 @@ vector UpdateChannel::GetList() } vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { UpdateChannel channel; @@ -149,6 +150,7 @@ vector UpdateVersion::GetChannelVersions(const string& channel) } vector result; + result.reserve(count); for (size_t i = 0; i < count; i++) { UpdateVersion version; -- cgit v1.3.1 From 6430776b3de5ee6eb922a9356080ad07d5a92856 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 16 Jan 2018 16:25:30 -0500 Subject: Add classes and groups for semantic flags resolution --- architecture.cpp | 267 ++++++++++++++++++++++++++++-- binaryninjaapi.h | 48 +++++- binaryninjacore.h | 50 +++++- lowlevelilinstruction.cpp | 59 ++++++- lowlevelilinstruction.h | 16 ++ mediumlevelilinstruction.cpp | 8 + python/architecture.py | 382 +++++++++++++++++++++++++++++++++++++++---- python/lowlevelil.py | 58 ++++++- python/mediumlevelil.py | 1 + 9 files changed, 832 insertions(+), 57 deletions(-) (limited to 'architecture.cpp') diff --git a/architecture.cpp b/architecture.cpp index 3ca41741..571794c6 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -224,6 +224,22 @@ char* Architecture::GetFlagWriteTypeNameCallback(void* ctxt, uint32_t flags) } +char* Architecture::GetSemanticFlagClassNameCallback(void* ctxt, uint32_t semClass) +{ + Architecture* arch = (Architecture*)ctxt; + string result = arch->GetSemanticFlagClassName(semClass); + return BNAllocString(result.c_str()); +} + + +char* Architecture::GetSemanticFlagGroupNameCallback(void* ctxt, uint32_t semGroup) +{ + Architecture* arch = (Architecture*)ctxt; + string result = arch->GetSemanticFlagGroupName(semGroup); + return BNAllocString(result.c_str()); +} + + uint32_t* Architecture::GetFullWidthRegistersCallback(void* ctxt, size_t* count) { Architecture* arch = (Architecture*)ctxt; @@ -276,6 +292,32 @@ uint32_t* Architecture::GetAllFlagWriteTypesCallback(void* ctxt, size_t* count) } +uint32_t* Architecture::GetAllSemanticFlagClassesCallback(void* ctxt, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector regs = arch->GetAllSemanticFlagClasses(); + *count = regs.size(); + + uint32_t* result = new uint32_t[regs.size()]; + for (size_t i = 0; i < regs.size(); i++) + result[i] = regs[i]; + return result; +} + + +uint32_t* Architecture::GetAllSemanticFlagGroupsCallback(void* ctxt, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector regs = arch->GetAllSemanticFlagGroups(); + *count = regs.size(); + + uint32_t* result = new uint32_t[regs.size()]; + for (size_t i = 0; i < regs.size(); i++) + result[i] = regs[i]; + return result; +} + + BNFlagRole Architecture::GetFlagRoleCallback(void* ctxt, uint32_t flag) { Architecture* arch = (Architecture*)ctxt; @@ -283,10 +325,24 @@ BNFlagRole Architecture::GetFlagRoleCallback(void* ctxt, uint32_t flag) } -uint32_t* Architecture::GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, size_t* count) +uint32_t* Architecture::GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, + uint32_t semClass, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector flags = arch->GetFlagsRequiredForFlagCondition(cond, semClass); + *count = flags.size(); + + uint32_t* result = new uint32_t[flags.size()]; + for (size_t i = 0; i < flags.size(); i++) + result[i] = flags[i]; + return result; +} + + +uint32_t* Architecture::GetFlagsRequiredForSemanticFlagGroupCallback(void* ctxt, uint32_t semGroup, size_t* count) { Architecture* arch = (Architecture*)ctxt; - vector flags = arch->GetFlagsRequiredForFlagCondition(cond); + vector flags = arch->GetFlagsRequiredForSemanticFlagGroup(semGroup); *count = flags.size(); uint32_t* result = new uint32_t[flags.size()]; @@ -296,6 +352,31 @@ uint32_t* Architecture::GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNL } +BNFlagConditionForSemanticClass* Architecture::GetFlagConditionsForSemanticFlagGroupCallback(void* ctxt, + uint32_t semGroup, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + map conditions = arch->GetFlagConditionsForSemanticFlagGroup(semGroup); + *count = conditions.size(); + + BNFlagConditionForSemanticClass* result = new BNFlagConditionForSemanticClass[conditions.size()]; + size_t i = 0; + for (auto& j : conditions) + { + result[i].semanticClass = j.first; + result[i].condition = j.second; + i++; + } + return result; +} + + +void Architecture::FreeFlagConditionsForSemanticFlagGroupCallback(void*, BNFlagConditionForSemanticClass* conditions) +{ + delete[] conditions; +} + + uint32_t* Architecture::GetFlagsWrittenByFlagWriteTypeCallback(void* ctxt, uint32_t writeType, size_t* count) { Architecture* arch = (Architecture*)ctxt; @@ -309,6 +390,13 @@ uint32_t* Architecture::GetFlagsWrittenByFlagWriteTypeCallback(void* ctxt, uint3 } +uint32_t Architecture::GetSemanticClassForFlagWriteTypeCallback(void* ctxt, uint32_t writeType) +{ + Architecture* arch = (Architecture*)ctxt; + return arch->GetSemanticClassForFlagWriteType(writeType); +} + + size_t Architecture::GetFlagWriteLowLevelILCallback(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il) { @@ -318,12 +406,20 @@ size_t Architecture::GetFlagWriteLowLevelILCallback(void* ctxt, BNLowLevelILOper } -size_t Architecture::GetFlagConditionLowLevelILCallback(void* ctxt, BNLowLevelILFlagCondition cond, +size_t Architecture::GetFlagConditionLowLevelILCallback(void* ctxt, BNLowLevelILFlagCondition cond, uint32_t semClass, BNLowLevelILFunction* il) { Architecture* arch = (Architecture*)ctxt; LowLevelILFunction func(il); - return arch->GetFlagConditionLowLevelIL(cond, func); + return arch->GetFlagConditionLowLevelIL(cond, semClass, func); +} + + +size_t Architecture::GetSemanticFlagGroupLowLevelILCallback(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il) +{ + Architecture* arch = (Architecture*)ctxt; + LowLevelILFunction func(il); + return arch->GetSemanticFlagGroupLowLevelIL(semGroup, func); } @@ -490,15 +586,24 @@ void Architecture::Register(Architecture* arch) callbacks.getRegisterName = GetRegisterNameCallback; callbacks.getFlagName = GetFlagNameCallback; callbacks.getFlagWriteTypeName = GetFlagWriteTypeNameCallback; + callbacks.getSemanticFlagClassName = GetSemanticFlagClassNameCallback; + callbacks.getSemanticFlagGroupName = GetSemanticFlagGroupNameCallback; callbacks.getFullWidthRegisters = GetFullWidthRegistersCallback; callbacks.getAllRegisters = GetAllRegistersCallback; callbacks.getAllFlags = GetAllFlagsCallback; callbacks.getAllFlagWriteTypes = GetAllFlagWriteTypesCallback; + callbacks.getAllSemanticFlagClasses = GetAllSemanticFlagClassesCallback; + callbacks.getAllSemanticFlagGroups = GetAllSemanticFlagGroupsCallback; callbacks.getFlagRole = GetFlagRoleCallback; callbacks.getFlagsRequiredForFlagCondition = GetFlagsRequiredForFlagConditionCallback; + callbacks.getFlagsRequiredForSemanticFlagGroup = GetFlagsRequiredForSemanticFlagGroupCallback; + callbacks.getFlagConditionsForSemanticFlagGroup = GetFlagConditionsForSemanticFlagGroupCallback; + callbacks.freeFlagConditionsForSemanticFlagGroup = FreeFlagConditionsForSemanticFlagGroupCallback; callbacks.getFlagsWrittenByFlagWriteType = GetFlagsWrittenByFlagWriteTypeCallback; + callbacks.getSemanticClassForFlagWriteType = GetSemanticClassForFlagWriteTypeCallback; callbacks.getFlagWriteLowLevelIL = GetFlagWriteLowLevelILCallback; callbacks.getFlagConditionLowLevelIL = GetFlagConditionLowLevelILCallback; + callbacks.getSemanticFlagGroupLowLevelIL = GetSemanticFlagGroupLowLevelILCallback; callbacks.freeRegisterList = FreeRegisterListCallback; callbacks.getRegisterInfo = GetRegisterInfoCallback; callbacks.getStackPointerRegister = GetStackPointerRegisterCallback; @@ -621,6 +726,24 @@ string Architecture::GetFlagWriteTypeName(uint32_t flags) } +string Architecture::GetSemanticFlagClassName(uint32_t semClass) +{ + if (semClass == 0) + return ""; + char flagStr[32]; + sprintf(flagStr, "semantic%" PRIu32, semClass); + return flagStr; +} + + +string Architecture::GetSemanticFlagGroupName(uint32_t semGroup) +{ + char flagStr[32]; + sprintf(flagStr, "group%" PRIu32, semGroup); + return flagStr; +} + + vector Architecture::GetFullWidthRegisters() { return vector(); @@ -645,24 +768,54 @@ vector Architecture::GetAllFlagWriteTypes() } +vector Architecture::GetAllSemanticFlagClasses() +{ + return vector(); +} + + +vector Architecture::GetAllSemanticFlagGroups() +{ + return vector(); +} + + BNFlagRole Architecture::GetFlagRole(uint32_t) { return SpecialFlagRole; } -vector Architecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition) +vector Architecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition, uint32_t) { return vector(); } +vector Architecture::GetFlagsRequiredForSemanticFlagGroup(uint32_t) +{ + return vector(); +} + + +map Architecture::GetFlagConditionsForSemanticFlagGroup(uint32_t) +{ + return map(); +} + + vector Architecture::GetFlagsWrittenByFlagWriteType(uint32_t) { return vector(); } +uint32_t Architecture::GetSemanticClassForFlagWriteType(uint32_t) +{ + return 0; +} + + size_t Architecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il) { @@ -681,7 +834,7 @@ size_t Architecture::GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, siz } -ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) +ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, uint32_t, LowLevelILFunction& il) { return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); } @@ -693,6 +846,12 @@ ExprId Architecture::GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition } +ExprId Architecture::GetSemanticFlagGroupLowLevelIL(uint32_t, LowLevelILFunction& il) +{ + return il.Unimplemented(); +} + + BNRegisterInfo Architecture::GetRegisterInfo(uint32_t) { BNRegisterInfo result; @@ -1064,6 +1223,24 @@ string CoreArchitecture::GetFlagWriteTypeName(uint32_t flags) } +string CoreArchitecture::GetSemanticFlagClassName(uint32_t semClass) +{ + char* name = BNGetArchitectureSemanticFlagClassName(m_object, semClass); + string result = name; + BNFreeString(name); + return result; +} + + +string CoreArchitecture::GetSemanticFlagGroupName(uint32_t semGroup) +{ + char* name = BNGetArchitectureSemanticFlagGroupName(m_object, semGroup); + string result = name; + BNFreeString(name); + return result; +} + + vector CoreArchitecture::GetFullWidthRegisters() { size_t count; @@ -1120,16 +1297,58 @@ vector CoreArchitecture::GetAllFlagWriteTypes() } +vector CoreArchitecture::GetAllSemanticFlagClasses() +{ + size_t count; + uint32_t* regs = BNGetAllArchitectureSemanticFlagClasses(m_object, &count); + + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(regs[i]); + + BNFreeRegisterList(regs); + return result; +} + + +vector CoreArchitecture::GetAllSemanticFlagGroups() +{ + size_t count; + uint32_t* regs = BNGetAllArchitectureSemanticFlagGroups(m_object, &count); + + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(regs[i]); + + BNFreeRegisterList(regs); + return result; +} + + BNFlagRole CoreArchitecture::GetFlagRole(uint32_t flag) { return BNGetArchitectureFlagRole(m_object, flag); } -vector CoreArchitecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) +vector CoreArchitecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, uint32_t semClass) +{ + size_t count; + uint32_t* flags = BNGetArchitectureFlagsRequiredForFlagCondition(m_object, cond, semClass, &count); + + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(flags[i]); + + BNFreeRegisterList(flags); + return result; +} + + +vector CoreArchitecture::GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) { size_t count; - uint32_t* flags = BNGetArchitectureFlagsRequiredForFlagCondition(m_object, cond, &count); + uint32_t* flags = BNGetArchitectureFlagsRequiredForSemanticFlagGroup(m_object, semGroup, &count); vector result; for (size_t i = 0; i < count; i++) @@ -1140,6 +1359,21 @@ vector CoreArchitecture::GetFlagsRequiredForFlagCondition(BNLowLevelIL } +map CoreArchitecture::GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) +{ + size_t count; + BNFlagConditionForSemanticClass* conditions = BNGetArchitectureFlagConditionsForSemanticFlagGroup(m_object, + semGroup, &count); + + map result; + for (size_t i = 0; i < count; i++) + result[conditions[i].semanticClass] = conditions[i].condition; + + BNFreeFlagConditionsForSemanticFlagGroup(conditions); + return result; +} + + vector CoreArchitecture::GetFlagsWrittenByFlagWriteType(uint32_t writeType) { size_t count; @@ -1154,6 +1388,12 @@ vector CoreArchitecture::GetFlagsWrittenByFlagWriteType(uint32_t write } +uint32_t CoreArchitecture::GetSemanticClassForFlagWriteType(uint32_t writeType) +{ + return BNGetArchitectureSemanticClassForFlagWriteType(m_object, writeType); +} + + size_t CoreArchitecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) { @@ -1162,9 +1402,16 @@ size_t CoreArchitecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t } -ExprId CoreArchitecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) +ExprId CoreArchitecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) +{ + return (ExprId)BNGetArchitectureFlagConditionLowLevelIL(m_object, cond, semClass, il.GetObject()); +} + + +ExprId CoreArchitecture::GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) { - return (ExprId)BNGetArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); + return (ExprId)BNGetArchitectureSemanticFlagGroupLowLevelIL(m_object, semGroup, il.GetObject()); } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index b90f72a2..cbd51d05 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1601,17 +1601,28 @@ namespace BinaryNinja static char* GetRegisterNameCallback(void* ctxt, uint32_t reg); static char* GetFlagNameCallback(void* ctxt, uint32_t flag); static char* GetFlagWriteTypeNameCallback(void* ctxt, uint32_t flags); + static char* GetSemanticFlagClassNameCallback(void* ctxt, uint32_t semClass); + static char* GetSemanticFlagGroupNameCallback(void* ctxt, uint32_t semGroup); static uint32_t* GetFullWidthRegistersCallback(void* ctxt, size_t* count); static uint32_t* GetAllRegistersCallback(void* ctxt, size_t* count); static uint32_t* GetAllFlagsCallback(void* ctxt, size_t* count); static uint32_t* GetAllFlagWriteTypesCallback(void* ctxt, size_t* count); + static uint32_t* GetAllSemanticFlagClassesCallback(void* ctxt, size_t* count); + static uint32_t* GetAllSemanticFlagGroupsCallback(void* ctxt, size_t* count); static BNFlagRole GetFlagRoleCallback(void* ctxt, uint32_t flag); - static uint32_t* GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, size_t* count); + static uint32_t* GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, + uint32_t semClass, size_t* count); + static uint32_t* GetFlagsRequiredForSemanticFlagGroupCallback(void* ctxt, uint32_t semGroup, size_t* count); + static BNFlagConditionForSemanticClass* GetFlagConditionsForSemanticFlagGroupCallback(void* ctxt, + uint32_t semGroup, size_t* count); + static void FreeFlagConditionsForSemanticFlagGroupCallback(void* ctxt, BNFlagConditionForSemanticClass* conditions); static uint32_t* GetFlagsWrittenByFlagWriteTypeCallback(void* ctxt, uint32_t writeType, size_t* count); + static uint32_t GetSemanticClassForFlagWriteTypeCallback(void* ctxt, uint32_t writeType); static size_t GetFlagWriteLowLevelILCallback(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); static size_t GetFlagConditionLowLevelILCallback(void* ctxt, BNLowLevelILFlagCondition cond, - BNLowLevelILFunction* il); + uint32_t semClass, BNLowLevelILFunction* il); + static size_t GetSemanticFlagGroupLowLevelILCallback(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il); static void FreeRegisterListCallback(void* ctxt, uint32_t* regs); static void GetRegisterInfoCallback(void* ctxt, uint32_t reg, BNRegisterInfo* result); static uint32_t GetStackPointerRegisterCallback(void* ctxt); @@ -1668,19 +1679,28 @@ namespace BinaryNinja virtual std::string GetRegisterName(uint32_t reg); virtual std::string GetFlagName(uint32_t flag); virtual std::string GetFlagWriteTypeName(uint32_t flags); + virtual std::string GetSemanticFlagClassName(uint32_t semClass); + virtual std::string GetSemanticFlagGroupName(uint32_t semGroup); virtual std::vector GetFullWidthRegisters(); virtual std::vector GetAllRegisters(); virtual std::vector GetAllFlags(); virtual std::vector GetAllFlagWriteTypes(); + virtual std::vector GetAllSemanticFlagClasses(); + virtual std::vector GetAllSemanticFlagGroups(); virtual BNFlagRole GetFlagRole(uint32_t flag); - virtual std::vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond); + virtual std::vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, + uint32_t semClass = 0); + virtual std::vector GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup); + virtual std::map GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup); virtual std::vector GetFlagsWrittenByFlagWriteType(uint32_t writeType); + virtual uint32_t GetSemanticClassForFlagWriteType(uint32_t writeType); virtual ExprId GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il); ExprId GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, BNFlagRole role, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il); - virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il); + virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, uint32_t semClass, LowLevelILFunction& il); ExprId GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il); + virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il); virtual BNRegisterInfo GetRegisterInfo(uint32_t reg); virtual uint32_t GetStackPointerRegister(); virtual uint32_t GetLinkRegister(); @@ -1804,16 +1824,26 @@ namespace BinaryNinja virtual std::string GetRegisterName(uint32_t reg) override; virtual std::string GetFlagName(uint32_t flag) override; virtual std::string GetFlagWriteTypeName(uint32_t flags) override; + virtual std::string GetSemanticFlagClassName(uint32_t semClass) override; + virtual std::string GetSemanticFlagGroupName(uint32_t semGroup) override; virtual std::vector GetFullWidthRegisters() override; virtual std::vector GetAllRegisters() override; virtual std::vector GetAllFlags() override; virtual std::vector GetAllFlagWriteTypes() override; + virtual std::vector GetAllSemanticFlagClasses() override; + virtual std::vector GetAllSemanticFlagGroups() override; virtual BNFlagRole GetFlagRole(uint32_t flag) override; - virtual std::vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override; + virtual std::vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, + uint32_t semClass = 0) override; + virtual std::vector GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) override; + virtual std::map GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) override; virtual std::vector GetFlagsWrittenByFlagWriteType(uint32_t writeType) override; + virtual uint32_t GetSemanticClassForFlagWriteType(uint32_t writeType) override; virtual ExprId GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override; - virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) override; + virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) override; + virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) override; virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override; virtual uint32_t GetStackPointerRegister() override; virtual uint32_t GetLinkRegister() override; @@ -2584,7 +2614,9 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId Return(size_t dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId NoReturn(const ILSourceLocation& loc = ILSourceLocation()); - ExprId FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagCondition(BNLowLevelILFlagCondition cond, uint32_t semClass = 0, + const ILSourceLocation& loc = ILSourceLocation()); + ExprId FlagGroup(uint32_t semGroup, const ILSourceLocation& loc = ILSourceLocation()); ExprId CompareEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId CompareNotEqual(size_t size, ExprId a, ExprId b, @@ -2641,6 +2673,7 @@ namespace BinaryNinja ExprId FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId Goto(BNLowLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); @@ -2944,6 +2977,7 @@ namespace BinaryNinja ExprId FloatCompareLessEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId FloatCompareGreaterEqual(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId FloatCompareGreaterThan(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); + ExprId FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId Goto(BNMediumLevelILLabel& label, const ILSourceLocation& loc = ILSourceLocation()); diff --git a/binaryninjacore.h b/binaryninjacore.h index baca94be..388d3643 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -335,6 +335,7 @@ extern "C" LLIL_IF, LLIL_GOTO, LLIL_FLAG_COND, // Valid only in Lifted IL + LLIL_FLAG_GROUP, // Valid only in Lifted IL LLIL_CMP_E, LLIL_CMP_NE, LLIL_CMP_SLT, @@ -372,6 +373,7 @@ extern "C" LLIL_FCMP_LE, LLIL_FCMP_GE, LLIL_FCMP_GT, + LLIL_FCMP_O, LLIL_FCMP_UO, // The following instructions are only used in SSA form @@ -418,7 +420,15 @@ extern "C" LLFC_NEG, LLFC_POS, LLFC_O, - LLFC_NO + LLFC_NO, + LLFC_FE, + LLFC_FNE, + LLFC_FLT, + LLFC_FLE, + LLFC_FGE, + LLFC_FGT, + LLFC_FO, + LLFC_FUO }; enum BNFlagRole @@ -869,6 +879,7 @@ extern "C" MLIL_FCMP_LE, MLIL_FCMP_GE, MLIL_FCMP_GT, + MLIL_FCMP_O, MLIL_FCMP_UO, // The following instructions are only used in SSA form @@ -1058,6 +1069,12 @@ extern "C" size_t count; }; + struct BNFlagConditionForSemanticClass + { + uint32_t semanticClass; + BNLowLevelILFlagCondition condition; + }; + struct BNCustomArchitecture { void* context; @@ -1077,16 +1094,27 @@ extern "C" char* (*getRegisterName)(void* ctxt, uint32_t reg); char* (*getFlagName)(void* ctxt, uint32_t flag); char* (*getFlagWriteTypeName)(void* ctxt, uint32_t flags); + char* (*getSemanticFlagClassName)(void* ctxt, uint32_t semClass); + char* (*getSemanticFlagGroupName)(void* ctxt, uint32_t semGroup); uint32_t* (*getFullWidthRegisters)(void* ctxt, size_t* count); uint32_t* (*getAllRegisters)(void* ctxt, size_t* count); uint32_t* (*getAllFlags)(void* ctxt, size_t* count); uint32_t* (*getAllFlagWriteTypes)(void* ctxt, size_t* count); + uint32_t* (*getAllSemanticFlagClasses)(void* ctxt, size_t* count); + uint32_t* (*getAllSemanticFlagGroups)(void* ctxt, size_t* count); BNFlagRole (*getFlagRole)(void* ctxt, uint32_t flag); - uint32_t* (*getFlagsRequiredForFlagCondition)(void* ctxt, BNLowLevelILFlagCondition cond, size_t* count); + uint32_t* (*getFlagsRequiredForFlagCondition)(void* ctxt, BNLowLevelILFlagCondition cond, + uint32_t semClass, size_t* count); + uint32_t* (*getFlagsRequiredForSemanticFlagGroup)(void* ctxt, uint32_t semGroup, size_t* count); + BNFlagConditionForSemanticClass* (*getFlagConditionsForSemanticFlagGroup)(void* ctxt, uint32_t semGroup, size_t* count); + void (*freeFlagConditionsForSemanticFlagGroup)(void* ctxt, BNFlagConditionForSemanticClass* conditions); uint32_t* (*getFlagsWrittenByFlagWriteType)(void* ctxt, uint32_t writeType, size_t* count); + uint32_t (*getSemanticClassForFlagWriteType)(void* ctxt, uint32_t writeType); size_t (*getFlagWriteLowLevelIL)(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); - size_t (*getFlagConditionLowLevelIL)(void* ctxt, BNLowLevelILFlagCondition cond, BNLowLevelILFunction* il); + size_t (*getFlagConditionLowLevelIL)(void* ctxt, BNLowLevelILFlagCondition cond, + uint32_t semClass, BNLowLevelILFunction* il); + size_t (*getSemanticFlagGroupLowLevelIL)(void* ctxt, uint32_t semGroup, BNLowLevelILFunction* il); void (*freeRegisterList)(void* ctxt, uint32_t* regs); void (*getRegisterInfo)(void* ctxt, uint32_t reg, BNRegisterInfo* result); uint32_t (*getStackPointerRegister)(void* ctxt); @@ -2042,24 +2070,36 @@ extern "C" BINARYNINJACOREAPI char* BNGetArchitectureRegisterName(BNArchitecture* arch, uint32_t reg); BINARYNINJACOREAPI char* BNGetArchitectureFlagName(BNArchitecture* arch, uint32_t flag); BINARYNINJACOREAPI char* BNGetArchitectureFlagWriteTypeName(BNArchitecture* arch, uint32_t flags); + BINARYNINJACOREAPI char* BNGetArchitectureSemanticFlagClassName(BNArchitecture* arch, uint32_t semClass); + BINARYNINJACOREAPI char* BNGetArchitectureSemanticFlagGroupName(BNArchitecture* arch, uint32_t semGroup); BINARYNINJACOREAPI uint32_t* BNGetFullWidthArchitectureRegisters(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureRegisters(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureFlags(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureFlagWriteTypes(BNArchitecture* arch, size_t* count); + BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureSemanticFlagClasses(BNArchitecture* arch, size_t* count); + BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureSemanticFlagGroups(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI BNFlagRole BNGetArchitectureFlagRole(BNArchitecture* arch, uint32_t flag); BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsRequiredForFlagCondition(BNArchitecture* arch, BNLowLevelILFlagCondition cond, - size_t* count); + uint32_t semClass, size_t* count); + BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsRequiredForSemanticFlagGroup(BNArchitecture* arch, + uint32_t semGroup, size_t* count); + BINARYNINJACOREAPI BNFlagConditionForSemanticClass* BNGetArchitectureFlagConditionsForSemanticFlagGroup(BNArchitecture* arch, + uint32_t semGroup, size_t* count); + BINARYNINJACOREAPI void BNFreeFlagConditionsForSemanticFlagGroup(BNFlagConditionForSemanticClass* conditions); BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsWrittenByFlagWriteType(BNArchitecture* arch, uint32_t writeType, size_t* count); + BINARYNINJACOREAPI uint32_t BNGetArchitectureSemanticClassForFlagWriteType(BNArchitecture* arch, uint32_t writeType); BINARYNINJACOREAPI size_t BNGetArchitectureFlagWriteLowLevelIL(BNArchitecture* arch, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetDefaultArchitectureFlagWriteLowLevelIL(BNArchitecture* arch, BNLowLevelILOperation op, size_t size, BNFlagRole role, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, - BNLowLevelILFunction* il); + uint32_t semClass, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetDefaultArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, BNLowLevelILFunction* il); + BINARYNINJACOREAPI size_t BNGetArchitectureSemanticFlagGroupLowLevelIL(BNArchitecture* arch, + uint32_t semGroup, BNLowLevelILFunction* il); BINARYNINJACOREAPI uint32_t* BNGetModifiedArchitectureRegistersOnWrite(BNArchitecture* arch, uint32_t reg, size_t* count); BINARYNINJACOREAPI void BNFreeRegisterList(uint32_t* regs); BINARYNINJACOREAPI BNRegisterInfo BNGetArchitectureRegisterInfo(BNArchitecture* arch, uint32_t reg); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 6b67ef72..4b1acff3 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -49,6 +49,8 @@ unordered_map {DestSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, {DestSSARegisterStackLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, {DestSSAFlagLowLevelOperandUsage, SSAFlagLowLevelOperand}, + {SemanticFlagClassLowLevelOperandUsage, SemanticFlagClassLowLevelOperand}, + {SemanticFlagGroupLowLevelOperandUsage, SemanticFlagGroupLowLevelOperand}, {PartialRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, {PartialSSARegisterStackSourceLowLevelOperandUsage, SSARegisterStackLowLevelOperand}, {StackSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, @@ -140,7 +142,8 @@ unordered_map> {LLIL_IF, {ConditionExprLowLevelOperandUsage, TrueTargetLowLevelOperandUsage, FalseTargetLowLevelOperandUsage}}, {LLIL_GOTO, {TargetLowLevelOperandUsage}}, - {LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage}}, + {LLIL_FLAG_COND, {FlagConditionLowLevelOperandUsage, SemanticFlagClassLowLevelOperandUsage}}, + {LLIL_FLAG_GROUP, {SemanticFlagGroupLowLevelOperandUsage}}, {LLIL_TRAP, {VectorLowLevelOperandUsage}}, {LLIL_CALL_SSA, {OutputSSARegistersLowLevelOperandUsage, OutputMemoryVersionLowLevelOperandUsage, DestExprLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, @@ -886,6 +889,22 @@ BNLowLevelILFlagCondition LowLevelILOperand::GetFlagCondition() const } +uint32_t LowLevelILOperand::GetSemanticFlagClass() const +{ + if (m_type != SemanticFlagClassLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + +uint32_t LowLevelILOperand::GetSemanticFlagGroup() const +{ + if (m_type != SemanticFlagGroupLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + SSARegister LowLevelILOperand::GetSSARegister() const { if (m_type != SSARegisterLowLevelOperand) @@ -1710,7 +1729,9 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, return dest->Undefined(*this); return dest->If(subExprHandler(GetConditionExpr()), *labelA, *labelB, *this); case LLIL_FLAG_COND: - return dest->FlagCondition(GetFlagCondition(), *this); + return dest->FlagCondition(GetFlagCondition(), GetSemanticFlagClass(), *this); + case LLIL_FLAG_GROUP: + return dest->FlagGroup(GetSemanticFlagGroup(), *this); case LLIL_TRAP: return dest->Trap(GetVector(), *this); case LLIL_CALL_SSA: @@ -1964,6 +1985,24 @@ SSAFlag LowLevelILInstruction::GetDestSSAFlag() const } +uint32_t LowLevelILInstruction::GetSemanticFlagClass() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SemanticFlagClassLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +uint32_t LowLevelILInstruction::GetSemanticFlagGroup() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(SemanticFlagGroupLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + uint32_t LowLevelILInstruction::GetPartialRegister() const { size_t operandIndex; @@ -2748,9 +2787,15 @@ ExprId LowLevelILFunction::NoReturn(const ILSourceLocation& loc) } -ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond, const ILSourceLocation& loc) +ExprId LowLevelILFunction::FlagCondition(BNLowLevelILFlagCondition cond, uint32_t semClass, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_FLAG_COND, loc, 0, 0, (ExprId)cond); + return AddExprWithLocation(LLIL_FLAG_COND, loc, 0, 0, (ExprId)cond, semClass); +} + + +ExprId LowLevelILFunction::FlagGroup(uint32_t semGroup, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FLAG_GROUP, loc, 0, 0, semGroup); } @@ -2988,6 +3033,12 @@ ExprId LowLevelILFunction::FloatCompareGreaterThan(size_t size, ExprId a, ExprId } +ExprId LowLevelILFunction::FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_FCMP_O, loc, size, 0, a, b); +} + + ExprId LowLevelILFunction::FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_FCMP_UO, loc, size, 0, a, b); diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index a0a867af..bb5041a6 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -108,6 +108,8 @@ namespace BinaryNinja RegisterStackLowLevelOperand, FlagLowLevelOperand, FlagConditionLowLevelOperand, + SemanticFlagClassLowLevelOperand, + SemanticFlagGroupLowLevelOperand, SSARegisterLowLevelOperand, SSARegisterStackLowLevelOperand, SSAFlagLowLevelOperand, @@ -135,6 +137,8 @@ namespace BinaryNinja DestSSARegisterLowLevelOperandUsage, DestSSARegisterStackLowLevelOperandUsage, DestSSAFlagLowLevelOperandUsage, + SemanticFlagClassLowLevelOperandUsage, + SemanticFlagGroupLowLevelOperandUsage, PartialRegisterLowLevelOperandUsage, PartialSSARegisterStackSourceLowLevelOperandUsage, StackSSARegisterLowLevelOperandUsage, @@ -587,6 +591,8 @@ namespace BinaryNinja template SSARegister GetDestSSARegister() const { return As().GetDestSSARegister(); } template SSARegisterStack GetDestSSARegisterStack() const { return As().GetDestSSARegisterStack(); } template SSAFlag GetDestSSAFlag() const { return As().GetDestSSAFlag(); } + template uint32_t GetSemanticFlagClass() const { return As().GetSemanticFlagClass(); } + template uint32_t GetSemanticFlagGroup() const { return As().GetSemanticFlagGroup(); } template uint32_t GetPartialRegister() const { return As().GetPartialRegister(); } template SSARegister GetStackSSARegister() const { return As().GetStackSSARegister(); } template SSARegister GetTopSSARegister() const { return As().GetTopSSARegister(); } @@ -645,6 +651,8 @@ namespace BinaryNinja SSARegister GetDestSSARegister() const; SSARegisterStack GetDestSSARegisterStack() const; SSAFlag GetDestSSAFlag() const; + uint32_t GetSemanticFlagClass() const; + uint32_t GetSemanticFlagGroup() const; uint32_t GetPartialRegister() const; SSARegister GetStackSSARegister() const; SSARegister GetTopSSARegister() const; @@ -696,6 +704,8 @@ namespace BinaryNinja uint32_t GetRegister() const; uint32_t GetRegisterStack() const; uint32_t GetFlag() const; + uint32_t GetSemanticFlagClass() const; + uint32_t GetSemanticFlagGroup() const; BNLowLevelILFlagCondition GetFlagCondition() const; SSARegister GetSSARegister() const; SSARegisterStack GetSSARegisterStack() const; @@ -974,6 +984,11 @@ namespace BinaryNinja template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase { BNLowLevelILFlagCondition GetFlagCondition() const { return GetRawOperandAsFlagCondition(0); } + uint32_t GetSemanticFlagClass() const { return GetRawOperandAsRegister(1); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + uint32_t GetSemanticFlagGroup() const { return GetRawOperandAsRegister(0); } }; template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase @@ -1083,6 +1098,7 @@ namespace BinaryNinja template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; + template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandInstruction {}; template <> struct LowLevelILInstructionAccessor: public LowLevelILTwoOperandWithCarryInstruction {}; diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index c3b4014f..e911c298 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -1331,6 +1331,7 @@ void MediumLevelILInstruction::VisitExprs(const std::functionAddExprWithLocation(operation, *this, size, subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); @@ -2706,6 +2708,12 @@ ExprId MediumLevelILFunction::FloatCompareGreaterThan(size_t size, ExprId a, Exp } +ExprId MediumLevelILFunction::FloatCompareOrdered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_FCMP_O, loc, size, a, b); +} + + ExprId MediumLevelILFunction::FloatCompareUnordered(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_FCMP_UO, loc, size, a, b); diff --git a/python/architecture.py b/python/architecture.py index 08049d46..d2ab586e 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -33,7 +33,6 @@ import callingconvention import platform import log import databuffer -import types class _ArchitectureMetaClass(type): @@ -120,9 +119,14 @@ class Architecture(object): global_regs = [] flags = [] flag_write_types = [] + semantic_flag_classes = [] + semantic_flag_groups = [] flag_roles = {} flags_required_for_flag_condition = {} + flags_required_for_semantic_flag_group = {} + flag_conditions_for_semantic_flag_group = {} flags_written_by_flag_write_type = {} + semantic_class_for_flag_write_type = {} reg_stacks = {} __metaclass__ = _ArchitectureMetaClass next_address = 0 @@ -166,16 +170,40 @@ class Architecture(object): core.BNFreeRegisterList(flags) count = ctypes.c_ulonglong() - types = core.BNGetAllArchitectureFlagWriteTypes(self.handle, count) + write_types = core.BNGetAllArchitectureFlagWriteTypes(self.handle, count) self._flag_write_types = {} self._flag_write_types_by_index = {} self.__dict__["flag_write_types"] = [] for i in xrange(0, count.value): - name = core.BNGetArchitectureFlagWriteTypeName(self.handle, types[i]) - self._flag_write_types[name] = types[i] - self._flag_write_types_by_index[types[i]] = name + name = core.BNGetArchitectureFlagWriteTypeName(self.handle, write_types[i]) + self._flag_write_types[name] = write_types[i] + self._flag_write_types_by_index[write_types[i]] = name self.flag_write_types.append(name) - core.BNFreeRegisterList(types) + core.BNFreeRegisterList(write_types) + + count = ctypes.c_ulonglong() + sem_classes = core.BNGetAllArchitectureSemanticFlagClasses(self.handle, count) + self._semantic_flag_classes = {} + self._semantic_flag_classes_by_index = {} + self.__dict__["semantic_flag_classes"] = [] + for i in xrange(0, count.value): + name = core.BNGetArchitectureSemanticFlagClassName(self.handle, sem_classes[i]) + self._semantic_flag_classes[name] = sem_classes[i] + self._semantic_flag_classes_by_index[sem_classes[i]] = name + self.semantic_flag_classes.append(name) + core.BNFreeRegisterList(sem_classes) + + count = ctypes.c_ulonglong() + sem_groups = core.BNGetAllArchitectureSemanticFlagGroups(self.handle, count) + self._semantic_flag_groups = {} + self._semantic_flag_groups_by_index = {} + self.__dict__["semantic_flag_groups"] = [] + for i in xrange(0, count.value): + name = core.BNGetArchitectureSemanticFlagGroupName(self.handle, sem_groups[i]) + self._semantic_flag_groups[name] = sem_groups[i] + self._semantic_flag_groups_by_index[sem_groups[i]] = name + self.semantic_flag_groups.append(name) + core.BNFreeRegisterList(sem_groups) self._flag_roles = {} self.__dict__["flag_roles"] = {} @@ -184,19 +212,48 @@ class Architecture(object): self.__dict__["flag_roles"][flag] = role self._flag_roles[self._flags[flag]] = role - self._flags_required_for_flag_condition = {} self.__dict__["flags_required_for_flag_condition"] = {} for cond in LowLevelILFlagCondition: count = ctypes.c_ulonglong() - flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, count) + flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, 0, count) + flag_names = [] + for i in xrange(0, count.value): + flag_names.append(self._flags_by_index[flags[i]]) + core.BNFreeRegisterList(flags) + self.__dict__["flags_required_for_flag_condition"][cond] = flag_names + + self._flags_required_by_semantic_flag_group = {} + self.__dict__["flags_required_for_semantic_flag_group"] = {} + for group in self.semantic_flag_groups: + count = ctypes.c_ulonglong() + flags = core.BNGetArchitectureFlagsRequiredForSemanticFlagGroup(self.handle, + self._semantic_flag_groups[group], count) flag_indexes = [] flag_names = [] for i in xrange(0, count.value): flag_indexes.append(flags[i]) flag_names.append(self._flags_by_index[flags[i]]) core.BNFreeRegisterList(flags) - self._flags_required_for_flag_condition[cond] = flag_indexes - self.__dict__["flags_required_for_flag_condition"][cond] = flag_names + self._flags_required_by_semantic_flag_group[self._semantic_flag_groups[group]] = flag_indexes + self.__dict__["flags_required_for_semantic_flag_group"][cond] = flag_names + + self._flag_conditions_for_semantic_flag_group = {} + self.__dict__["flag_conditions_for_semantic_flag_group"] = {} + for group in self.semantic_flag_groups: + count = ctypes.c_ulonglong() + conditions = core.BNGetArchitectureFlagConditionsForSemanticFlagGroup(self.handle, + self._semantic_flag_groups[group], count) + class_index_cond = {} + class_cond = {} + for i in xrange(0, count.value): + class_index_cond[conditions[i].semanticClass] = conditions[i].condition + if conditions[i].semanticClass == 0: + class_cond[None] = conditions[i].condition + elif conditions[i].semanticClass in self._semantic_flag_classes_by_index: + class_cond[self._semantic_flag_classes_by_index[conditions[i].semanticClass]] = conditions[i].condition + core.BNFreeFlagConditionsForSemanticFlagGroup(conditions) + self._flag_conditions_for_semantic_flag_group[self._semantic_flag_groups[group]] = class_index_cond + self.__dict__["flag_conditions_for_semantic_flag_group"][group] = class_cond self._flags_written_by_flag_write_type = {} self.__dict__["flags_written_by_flag_write_type"] = {} @@ -213,6 +270,18 @@ class Architecture(object): self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names + self._semantic_class_for_flag_write_type = {} + self.__dict__["semantic_class_for_flag_write_type"] = {} + for write_type in self.flag_write_types: + sem_class = core.BNGetArchitectureSemanticClassForFlagWriteType(self.handle, + self._flag_write_types[write_type]) + if sem_class == 0: + sem_class_name = None + else: + sem_class_name = self._semantic_flag_classes_by_index[sem_class] + self._semantic_class_for_flag_write_type[self._flag_write_types[write_type]] = sem_class + self.__dict__["semantic_class_for_flag_write_type"][write_type] = sem_class_name + count = ctypes.c_ulonglong() regs = core.BNGetArchitectureGlobalRegisters(self.handle, count) self.__dict__["global_regs"] = [] @@ -260,19 +329,33 @@ class Architecture(object): self._cb.getRegisterName = self._cb.getRegisterName.__class__(self._get_register_name) self._cb.getFlagName = self._cb.getFlagName.__class__(self._get_flag_name) self._cb.getFlagWriteTypeName = self._cb.getFlagWriteTypeName.__class__(self._get_flag_write_type_name) + self._cb.getFlagSemanticClassName = self._cb.getFlagSemanticClassName.__class__(self._get_semantic_flag_class_name) + self._cb.getFlagSemanticGroupName = self._cb.getFlagSemanticGroupName.__class__(self._get_semantic_flag_group_name) self._cb.getFullWidthRegisters = self._cb.getFullWidthRegisters.__class__(self._get_full_width_registers) self._cb.getAllRegisters = self._cb.getAllRegisters.__class__(self._get_all_registers) self._cb.getAllFlags = self._cb.getAllRegisters.__class__(self._get_all_flags) self._cb.getAllFlagWriteTypes = self._cb.getAllRegisters.__class__(self._get_all_flag_write_types) + self._cb.getAllFlagSemanticClasses = self._cb.getAllFlagSemanticClasses.__class__(self._get_all_semantic_flag_classes) + self._cb.getAllFlagSemanticGroups = self._cb.getAllFlagSemanticGroups.__class__(self._get_all_semantic_flag_groups) self._cb.getFlagRole = self._cb.getFlagRole.__class__(self._get_flag_role) self._cb.getFlagsRequiredForFlagCondition = self._cb.getFlagsRequiredForFlagCondition.__class__( self._get_flags_required_for_flag_condition) + self._cb.getFlagsRequiredForSemanticFlagGroup = self._cb.getFlagsRequiredForSemanticFlagGroup.__class__( + self._get_flags_required_for_semantic_flag_group) + self._cb.getFlagConditionsForSemanticFlagGroup = self._cb.getFlagConditionsForSemanticFlagGroup.__class__( + self._get_flag_conditions_for_semantic_flag_group) + self._cb.freeFlagConditionsForSemanticFlagGroup = self._cb.freeFlagConditionsForSemanticFlagGroup.__class__( + self._free_flag_conditions_for_semantic_flag_group) self._cb.getFlagsWrittenByFlagWriteType = self._cb.getFlagsWrittenByFlagWriteType.__class__( self._get_flags_written_by_flag_write_type) + self._cb.getSemanticClassForFlagWriteType = self._cb.getSemanticClassForFlagWriteType.__class__( + self._get_semantic_class_for_flag_write_type) self._cb.getFlagWriteLowLevelIL = self._cb.getFlagWriteLowLevelIL.__class__( self._get_flag_write_low_level_il) self._cb.getFlagConditionLowLevelIL = self._cb.getFlagConditionLowLevelIL.__class__( self._get_flag_condition_low_level_il) + self._cb.getSemanticFlagGroupLowLevelIL = self._cb.getSemanticFlagGroupLowLevelIL.__class__( + self._get_semantic_flag_group_low_level_il) self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list) self._cb.getRegisterInfo = self._cb.getRegisterInfo.__class__(self._get_register_info) self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__( @@ -362,6 +445,26 @@ class Architecture(object): self._flag_write_types_by_index[write_type_index] = write_type write_type_index += 1 + self._semantic_flag_classes = {} + self._semantic_flag_classes_by_index = {} + self.__dict__["semantic_flag_classes"] = self.__class__.semantic_flag_classes + semantic_class_index = 1 + for sem_class in self.__class__.semantic_flag_classes: + if sem_class not in self._semantic_flag_classes: + self._semantic_flag_classes[sem_class] = semantic_class_index + self._semantic_flag_classes_by_index[semantic_class_index] = sem_class + semantic_class_index += 1 + + self._semantic_flag_groups = {} + self._semantic_flag_groups_by_index = {} + self.__dict__["semantic_flag_groups"] = self.__class__.semantic_flag_groups + semantic_group_index = 0 + for sem_group in self.__class__.semantic_flag_groups: + if sem_group not in self._semantic_flag_groups: + self._semantic_flag_groups[sem_group] = semantic_group_index + self._semantic_flag_groups_by_index[semantic_group_index] = sem_group + semantic_group_index += 1 + self._flag_roles = {} self.__dict__["flag_roles"] = self.__class__.flag_roles for flag in self.__class__.flag_roles: @@ -370,13 +473,26 @@ class Architecture(object): role = FlagRole[role] self._flag_roles[self._flags[flag]] = role - self._flags_required_for_flag_condition = {} self.__dict__["flags_required_for_flag_condition"] = self.__class__.flags_required_for_flag_condition - for cond in self.__class__.flags_required_for_flag_condition: + + self._flags_required_by_semantic_flag_group = {} + self.__dict__["flags_required_for_semantic_flag_group"] = self.__class__.flags_required_for_semantic_flag_group + for group in self.__class__.flags_required_for_semantic_flag_group: flags = [] - for flag in self.__class__.flags_required_for_flag_condition[cond]: + for flag in self.__class__.flags_required_for_semantic_flag_group[group]: flags.append(self._flags[flag]) - self._flags_required_for_flag_condition[cond] = flags + self._flags_required_by_semantic_flag_group[self._semantic_flag_groups[group]] = flags + + self._flag_conditions_for_semantic_flag_group = {} + self.__dict__["flag_conditions_for_semantic_flag_group"] = self.__class__.flag_conditions_for_semantic_flag_group + for group in self.__class__.flag_conditions_for_semantic_flag_group: + class_cond = {} + for sem_class in self.__class__.flag_conditions_for_semantic_flag_group[group]: + if sem_class is None: + class_cond[0] = self.__class__.flag_conditions_for_semantic_flag_group[group][sem_class] + else: + class_cond[self._semantic_flag_classes[sem_class]] = self.__class__.flag_conditions_for_semantic_flag_group[group][sem_class] + self._flag_conditions_for_semantic_flag_group[self._semantic_flag_groups[group]] = class_cond self._flags_written_by_flag_write_type = {} self.__dict__["flags_written_by_flag_write_type"] = self.__class__.flags_written_by_flag_write_type @@ -386,10 +502,21 @@ class Architecture(object): flags.append(self._flags[flag]) self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags + self._semantic_class_for_flag_write_type = {} + self.__dict__["semantic_class_for_flag_write_type"] = self.__class__.semantic_class_for_flag_write_type + for write_type in self.__class__.semantic_class_for_flag_write_type: + sem_class = self.__class__.semantic_class_for_flag_write_type[write_type] + if sem_class in self._semantic_flag_classes: + sem_class_index = self._semantic_flag_classes[sem_class] + else: + sem_class_index = 0 + self._semantic_class_for_flag_write_type[self._flag_write_types[write_type]] = sem_class_index + self.__dict__["global_regs"] = self.__class__.global_regs self._pending_reg_lists = {} self._pending_token_lists = {} + self._pending_condition_lists = {} def __eq__(self, value): if not isinstance(value, Architecture): @@ -605,6 +732,24 @@ class Architecture(object): log.log_error(traceback.format_exc()) return core.BNAllocString("") + def _get_semantic_flag_class_name(self, ctxt, sem_class): + try: + if sem_class in self._semantic_flag_class_by_index: + return core.BNAllocString(self._semantic_flag_class_by_index[sem_class]) + return core.BNAllocString("") + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + return core.BNAllocString("") + + def _get_semantic_flag_group_name(self, ctxt, sem_group): + try: + if sem_group in self._semantic_flag_group_by_index: + return core.BNAllocString(self._semantic_flag_group_by_index[sem_group]) + return core.BNAllocString("") + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + return core.BNAllocString("") + def _get_full_width_registers(self, ctxt, count): try: regs = self._full_width_regs.values() @@ -652,11 +797,11 @@ class Architecture(object): def _get_all_flag_write_types(self, ctxt, count): try: - types = self._flag_write_types_by_index.keys() - count[0] = len(types) - type_buf = (ctypes.c_uint * len(types))() - for i in xrange(0, len(types)): - type_buf[i] = types[i] + write_types = self._flag_write_types_by_index.keys() + count[0] = len(write_types) + type_buf = (ctypes.c_uint * len(write_types))() + for i in xrange(0, len(write_types)): + type_buf[i] = write_types[i] result = ctypes.cast(type_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, type_buf) return result.value @@ -665,6 +810,36 @@ class Architecture(object): count[0] = 0 return None + def _get_all_semantic_flag_classes(self, ctxt, count): + try: + sem_classes = self._semantic_flag_classes_by_index.keys() + count[0] = len(sem_classes) + class_buf = (ctypes.c_uint * len(sem_classes))() + for i in xrange(0, len(sem_classes)): + class_buf[i] = sem_classes[i] + result = ctypes.cast(class_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, class_buf) + return result.value + except KeyError: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _get_all_semantic_flag_groups(self, ctxt, count): + try: + sem_groups = self._semantic_flag_groups_by_index.keys() + count[0] = len(sem_groups) + group_buf = (ctypes.c_uint * len(sem_groups))() + for i in xrange(0, len(sem_groups)): + group_buf[i] = sem_groups[i] + result = ctypes.cast(group_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, group_buf) + return result.value + except KeyError: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + def _get_flag_role(self, ctxt, flag): try: if flag in self._flag_roles: @@ -674,12 +849,16 @@ class Architecture(object): log.log_error(traceback.format_exc()) return None - def _get_flags_required_for_flag_condition(self, ctxt, cond, count): + def _get_flags_required_for_flag_condition(self, ctxt, cond, sem_class, count): try: - if cond in self._flags_required_for_flag_condition: - flags = self._flags_required_for_flag_condition[cond] + if sem_class in self._semantic_flag_classes_by_index: + sem_class = self._semantic_flag_classes_by_index[sem_class] else: - flags = [] + sem_class = 0 + flag_names = self.perform_get_flags_required_for_flag_condition(cond, sem_class) + flags = [] + for name in flag_names: + flags.append(self._flags[name]) count[0] = len(flags) flag_buf = (ctypes.c_uint * len(flags))() for i in xrange(0, len(flags)): @@ -692,6 +871,59 @@ class Architecture(object): count[0] = 0 return None + def perform_get_flags_required_for_flag_condition(self, cond, sem_class): + if cond in self.flags_required_for_flag_condition: + return self.flags_required_for_flag_condition[cond] + return [] + + def _get_flags_required_for_semantic_flag_group(self, ctxt, sem_group, count): + try: + if sem_group in self._flags_required_by_semantic_flag_group: + flags = self._flags_required_by_semantic_flag_group[sem_group] + else: + flags = [] + count[0] = len(flags) + flag_buf = (ctypes.c_uint * len(flags))() + for i in xrange(0, len(flags)): + flag_buf[i] = flags[i] + result = ctypes.cast(flag_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, flag_buf) + return result.value + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _get_flag_conditions_for_semantic_flag_group(self, ctxt, sem_group, count): + try: + if sem_group in self._flag_conditions_by_semantic_flag_group: + class_cond = self._flag_conditions_by_semantic_flag_group[sem_group] + else: + class_cond = {} + count[0] = len(class_cond) + cond_buf = (core.BNFlagConditionForSemanticClass * len(class_cond))() + i = 0 + for class_index in class_cond.keys(): + cond_buf[i].semanticClass = class_index + cond_buf[i].condition = class_cond[class_index] + i += 1 + result = ctypes.cast(cond_buf, ctypes.c_void_p) + self._pending_conditions[result.value] = (result, cond_buf) + return result.value + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _free_flag_conditions_for_semantic_flag_group(self, ctxt, conditions): + try: + buf = ctypes.cast(conditions, ctypes.c_void_p) + if buf.value not in self._pending_conditions: + raise ValueError("freeing condition list that wasn't allocated") + del self._pending_conditions[buf.value] + except (ValueError, KeyError): + log.log_error(traceback.format_exc()) + def _get_flags_written_by_flag_write_type(self, ctxt, write_type, count): try: if write_type in self._flags_written_by_flag_write_type: @@ -710,6 +942,16 @@ class Architecture(object): count[0] = 0 return None + def _get_semantic_class_for_flag_write_type(self, ctxt, write_type): + try: + if write_type in self._semantic_class_for_flag_write_type: + return self._semantic_class_for_flag_write_type[write_type] + else: + return 0 + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + return 0 + def _get_flag_write_low_level_il(self, ctxt, op, size, write_type, flag, operands, operand_count, il): try: write_type_name = None @@ -730,9 +972,25 @@ class Architecture(object): log.log_error(traceback.format_exc()) return False - def _get_flag_condition_low_level_il(self, ctxt, cond, il): + def _get_flag_condition_low_level_il(self, ctxt, cond, sem_class, il): try: - return self.perform_get_flag_condition_low_level_il(cond, + if sem_class in self._semantic_flag_classes_by_index: + sem_class_name = self._semantic_flag_classes_by_index[sem_class] + else: + sem_class_name = None + return self.perform_get_flag_condition_low_level_il(cond, sem_class_name, + lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index + except OSError: + log.log_error(traceback.format_exc()) + return 0 + + def _get_semantic_flag_group_low_level_il(self, ctxt, sem_group, il): + try: + if sem_group in self._semantic_flag_groups_by_index: + sem_group_name = self._semantic_flag_groups_by_index[sem_group] + else: + sem_group_name = None + return self.perform_get_semantic_flag_group_low_level_il(sem_group_name, lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index except OSError: log.log_error(traceback.format_exc()) @@ -1054,17 +1312,30 @@ class Architecture(object): return self.get_default_flag_write_low_level_il(op, size, self._flag_roles[flag], operands, il) @abc.abstractmethod - def perform_get_flag_condition_low_level_il(self, cond, il): + def perform_get_flag_condition_low_level_il(self, cond, sem_class, il): """ .. note:: Architecture subclasses should implement this method. .. warning:: This method should never be called directly. - :param LowLevelILFlagCondition cond: - :param LowLevelILFunction il: + :param LowLevelILFlagCondition cond: Flag condition to be computed + :param str sem_class: Semantic class to be used (None for default semantics) + :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to :rtype: LowLevelILExpr """ return self.get_default_flag_condition_low_level_il(cond, il) + @abc.abstractmethod + def perform_get_semantic_flag_group_low_level_il(self, sem_group, il): + """ + .. note:: Architecture subclasses should implement this method. + .. warning:: This method should never be called directly. + + :param str sem_group: Semantic group to be computed + :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to + :rtype: LowLevelILExpr + """ + return il.unimplemented() + @abc.abstractmethod def perform_assemble(self, code, addr): """ @@ -1407,6 +1678,22 @@ class Architecture(object): return flag.index return flag + def get_semantic_flag_class_index(self, sem_class): + if sem_class is None: + return 0 + elif isinstance(sem_class, str): + return self._semantic_flag_classes[sem_class] + elif isinstance(sem_class, lowlevelil.ILSemanticFlagClass): + return sem_class.index + return sem_class + + def get_semantic_flag_group_index(self, sem_group): + if isinstance(sem_group, str): + return self._semantic_flag_groups[sem_group] + elif isinstance(sem_group, lowlevelil.ILSemanticFlagGroup): + return sem_group.index + return sem_group + def get_flag_write_type_name(self, write_type): """ ``get_flag_write_type_name`` gets the flag write type name for the given flag. @@ -1437,6 +1724,26 @@ class Architecture(object): """ return self._flag_write_types[write_type] + def get_semantic_flag_class_by_name(self, sem_class): + """ + ``get_semantic_flag_class_by_name`` gets the semantic flag class index by name. + + :param int sem_class: semantic flag class + :return: semantic flag class index + :rtype: str + """ + return self._semantic_flag_classes[sem_class] + + def get_semantic_flag_group_by_name(self, sem_group): + """ + ``get_semantic_flag_group_by_name`` gets the semantic flag group index by name. + + :param int sem_group: semantic flag group + :return: semantic flag group index + :rtype: str + """ + return self._semantic_flag_groups[sem_group] + def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): """ :param LowLevelILOperation op: @@ -1502,6 +1809,25 @@ class Architecture(object): """ return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + def get_semantic_flag_group_low_level_il(self, sem_group, il): + """ + :param str sem_group: + :param LowLevelILFunction il: + :rtype: LowLevelILExpr + """ + group_index = self.get_semantic_flag_group_index(sem_group) + return lowlevelil.LowLevelILExpr(core.BNGetArchitectureSemanticFlagGroupLowLevelIL(self.handle, group_index, il.handle)) + + def get_flags_required_for_flag_condition(self, cond, sem_class = None): + sem_class = self.get_semantic_flag_class_index(sem_class) + count = ctypes.c_ulonglong() + flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, sem_class, count) + flag_names = [] + for i in xrange(0, count.value): + flag_names.append(self._flags_by_index[flags[i]]) + core.BNFreeRegisterList(flags) + return flag_names + def get_modified_regs_on_write(self, reg): """ ``get_modified_regs_on_write`` returns a list of register names that are modified when ``reg`` is written. diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 42c34ee0..a2d77c9f 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -99,6 +99,38 @@ class ILFlag(object): return self.name +class ILSemanticFlagClass(object): + def __init__(self, arch, sem_class): + self.arch = arch + self.index = sem_class + self.name = self.arch.get_semantic_flag_class_name(self.index) + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + def __eq__(self, other): + return self.index == other.index + + +class ILSemanticFlagGroup(object): + def __init__(self, arch, sem_group): + self.arch = arch + self.index = sem_group + self.name = self.arch.get_semantic_flag_group_name(self.index) + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + def __eq__(self, other): + return self.index == other.index + + class SSARegister(object): def __init__(self, reg, version): self.reg = reg @@ -202,7 +234,8 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_NORET: [], LowLevelILOperation.LLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], LowLevelILOperation.LLIL_GOTO: [("dest", "int")], - LowLevelILOperation.LLIL_FLAG_COND: [("condition", "cond")], + LowLevelILOperation.LLIL_FLAG_COND: [("condition", "cond", "semantic_class", "sem_class")], + LowLevelILOperation.LLIL_FLAG_GROUP: [("semantic_group", "sem_group")], LowLevelILOperation.LLIL_CMP_E: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_NE: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], @@ -238,6 +271,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_FCMP_LE: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_FCMP_GE: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_FCMP_GT: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_FCMP_O: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_FCMP_UO: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg_ssa"), ("src", "expr")], LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("dest", "reg"), ("src", "expr")], @@ -324,6 +358,10 @@ class LowLevelILInstruction(object): flag = ILFlag(func.arch, instr.operands[i]) i += 1 value = SSAFlag(flag, instr.operands[i]) + elif operand_type == "sem_class": + value = ILSemanticFlagClass(func.arch, instr.operands[i]) + elif operand_type == "sem_group": + value = ILSemanticFlagGroup(func.arch, instr.operands[i]) elif operand_type == "cond": value = LowLevelILFlagCondition(instr.operands[i]) elif operand_type == "int_list": @@ -1507,11 +1545,12 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_NORET) - def flag_condition(self, cond): + def flag_condition(self, cond, sem_class = None): """ ``flag_condition`` returns a flag_condition expression for the given LowLevelILFlagCondition :param LowLevelILFlagCondition cond: Flag condition expression to retrieve + :param str sem_class: Optional semantic flag class :return: A flag_condition expression :rtype: LowLevelILExpr """ @@ -1519,7 +1558,19 @@ class LowLevelILFunction(object): cond = LowLevelILFlagCondition[cond] elif isinstance(cond, LowLevelILFlagCondition): cond = cond.value - return self.expr(LowLevelILOperation.LLIL_FLAG_COND, cond) + class_index = self.arch.get_semantic_flag_class_index(sem_class) + return self.expr(LowLevelILOperation.LLIL_FLAG_COND, cond, class_index) + + def flag_group(self, sem_group): + """ + ``flag_group`` returns a flag_group expression for the given semantic flag group + + :param str sem_group: Semantic flag group to access + :return: A flag_group expression + :rtype: LowLevelILExpr + """ + group = self.arch.get_semantic_flag_group_index(sem_group) + return self.expr(LowLevelILOperation.LLIL_FLAG_GROUP, group) def compare_equal(self, size, a, b): """ @@ -2174,6 +2225,7 @@ class LowLevelILBasicBlock(basicblock.BasicBlock): def __hash__(self): return hash((self.start, self.end, self.il_function)) + def LLIL_TEMP(n): return n | 0x80000000 diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 85feba0a..8594ea36 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -169,6 +169,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_FCMP_LE: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_FCMP_GE: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_FCMP_GT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_FCMP_O: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_FCMP_UO: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var_ssa"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], -- cgit v1.3.1 From 1228e32e300d62f5d76438e4500965d76edeca69 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 18 Jan 2018 20:15:04 -0500 Subject: Allow flag roles to be dependent on semantic class --- architecture.cpp | 23 ++++++++++++----------- binaryninjaapi.h | 11 ++++++----- binaryninjacore.h | 10 ++++++---- lowlevelilinstruction.cpp | 7 ++++--- python/architecture.py | 42 ++++++++++++++++++++++++++++++++---------- 5 files changed, 60 insertions(+), 33 deletions(-) (limited to 'architecture.cpp') diff --git a/architecture.cpp b/architecture.cpp index 571794c6..78a67105 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -318,10 +318,10 @@ uint32_t* Architecture::GetAllSemanticFlagGroupsCallback(void* ctxt, size_t* cou } -BNFlagRole Architecture::GetFlagRoleCallback(void* ctxt, uint32_t flag) +BNFlagRole Architecture::GetFlagRoleCallback(void* ctxt, uint32_t flag, uint32_t semClass) { Architecture* arch = (Architecture*)ctxt; - return arch->GetFlagRole(flag); + return arch->GetFlagRole(flag, semClass); } @@ -780,7 +780,7 @@ vector Architecture::GetAllSemanticFlagGroups() } -BNFlagRole Architecture::GetFlagRole(uint32_t) +BNFlagRole Architecture::GetFlagRole(uint32_t, uint32_t) { return SpecialFlagRole; } @@ -819,8 +819,7 @@ uint32_t Architecture::GetSemanticClassForFlagWriteType(uint32_t) size_t Architecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il) { - (void)flagWriteType; - BNFlagRole role = GetFlagRole(flag); + BNFlagRole role = GetFlagRole(flag, GetSemanticClassForFlagWriteType(flagWriteType)); return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, role, operands, operandCount, il.GetObject()); } @@ -834,15 +833,17 @@ size_t Architecture::GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, siz } -ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, uint32_t, LowLevelILFunction& il) +ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) { - return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); + return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, semClass, il.GetObject()); } -ExprId Architecture::GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) +ExprId Architecture::GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) { - return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); + return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, semClass, il.GetObject()); } @@ -1325,9 +1326,9 @@ vector CoreArchitecture::GetAllSemanticFlagGroups() } -BNFlagRole CoreArchitecture::GetFlagRole(uint32_t flag) +BNFlagRole CoreArchitecture::GetFlagRole(uint32_t flag, uint32_t semClass) { - return BNGetArchitectureFlagRole(m_object, flag); + return BNGetArchitectureFlagRole(m_object, flag, semClass); } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index cbd51d05..b74fa971 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1609,7 +1609,7 @@ namespace BinaryNinja static uint32_t* GetAllFlagWriteTypesCallback(void* ctxt, size_t* count); static uint32_t* GetAllSemanticFlagClassesCallback(void* ctxt, size_t* count); static uint32_t* GetAllSemanticFlagGroupsCallback(void* ctxt, size_t* count); - static BNFlagRole GetFlagRoleCallback(void* ctxt, uint32_t flag); + static BNFlagRole GetFlagRoleCallback(void* ctxt, uint32_t flag, uint32_t semClass); static uint32_t* GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, uint32_t semClass, size_t* count); static uint32_t* GetFlagsRequiredForSemanticFlagGroupCallback(void* ctxt, uint32_t semGroup, size_t* count); @@ -1687,7 +1687,7 @@ namespace BinaryNinja virtual std::vector GetAllFlagWriteTypes(); virtual std::vector GetAllSemanticFlagClasses(); virtual std::vector GetAllSemanticFlagGroups(); - virtual BNFlagRole GetFlagRole(uint32_t flag); + virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass = 0); virtual std::vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, uint32_t semClass = 0); virtual std::vector GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup); @@ -1699,7 +1699,7 @@ namespace BinaryNinja ExprId GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, BNFlagRole role, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il); virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, uint32_t semClass, LowLevelILFunction& il); - ExprId GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il); + ExprId GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, uint32_t semClass, LowLevelILFunction& il); virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il); virtual BNRegisterInfo GetRegisterInfo(uint32_t reg); virtual uint32_t GetStackPointerRegister(); @@ -1832,7 +1832,7 @@ namespace BinaryNinja virtual std::vector GetAllFlagWriteTypes() override; virtual std::vector GetAllSemanticFlagClasses() override; virtual std::vector GetAllSemanticFlagGroups() override; - virtual BNFlagRole GetFlagRole(uint32_t flag) override; + virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass = 0) override; virtual std::vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, uint32_t semClass = 0) override; virtual std::vector GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) override; @@ -2526,7 +2526,8 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId RegisterStackTopRelative(size_t size, uint32_t regStack, ExprId entry, const ILSourceLocation& loc = ILSourceLocation()); - ExprId RegisterStackPop(size_t size, uint32_t regStack, const ILSourceLocation& loc = ILSourceLocation()); + ExprId RegisterStackPop(size_t size, uint32_t regStack, uint32_t flags = 0, + const ILSourceLocation& loc = ILSourceLocation()); ExprId RegisterStackTopRelativeSSA(size_t size, const SSARegisterStack& regStack, ExprId entry, const SSARegister& top, const ILSourceLocation& loc = ILSourceLocation()); ExprId RegisterStackAbsoluteSSA(size_t size, const SSARegisterStack& regStack, uint32_t reg, diff --git a/binaryninjacore.h b/binaryninjacore.h index 388d3643..bc58092d 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -441,7 +441,9 @@ extern "C" OverflowFlagRole = 5, HalfCarryFlagRole = 6, EvenParityFlagRole = 7, - OddParityFlagRole = 8 + OddParityFlagRole = 8, + OrderedFlagRole = 9, + UnorderedFlagRole = 10 }; enum BNFunctionGraphType @@ -1102,7 +1104,7 @@ extern "C" uint32_t* (*getAllFlagWriteTypes)(void* ctxt, size_t* count); uint32_t* (*getAllSemanticFlagClasses)(void* ctxt, size_t* count); uint32_t* (*getAllSemanticFlagGroups)(void* ctxt, size_t* count); - BNFlagRole (*getFlagRole)(void* ctxt, uint32_t flag); + BNFlagRole (*getFlagRole)(void* ctxt, uint32_t flag, uint32_t semClass); uint32_t* (*getFlagsRequiredForFlagCondition)(void* ctxt, BNLowLevelILFlagCondition cond, uint32_t semClass, size_t* count); uint32_t* (*getFlagsRequiredForSemanticFlagGroup)(void* ctxt, uint32_t semGroup, size_t* count); @@ -2078,7 +2080,7 @@ extern "C" BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureFlagWriteTypes(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureSemanticFlagClasses(BNArchitecture* arch, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureSemanticFlagGroups(BNArchitecture* arch, size_t* count); - BINARYNINJACOREAPI BNFlagRole BNGetArchitectureFlagRole(BNArchitecture* arch, uint32_t flag); + BINARYNINJACOREAPI BNFlagRole BNGetArchitectureFlagRole(BNArchitecture* arch, uint32_t flag, uint32_t semClass); BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsRequiredForFlagCondition(BNArchitecture* arch, BNLowLevelILFlagCondition cond, uint32_t semClass, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsRequiredForSemanticFlagGroup(BNArchitecture* arch, @@ -2097,7 +2099,7 @@ extern "C" BINARYNINJACOREAPI size_t BNGetArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, uint32_t semClass, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetDefaultArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, - BNLowLevelILFunction* il); + uint32_t semClass, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetArchitectureSemanticFlagGroupLowLevelIL(BNArchitecture* arch, uint32_t semGroup, BNLowLevelILFunction* il); BINARYNINJACOREAPI uint32_t* BNGetModifiedArchitectureRegistersOnWrite(BNArchitecture* arch, uint32_t reg, size_t* count); diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 4b1acff3..9909e8ee 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -1680,7 +1680,7 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, return dest->RegisterStackTopRelative(size, GetSourceRegisterStack(), subExprHandler(GetSourceExpr()), *this); case LLIL_REG_STACK_POP: - return dest->RegisterStackPop(size, GetSourceRegisterStack(), *this); + return dest->RegisterStackPop(size, GetSourceRegisterStack(), flags, *this); case LLIL_REG_STACK_REL_SSA: return dest->RegisterStackTopRelativeSSA(size, GetSourceSSARegisterStack(), subExprHandler(GetSourceExpr()), @@ -1827,6 +1827,7 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, case LLIL_FCMP_LE: case LLIL_FCMP_GE: case LLIL_FCMP_GT: + case LLIL_FCMP_O: case LLIL_FCMP_UO: return dest->AddExprWithLocation(operation, *this, size, flags, subExprHandler(AsTwoOperand().GetLeftExpr()), subExprHandler(AsTwoOperand().GetRightExpr())); @@ -2435,9 +2436,9 @@ ExprId LowLevelILFunction::RegisterStackTopRelative(size_t size, uint32_t regSta } -ExprId LowLevelILFunction::RegisterStackPop(size_t size, uint32_t regStack, const ILSourceLocation& loc) +ExprId LowLevelILFunction::RegisterStackPop(size_t size, uint32_t regStack, uint32_t flags, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_REG_STACK_POP, loc, size, 0, regStack); + return AddExprWithLocation(LLIL_REG_STACK_POP, loc, size, flags, regStack); } diff --git a/python/architecture.py b/python/architecture.py index d2ab586e..2b422962 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -208,7 +208,7 @@ class Architecture(object): self._flag_roles = {} self.__dict__["flag_roles"] = {} for flag in self.__dict__["flags"]: - role = FlagRole(core.BNGetArchitectureFlagRole(self.handle, self._flags[flag])) + role = FlagRole(core.BNGetArchitectureFlagRole(self.handle, self._flags[flag], 0)) self.__dict__["flag_roles"][flag] = role self._flag_roles[self._flags[flag]] = role @@ -840,21 +840,28 @@ class Architecture(object): count[0] = 0 return None - def _get_flag_role(self, ctxt, flag): + def _get_flag_role(self, ctxt, flag, sem_class): try: - if flag in self._flag_roles: - return self._flag_roles[flag] - return FlagRole.SpecialFlagRole + if sem_class in self._semantic_flag_classes_by_index: + sem_class = self._semantic_flag_classes_by_index[sem_class] + else: + sem_class = None + return self.perform_get_flag_role(flag, sem_class) except KeyError: log.log_error(traceback.format_exc()) - return None + return FlagRole.SpecialFlagRole + + def perform_get_flag_role(self, flag, sem_class): + if flag in self._flag_roles: + return self._flag_roles[flag] + return FlagRole.SpecialFlagRole def _get_flags_required_for_flag_condition(self, ctxt, cond, sem_class, count): try: if sem_class in self._semantic_flag_classes_by_index: sem_class = self._semantic_flag_classes_by_index[sem_class] else: - sem_class = 0 + sem_class = None flag_names = self.perform_get_flags_required_for_flag_condition(cond, sem_class) flags = [] for name in flag_names: @@ -1322,7 +1329,7 @@ class Architecture(object): :param LowLevelILFunction il: LowLevelILFunction object to append LowLevelILExpr objects to :rtype: LowLevelILExpr """ - return self.get_default_flag_condition_low_level_il(cond, il) + return self.get_default_flag_condition_low_level_il(cond, sem_class, il) @abc.abstractmethod def perform_get_semantic_flag_group_low_level_il(self, sem_group, il): @@ -1744,6 +1751,19 @@ class Architecture(object): """ return self._semantic_flag_groups[sem_group] + def get_flag_role(self, flag, sem_class = None): + """ + ``get_flag_role`` gets the role of a given flag. + + :param int flag: flag + :param int sem_class: optional semantic flag class + :return: flag role + :rtype: FlagRole + """ + flag = self.get_flag_index(flag) + sem_class = self.get_semantic_flag_class_index(sem_class) + return FlagRole(core.BNGetArchitectureFlagRole(self.handle, flag, sem_class)) + def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): """ :param LowLevelILOperation op: @@ -1801,13 +1821,15 @@ class Architecture(object): """ return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) - def get_default_flag_condition_low_level_il(self, cond, il): + def get_default_flag_condition_low_level_il(self, cond, sem_class, il): """ :param LowLevelILFlagCondition cond: :param LowLevelILFunction il: + :param str sem_class: :rtype: LowLevelILExpr """ - return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + class_index = self.get_semantic_flag_class_index(sem_class) + return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, class_index, il.handle)) def get_semantic_flag_group_low_level_il(self, sem_group, il): """ -- cgit v1.3.1 From 2f3873928078e8c21911ffeb5476781b31886514 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 31 Jan 2018 20:24:16 -0500 Subject: Adding CPU intrinsics support --- architecture.cpp | 159 +++++++++++++++++++ binaryninjaapi.h | 39 +++++ binaryninjacore.h | 40 ++++- lowlevelil.cpp | 25 +++ lowlevelilinstruction.cpp | 355 ++++++++++++++++++++++++++++++++++++++++++- lowlevelilinstruction.h | 129 ++++++++++++++++ mediumlevelilinstruction.cpp | 71 ++++++++- mediumlevelilinstruction.h | 20 +++ python/architecture.py | 154 +++++++++++++++++++ python/function.py | 23 ++- python/lowlevelil.py | 109 ++++++++++--- python/mediumlevelil.py | 4 + 12 files changed, 1095 insertions(+), 33 deletions(-) (limited to 'architecture.cpp') diff --git a/architecture.cpp b/architecture.cpp index 78a67105..223af13d 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -491,6 +491,79 @@ void Architecture::GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, B } +char* Architecture::GetIntrinsicNameCallback(void* ctxt, uint32_t intrinsic) +{ + Architecture* arch = (Architecture*)ctxt; + string result = arch->GetIntrinsicName(intrinsic); + return BNAllocString(result.c_str()); +} + + +uint32_t* Architecture::GetAllIntrinsicsCallback(void* ctxt, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector regs = arch->GetAllIntrinsics(); + *count = regs.size(); + + uint32_t* result = new uint32_t[regs.size()]; + for (size_t i = 0; i < regs.size(); i++) + result[i] = regs[i]; + return result; +} + + +BNNameAndType* Architecture::GetIntrinsicInputsCallback(void* ctxt, uint32_t intrinsic, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector inputs = arch->GetIntrinsicInputs(intrinsic); + *count = inputs.size(); + + BNNameAndType* result = new BNNameAndType[inputs.size()]; + for (size_t i = 0; i < inputs.size(); i++) + { + result[i].name = BNAllocString(inputs[i].name.c_str()); + result[i].type = BNNewTypeReference(inputs[i].type.GetValue()->GetObject()); + result[i].typeConfidence = inputs[i].type.GetConfidence(); + } + return result; +} + + +void Architecture::FreeNameAndTypeListCallback(void*, BNNameAndType* nt, size_t count) +{ + for (size_t i = 0; i < count; i++) + { + BNFreeString(nt[i].name); + BNFreeType(nt[i].type); + } + delete[] nt; +} + + +BNTypeWithConfidence* Architecture::GetIntrinsicOutputsCallback(void* ctxt, uint32_t intrinsic, size_t* count) +{ + Architecture* arch = (Architecture*)ctxt; + vector>> outputs = arch->GetIntrinsicOutputs(intrinsic); + *count = outputs.size(); + + BNTypeWithConfidence* result = new BNTypeWithConfidence[outputs.size()]; + for (size_t i = 0; i < outputs.size(); i++) + { + result[i].type = BNNewTypeReference(outputs[i].GetValue()->GetObject()); + result[i].confidence = outputs[i].GetConfidence(); + } + return result; +} + + +void Architecture::FreeTypeListCallback(void*, BNTypeWithConfidence* types, size_t count) +{ + for (size_t i = 0; i < count; i++) + BNFreeType(types[i].type); + delete[] types; +} + + bool Architecture::AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors) { Architecture* arch = (Architecture*)ctxt; @@ -612,6 +685,12 @@ void Architecture::Register(Architecture* arch) callbacks.getRegisterStackName = GetRegisterStackNameCallback; callbacks.getAllRegisterStacks = GetAllRegisterStacksCallback; callbacks.getRegisterStackInfo = GetRegisterStackInfoCallback; + callbacks.getIntrinsicName = GetIntrinsicNameCallback; + callbacks.getAllIntrinsics = GetAllIntrinsicsCallback; + callbacks.getIntrinsicInputs = GetIntrinsicInputsCallback; + callbacks.freeNameAndTypeList = FreeNameAndTypeListCallback; + callbacks.getIntrinsicOutputs = GetIntrinsicOutputsCallback; + callbacks.freeTypeList = FreeTypeListCallback; callbacks.assemble = AssembleCallback; callbacks.isNeverBranchPatchAvailable = IsNeverBranchPatchAvailableCallback; callbacks.isAlwaysBranchPatchAvailable = IsAlwaysBranchPatchAvailableCallback; @@ -920,6 +999,32 @@ uint32_t Architecture::GetRegisterStackForRegister(uint32_t reg) } +string Architecture::GetIntrinsicName(uint32_t intrinsic) +{ + char intrinsicStr[32]; + sprintf(intrinsicStr, "intrinsic_%" PRIu32, intrinsic); + return intrinsicStr; +} + + +vector Architecture::GetAllIntrinsics() +{ + return vector(); +} + + +vector Architecture::GetIntrinsicInputs(uint32_t) +{ + return vector(); +} + + +vector>> Architecture::GetIntrinsicOutputs(uint32_t) +{ + return vector>>(); +} + + vector Architecture::GetModifiedRegistersOnWrite(uint32_t reg) { size_t count; @@ -1477,6 +1582,60 @@ BNRegisterStackInfo CoreArchitecture::GetRegisterStackInfo(uint32_t regStack) } +string CoreArchitecture::GetIntrinsicName(uint32_t intrinsic) +{ + char* name = BNGetArchitectureIntrinsicName(m_object, intrinsic); + string result = name; + BNFreeString(name); + return result; +} + + +vector CoreArchitecture::GetAllIntrinsics() +{ + size_t count; + uint32_t* regs = BNGetAllArchitectureIntrinsics(m_object, &count); + + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(regs[i]); + + BNFreeRegisterList(regs); + return result; +} + + +vector CoreArchitecture::GetIntrinsicInputs(uint32_t intrinsic) +{ + size_t count; + BNNameAndType* inputs = BNGetArchitectureIntrinsicInputs(m_object, intrinsic, &count); + + vector result; + for (size_t i = 0; i < count; i++) + { + result.push_back(NameAndType(inputs[i].name, Confidence>( + new Type(BNNewTypeReference(inputs[i].type)), inputs[i].typeConfidence))); + } + + BNFreeNameAndTypeList(inputs, count); + return result; +} + + +vector>> CoreArchitecture::GetIntrinsicOutputs(uint32_t intrinsic) +{ + size_t count; + BNTypeWithConfidence* outputs = BNGetArchitectureIntrinsicOutputs(m_object, intrinsic, &count); + + vector>> result; + for (size_t i = 0; i < count; i++) + result.push_back(Confidence>(new Type(BNNewTypeReference(outputs[i].type)), outputs[i].confidence)); + + BNFreeOutputTypeList(outputs, count); + return result; +} + + bool CoreArchitecture::Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) { char* errorStr = nullptr; diff --git a/binaryninjaapi.h b/binaryninjaapi.h index b74fa971..d1ca9cdb 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1566,6 +1566,16 @@ namespace BinaryNinja void AddBranch(BNBranchType type, uint64_t target = 0, Architecture* arch = nullptr, bool hasDelaySlot = false); }; + struct NameAndType + { + std::string name; + Confidence> type; + + NameAndType() {} + NameAndType(const Confidence>& t): type(t) {} + NameAndType(const std::string& n, const Confidence>& t): name(n), type(t) {} + }; + class LowLevelILFunction; class FunctionRecognizer; class CallingConvention; @@ -1633,6 +1643,13 @@ namespace BinaryNinja static uint32_t* GetAllRegisterStacksCallback(void* ctxt, size_t* count); static void GetRegisterStackInfoCallback(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result); + static char* GetIntrinsicNameCallback(void* ctxt, uint32_t intrinsic); + static uint32_t* GetAllIntrinsicsCallback(void* ctxt, size_t* count); + static BNNameAndType* GetIntrinsicInputsCallback(void* ctxt, uint32_t intrinsic, size_t* count); + static void FreeNameAndTypeListCallback(void* ctxt, BNNameAndType* nt, size_t count); + static BNTypeWithConfidence* GetIntrinsicOutputsCallback(void* ctxt, uint32_t intrinsic, size_t* count); + static void FreeTypeListCallback(void* ctxt, BNTypeWithConfidence* types, size_t count); + static bool AssembleCallback(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors); static bool IsNeverBranchPatchAvailableCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t len); static bool IsAlwaysBranchPatchAvailableCallback(void* ctxt, const uint8_t* data, uint64_t addr, size_t len); @@ -1714,6 +1731,11 @@ namespace BinaryNinja virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack); uint32_t GetRegisterStackForRegister(uint32_t reg); + virtual std::string GetIntrinsicName(uint32_t intrinsic); + virtual std::vector GetAllIntrinsics(); + virtual std::vector GetIntrinsicInputs(uint32_t intrinsic); + virtual std::vector>> GetIntrinsicOutputs(uint32_t intrinsic); + virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors); /*! IsNeverBranchPatchAvailable returns true if the instruction at addr can be patched to never branch. @@ -1853,6 +1875,11 @@ namespace BinaryNinja virtual std::vector GetAllRegisterStacks() override; virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack) override; + virtual std::string GetIntrinsicName(uint32_t intrinsic) override; + virtual std::vector GetAllIntrinsics() override; + virtual std::vector GetIntrinsicInputs(uint32_t intrinsic) override; + virtual std::vector>> GetIntrinsicOutputs(uint32_t intrinsic) override; + virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors) override; virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; @@ -2452,9 +2479,11 @@ namespace BinaryNinja }; struct LowLevelILInstruction; + struct RegisterOrFlag; struct SSARegister; struct SSARegisterStack; struct SSAFlag; + struct SSARegisterOrFlag; class LowLevelILFunction: public CoreRefCountObject @@ -2641,6 +2670,10 @@ namespace BinaryNinja ExprId TestBit(size_t size, ExprId a, ExprId b, const ILSourceLocation& loc = ILSourceLocation()); ExprId BoolToInt(size_t size, ExprId a, const ILSourceLocation& loc = ILSourceLocation()); ExprId SystemCall(const ILSourceLocation& loc = ILSourceLocation()); + ExprId Intrinsic(const std::vector& outputs, uint32_t intrinsic, + const std::vector& params, const ILSourceLocation& loc = ILSourceLocation()); + ExprId IntrinsicSSA(const std::vector& outputs, uint32_t intrinsic, + const std::vector& params, const ILSourceLocation& loc = ILSourceLocation()); ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation()); ExprId Trap(uint32_t num, const ILSourceLocation& loc = ILSourceLocation()); ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); @@ -2686,9 +2719,11 @@ namespace BinaryNinja ExprId AddLabelList(const std::vector& labels); ExprId AddOperandList(const std::vector operands); ExprId AddIndexList(const std::vector operands); + ExprId AddRegisterOrFlagList(const std::vector& regs); ExprId AddSSARegisterList(const std::vector& regs); ExprId AddSSARegisterStackList(const std::vector& regStacks); ExprId AddSSAFlagList(const std::vector& flags); + ExprId AddSSARegisterOrFlagList(const std::vector& regs); ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); ExprId GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); @@ -2954,6 +2989,10 @@ namespace BinaryNinja const ILSourceLocation& loc = ILSourceLocation()); ExprId Breakpoint(const ILSourceLocation& loc = ILSourceLocation()); ExprId Trap(int64_t vector, const ILSourceLocation& loc = ILSourceLocation()); + ExprId Intrinsic(const std::vector& outputs, uint32_t intrinsic, + const std::vector& params, const ILSourceLocation& loc = ILSourceLocation()); + ExprId IntrinsicSSA(const std::vector& outputs, uint32_t intrinsic, + const std::vector& params, const ILSourceLocation& loc = ILSourceLocation()); ExprId Undefined(const ILSourceLocation& loc = ILSourceLocation()); ExprId Unimplemented(const ILSourceLocation& loc = ILSourceLocation()); ExprId UnimplementedMemoryRef(size_t size, ExprId target, diff --git a/binaryninjacore.h b/binaryninjacore.h index bc58092d..a946df31 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -352,6 +352,7 @@ extern "C" LLIL_SYSCALL, LLIL_BP, LLIL_TRAP, + LLIL_INTRINSIC, LLIL_UNDEF, LLIL_UNIMPL, LLIL_UNIMPL_MEM, @@ -394,11 +395,12 @@ extern "C" LLIL_FLAG_BIT_SSA, LLIL_CALL_SSA, LLIL_SYSCALL_SSA, - LLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions + LLIL_CALL_PARAM, // Only valid within the LLIL_CALL_SSA, LLIL_SYSCALL_SSA, LLIL_INTRINSIC, LLIL_INTRINSIC_SSA instructions LLIL_CALL_STACK_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions LLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions LLIL_LOAD_SSA, LLIL_STORE_SSA, + LLIL_INTRINSIC_SSA, LLIL_REG_PHI, LLIL_REG_STACK_PHI, LLIL_FLAG_PHI, @@ -858,6 +860,7 @@ extern "C" MLIL_ADD_OVERFLOW, MLIL_SYSCALL, // Not valid in SSA form (see MLIL_SYSCALL_SSA) MLIL_SYSCALL_UNTYPED, // Not valid in SSA form (see MLIL_SYSCALL_UNTYPED_SSA) + MLIL_INTRINSIC, // Not valid in SSA form (see MLIL_INTRINSIC_SSA) MLIL_BP, MLIL_TRAP, MLIL_UNDEF, @@ -905,6 +908,7 @@ extern "C" MLIL_LOAD_STRUCT_SSA, MLIL_STORE_SSA, MLIL_STORE_STRUCT_SSA, + MLIL_INTRINSIC_SSA, MLIL_VAR_PHI, MLIL_MEM_PHI }; @@ -1077,6 +1081,19 @@ extern "C" BNLowLevelILFlagCondition condition; }; + struct BNNameAndType + { + char* name; + BNType* type; + uint8_t typeConfidence; + }; + + struct BNTypeWithConfidence + { + BNType* type; + uint8_t confidence; + }; + struct BNCustomArchitecture { void* context; @@ -1127,6 +1144,13 @@ extern "C" uint32_t* (*getAllRegisterStacks)(void* ctxt, size_t* count); void (*getRegisterStackInfo)(void* ctxt, uint32_t regStack, BNRegisterStackInfo* result); + char* (*getIntrinsicName)(void* ctxt, uint32_t intrinsic); + uint32_t* (*getAllIntrinsics)(void* ctxt, size_t* count); + BNNameAndType* (*getIntrinsicInputs)(void* ctxt, uint32_t intrinsic, size_t* count); + void (*freeNameAndTypeList)(void* ctxt, BNNameAndType* nt, size_t count); + BNTypeWithConfidence* (*getIntrinsicOutputs)(void* ctxt, uint32_t intrinsic, size_t* count); + void (*freeTypeList)(void* ctxt, BNTypeWithConfidence* types, size_t count); + bool (*assemble)(void* ctxt, const char* code, uint64_t addr, BNDataBuffer* result, char** errors); bool (*isNeverBranchPatchAvailable)(void* ctxt, const uint8_t* data, uint64_t addr, size_t len); @@ -1203,12 +1227,6 @@ extern "C" char* (*serialize)(void* ctxt); }; - struct BNTypeWithConfidence - { - BNType* type; - uint8_t confidence; - }; - struct BNCallingConventionWithConfidence { BNCallingConvention* convention; @@ -2116,6 +2134,14 @@ extern "C" BINARYNINJACOREAPI BNRegisterStackInfo BNGetArchitectureRegisterStackInfo(BNArchitecture* arch, uint32_t regStack); BINARYNINJACOREAPI uint32_t BNGetArchitectureRegisterStackForRegister(BNArchitecture* arch, uint32_t reg); + BINARYNINJACOREAPI char* BNGetArchitectureIntrinsicName(BNArchitecture* arch, uint32_t intrinsic); + BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureIntrinsics(BNArchitecture* arch, size_t* count); + BINARYNINJACOREAPI BNNameAndType* BNGetArchitectureIntrinsicInputs(BNArchitecture* arch, uint32_t intrinsic, size_t* count); + BINARYNINJACOREAPI void BNFreeNameAndTypeList(BNNameAndType* nt, size_t count); + BINARYNINJACOREAPI BNTypeWithConfidence* BNGetArchitectureIntrinsicOutputs(BNArchitecture* arch, uint32_t intrinsic, + size_t* count); + BINARYNINJACOREAPI void BNFreeOutputTypeList(BNTypeWithConfidence* types, size_t count); + BINARYNINJACOREAPI bool BNAssemble(BNArchitecture* arch, const char* code, uint64_t addr, BNDataBuffer* result, char** errors); BINARYNINJACOREAPI bool BNIsArchitectureNeverBranchPatchAvailable(BNArchitecture* arch, const uint8_t* data, diff --git a/lowlevelil.cpp b/lowlevelil.cpp index c72d4b68..0f2b29be 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -216,6 +216,17 @@ ExprId LowLevelILFunction::AddIndexList(const vector operands) } +ExprId LowLevelILFunction::AddRegisterOrFlagList(const vector& regs) +{ + uint64_t* operandList = new uint64_t[regs.size()]; + for (size_t i = 0; i < regs.size(); i++) + operandList[i] = regs[i].ToIdentifier(); + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, regs.size()); + delete[] operandList; + return result; +} + + ExprId LowLevelILFunction::AddSSARegisterList(const vector& regs) { uint64_t* operandList = new uint64_t[regs.size() * 2]; @@ -258,6 +269,20 @@ ExprId LowLevelILFunction::AddSSAFlagList(const vector& flags) } +ExprId LowLevelILFunction::AddSSARegisterOrFlagList(const vector& regs) +{ + uint64_t* operandList = new uint64_t[regs.size() * 2]; + for (size_t i = 0; i < regs.size(); i++) + { + operandList[i * 2] = regs[i].regOrFlag.ToIdentifier(); + operandList[(i * 2) + 1] = regs[i].version; + } + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, regs.size() * 2); + delete[] operandList; + return result; +} + + ExprId LowLevelILFunction::GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size) { if (operand.constant) diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index 9909e8ee..2c00db68 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -64,6 +64,7 @@ unordered_map {HighSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, {LowRegisterLowLevelOperandUsage, RegisterLowLevelOperand}, {LowSSARegisterLowLevelOperandUsage, SSARegisterLowLevelOperand}, + {IntrinsicLowLevelOperandUsage, IntrinsicLowLevelOperand}, {ConstantLowLevelOperandUsage, IntegerLowLevelOperand}, {VectorLowLevelOperandUsage, IntegerLowLevelOperand}, {StackAdjustmentLowLevelOperandUsage, IntegerLowLevelOperand}, @@ -80,6 +81,8 @@ unordered_map {SourceSSARegistersLowLevelOperandUsage, SSARegisterListLowLevelOperand}, {SourceSSARegisterStacksLowLevelOperandUsage, SSARegisterStackListLowLevelOperand}, {SourceSSAFlagsLowLevelOperandUsage, SSAFlagListLowLevelOperand}, + {OutputRegisterOrFlagListLowLevelOperandUsage, RegisterOrFlagListLowLevelOperand}, + {OutputSSARegisterOrFlagListLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, {SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, {TargetListLowLevelOperandUsage, IndexListLowLevelOperand}, {RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand} @@ -202,6 +205,10 @@ unordered_map> {LLIL_ZX, {SourceExprLowLevelOperandUsage}}, {LLIL_LOW_PART, {SourceExprLowLevelOperandUsage}}, {LLIL_BOOL_TO_INT, {SourceExprLowLevelOperandUsage}}, + {LLIL_INTRINSIC, {OutputRegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, + ParameterExprsLowLevelOperandUsage}}, + {LLIL_INTRINSIC_SSA, {OutputSSARegisterOrFlagListLowLevelOperandUsage, IntrinsicLowLevelOperandUsage, + ParameterExprsLowLevelOperandUsage}}, {LLIL_UNIMPL_MEM, {SourceExprLowLevelOperandUsage}}, {LLIL_FADD, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, {LLIL_FSUB, {LeftExprLowLevelOperandUsage, RightExprLowLevelOperandUsage}}, @@ -268,6 +275,8 @@ static unordered_map() const } +const RegisterOrFlag LowLevelILRegisterOrFlagList::ListIterator::operator*() +{ + return RegisterOrFlag::FromIdentifier(*pos); +} + + +LowLevelILRegisterOrFlagList::LowLevelILRegisterOrFlagList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count) +{ +} + + +LowLevelILRegisterOrFlagList::const_iterator LowLevelILRegisterOrFlagList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILRegisterOrFlagList::const_iterator LowLevelILRegisterOrFlagList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILRegisterOrFlagList::size() const +{ + return m_list.size(); +} + + +const RegisterOrFlag LowLevelILRegisterOrFlagList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILRegisterOrFlagList::operator vector() const +{ + vector result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + const SSARegister LowLevelILSSARegisterList::ListIterator::operator*() { LowLevelILIntegerList::const_iterator cur = pos; @@ -818,6 +1004,64 @@ LowLevelILSSAFlagList::operator vector() const } +const SSARegisterOrFlag LowLevelILSSARegisterOrFlagList::ListIterator::operator*() +{ + LowLevelILIntegerList::const_iterator cur = pos; + RegisterOrFlag rf = RegisterOrFlag::FromIdentifier(*cur); + ++cur; + size_t version = (size_t)*cur; + return SSARegisterOrFlag(rf, version); +} + + +LowLevelILSSARegisterOrFlagList::LowLevelILSSARegisterOrFlagList(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +LowLevelILSSARegisterOrFlagList::const_iterator LowLevelILSSARegisterOrFlagList::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILSSARegisterOrFlagList::const_iterator LowLevelILSSARegisterOrFlagList::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILSSARegisterOrFlagList::size() const +{ + return m_list.size() / 2; +} + + +const SSARegisterOrFlag LowLevelILSSARegisterOrFlagList::operator[](size_t i) const +{ + if (i >= size()) + throw LowLevelILInstructionAccessException(); + auto iter = begin(); + for (size_t j = 0; j < i; j++) + ++iter; + return *iter; +} + + +LowLevelILSSARegisterOrFlagList::operator vector() const +{ + vector result; + for (auto& i : *this) + result.push_back(i); + return result; +} + + LowLevelILOperand::LowLevelILOperand(const LowLevelILInstruction& instr, LowLevelILOperandUsage usage, size_t operandIndex): m_instr(instr), m_usage(usage), m_operandIndex(operandIndex) @@ -905,6 +1149,14 @@ uint32_t LowLevelILOperand::GetSemanticFlagGroup() const } +uint32_t LowLevelILOperand::GetIntrinsic() const +{ + if (m_type != IntrinsicLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegister(m_operandIndex); +} + + SSARegister LowLevelILOperand::GetSSARegister() const { if (m_type != SSARegisterLowLevelOperand) @@ -952,6 +1204,14 @@ LowLevelILInstructionList LowLevelILOperand::GetExprList() const } +LowLevelILRegisterOrFlagList LowLevelILOperand::GetRegisterOrFlagList() const +{ + if (m_type != RegisterOrFlagListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsRegisterOrFlagList(m_operandIndex); +} + + LowLevelILSSARegisterList LowLevelILOperand::GetSSARegisterList() const { if (m_type != SSARegisterListLowLevelOperand) @@ -978,6 +1238,14 @@ LowLevelILSSAFlagList LowLevelILOperand::GetSSAFlagList() const } +LowLevelILSSARegisterOrFlagList LowLevelILOperand::GetSSARegisterOrFlagList() const +{ + if (m_type != SSARegisterOrFlagListLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsSSARegisterOrFlagList(m_operandIndex); +} + + map LowLevelILOperand::GetRegisterStackAdjustments() const { if (m_type != RegisterStackAdjustmentsLowLevelOperand) @@ -1174,6 +1442,12 @@ LowLevelILInstructionList LowLevelILInstructionBase::GetRawOperandAsExprList(siz } +LowLevelILRegisterOrFlagList LowLevelILInstructionBase::GetRawOperandAsRegisterOrFlagList(size_t operand) const +{ + return LowLevelILRegisterOrFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + LowLevelILSSARegisterList LowLevelILInstructionBase::GetRawOperandAsSSARegisterList(size_t operand) const { return LowLevelILSSARegisterList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); @@ -1192,6 +1466,12 @@ LowLevelILSSAFlagList LowLevelILInstructionBase::GetRawOperandAsSSAFlagList(size } +LowLevelILSSARegisterOrFlagList LowLevelILInstructionBase::GetRawOperandAsSSARegisterOrFlagList(size_t operand) const +{ + return LowLevelILSSARegisterOrFlagList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + map LowLevelILInstructionBase::GetRawOperandAsRegisterStackAdjustments(size_t operand) const { LowLevelILIntegerList list(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); @@ -1224,6 +1504,14 @@ void LowLevelILInstructionBase::UpdateRawOperandAsSSARegisterList(size_t operand } +void LowLevelILInstructionBase::UpdateRawOperandAsSSARegisterOrFlagList(size_t operandIndex, + const vector& outputs) +{ + UpdateRawOperand(operandIndex, outputs.size() * 2); + UpdateRawOperand(operandIndex + 1, function->AddSSARegisterOrFlagList(outputs)); +} + + RegisterValue LowLevelILInstructionBase::GetValue() const { return function->GetExprValue(*(const LowLevelILInstruction*)this); @@ -1585,6 +1873,14 @@ void LowLevelILInstruction::VisitExprs(const std::function()) + i.VisitExprs(func); + break; + case LLIL_INTRINSIC_SSA: + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; default: break; } @@ -1839,6 +2135,16 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, subExprHandler(AsTwoOperandWithCarry().GetLeftExpr()), subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); + case LLIL_INTRINSIC: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->Intrinsic(GetOutputRegisterOrFlagList(), GetIntrinsic(), + params, *this); + case LLIL_INTRINSIC_SSA: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->IntrinsicSSA(GetOutputSSARegisterOrFlagList(), GetIntrinsic(), + params, *this); default: throw LowLevelILInstructionAccessException(); } @@ -2103,6 +2409,15 @@ SSARegister LowLevelILInstruction::GetLowSSARegister() const } +uint32_t LowLevelILInstruction::GetIntrinsic() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(IntrinsicLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegister(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + int64_t LowLevelILInstruction::GetConstant() const { size_t operandIndex; @@ -2242,6 +2557,24 @@ LowLevelILSSAFlagList LowLevelILInstruction::GetSourceSSAFlags() const } +LowLevelILRegisterOrFlagList LowLevelILInstruction::GetOutputRegisterOrFlagList() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputRegisterOrFlagListLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsRegisterOrFlagList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILSSARegisterOrFlagList LowLevelILInstruction::GetOutputSSARegisterOrFlagList() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(OutputSSARegisterOrFlagListLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSARegisterOrFlagList(operandIndex); + throw LowLevelILInstructionAccessException(); +} + + LowLevelILIndexList LowLevelILInstruction::GetSourceMemoryVersions() const { size_t operandIndex; @@ -2759,7 +3092,7 @@ ExprId LowLevelILFunction::CallSSA(const vector& output, ExprId des AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer, output.size() * 2, AddSSARegisterList(output)), dest, AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer), - AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params))); } @@ -2771,7 +3104,7 @@ ExprId LowLevelILFunction::SystemCallSSA(const vector& output, cons AddExprWithLocation(LLIL_CALL_OUTPUT_SSA, loc, 0, 0, newMemoryVer, output.size() * 2, AddSSARegisterList(output)), AddExprWithLocation(LLIL_CALL_STACK_SSA, loc, 0, 0, stack.reg, stack.version, prevMemoryVer), - AddExprWithLocation(LLIL_CALL_PARAM_SSA, loc, 0, 0, + AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params))); } @@ -2878,6 +3211,24 @@ ExprId LowLevelILFunction::SystemCall(const ILSourceLocation& loc) } +ExprId LowLevelILFunction::Intrinsic(const vector& outputs, uint32_t intrinsic, + const vector& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_INTRINSIC, loc, 0, 0, + outputs.size(), AddRegisterOrFlagList(outputs), intrinsic, + AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params))); +} + + +ExprId LowLevelILFunction::IntrinsicSSA(const vector& outputs, uint32_t intrinsic, + const vector& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(LLIL_INTRINSIC_SSA, loc, 0, 0, + outputs.size() * 2, AddSSARegisterOrFlagList(outputs), intrinsic, + AddExprWithLocation(LLIL_CALL_PARAM, loc, 0, 0, params.size(), AddOperandList(params))); +} + + ExprId LowLevelILFunction::Breakpoint(const ILSourceLocation& loc) { return AddExprWithLocation(LLIL_BP, loc, 0, 0); diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index bb5041a6..4679f556 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -54,6 +54,31 @@ namespace BinaryNinja class LowLevelILOperand; class LowLevelILOperandList; + struct RegisterOrFlag + { + bool isFlag; + uint32_t index; + + RegisterOrFlag(); + RegisterOrFlag(bool flag, uint32_t i); + + bool IsRegister() const { return !isFlag; } + bool IsFlag() const { return isFlag; } + uint32_t GetRegister() const; + uint32_t GetFlag() const; + + RegisterOrFlag& operator=(const RegisterOrFlag& v); + bool operator==(const RegisterOrFlag& v) const; + bool operator!=(const RegisterOrFlag& v) const; + bool operator<(const RegisterOrFlag& v) const; + + uint64_t ToIdentifier() const; + static RegisterOrFlag FromIdentifier(uint64_t id); + + static RegisterOrFlag Register(uint32_t reg) { return RegisterOrFlag(false, reg); } + static RegisterOrFlag Flag(uint32_t flag) { return RegisterOrFlag(true, flag); } + }; + struct SSARegister { uint32_t reg; @@ -99,6 +124,23 @@ namespace BinaryNinja bool operator<(const SSAFlag& v) const; }; + struct SSARegisterOrFlag + { + RegisterOrFlag regOrFlag; + size_t version; + + SSARegisterOrFlag(); + SSARegisterOrFlag(const RegisterOrFlag& rf, size_t i); + SSARegisterOrFlag(const SSARegister& v); + SSARegisterOrFlag(const SSAFlag& v); + SSARegisterOrFlag(const SSARegisterOrFlag& v); + + SSARegisterOrFlag& operator=(const SSARegisterOrFlag& v); + bool operator==(const SSARegisterOrFlag& v) const; + bool operator!=(const SSARegisterOrFlag& v) const; + bool operator<(const SSARegisterOrFlag& v) const; + }; + enum LowLevelILOperandType { IntegerLowLevelOperand, @@ -108,6 +150,7 @@ namespace BinaryNinja RegisterStackLowLevelOperand, FlagLowLevelOperand, FlagConditionLowLevelOperand, + IntrinsicLowLevelOperand, SemanticFlagClassLowLevelOperand, SemanticFlagGroupLowLevelOperand, SSARegisterLowLevelOperand, @@ -115,9 +158,11 @@ namespace BinaryNinja SSAFlagLowLevelOperand, IndexListLowLevelOperand, ExprListLowLevelOperand, + RegisterOrFlagListLowLevelOperand, SSARegisterListLowLevelOperand, SSARegisterStackListLowLevelOperand, SSAFlagListLowLevelOperand, + SSARegisterOrFlagListLowLevelOperand, RegisterStackAdjustmentsLowLevelOperand }; @@ -152,6 +197,7 @@ namespace BinaryNinja HighSSARegisterLowLevelOperandUsage, LowRegisterLowLevelOperandUsage, LowSSARegisterLowLevelOperandUsage, + IntrinsicLowLevelOperandUsage, ConstantLowLevelOperandUsage, VectorLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage, @@ -168,6 +214,8 @@ namespace BinaryNinja SourceSSARegistersLowLevelOperandUsage, SourceSSARegisterStacksLowLevelOperandUsage, SourceSSAFlagsLowLevelOperandUsage, + OutputRegisterOrFlagListLowLevelOperandUsage, + OutputSSARegisterOrFlagListLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage, TargetListLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperandUsage @@ -365,6 +413,33 @@ namespace BinaryNinja operator std::vector() const; }; + class LowLevelILRegisterOrFlagList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; return *this; } + const RegisterOrFlag operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILRegisterOrFlagList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const RegisterOrFlag operator[](size_t i) const; + + operator std::vector() const; + }; + class LowLevelILSSARegisterList { struct ListIterator @@ -446,6 +521,33 @@ namespace BinaryNinja operator std::vector() const; }; + class LowLevelILSSARegisterOrFlagList + { + struct ListIterator + { + LowLevelILIntegerList::const_iterator pos; + bool operator==(const ListIterator& a) const { return pos == a.pos; } + bool operator!=(const ListIterator& a) const { return pos != a.pos; } + bool operator<(const ListIterator& a) const { return pos < a.pos; } + ListIterator& operator++() { ++pos; ++pos; return *this; } + const SSARegisterOrFlag operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILSSARegisterOrFlagList(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + const SSARegisterOrFlag operator[](size_t i) const; + + operator std::vector() const; + }; + struct LowLevelILInstructionBase: public BNLowLevelILInstruction { #ifdef BINARYNINJACORE_LIBRARY @@ -474,13 +576,16 @@ namespace BinaryNinja SSAFlag GetRawOperandAsSSAFlag(size_t operand) const; LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; LowLevelILInstructionList GetRawOperandAsExprList(size_t operand) const; + LowLevelILRegisterOrFlagList GetRawOperandAsRegisterOrFlagList(size_t operand) const; LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const; LowLevelILSSARegisterStackList GetRawOperandAsSSARegisterStackList(size_t operand) const; LowLevelILSSAFlagList GetRawOperandAsSSAFlagList(size_t operand) const; + LowLevelILSSARegisterOrFlagList GetRawOperandAsSSARegisterOrFlagList(size_t operand) const; std::map GetRawOperandAsRegisterStackAdjustments(size_t operand) const; void UpdateRawOperand(size_t operandIndex, ExprId value); void UpdateRawOperandAsSSARegisterList(size_t operandIndex, const std::vector& regs); + void UpdateRawOperandAsSSARegisterOrFlagList(size_t operandIndex, const std::vector& outputs); RegisterValue GetValue() const; PossibleValueSet GetPossibleValues() const; @@ -604,6 +709,7 @@ namespace BinaryNinja template SSARegister GetHighSSARegister() const { return As().GetHighSSARegister(); } template uint32_t GetLowRegister() const { return As().GetLowRegister(); } template SSARegister GetLowSSARegister() const { return As().GetLowSSARegister(); } + template uint32_t GetIntrinsic() const { return As().GetIntrinsic(); } template int64_t GetConstant() const { return As().GetConstant(); } template int64_t GetVector() const { return As().GetVector(); } template size_t GetStackAdjustment() const { return As().GetStackAdjustment(); } @@ -619,6 +725,8 @@ namespace BinaryNinja template LowLevelILSSARegisterList GetSourceSSARegisters() const { return As().GetSourceSSARegisters(); } template LowLevelILSSARegisterStackList GetSourceSSARegisterStacks() const { return As().GetSourceSSARegisterStacks(); } template LowLevelILSSAFlagList GetSourceSSAFlags() const { return As().GetSourceSSAFlags(); } + template LowLevelILRegisterOrFlagList GetOutputRegisterOrFlagList() const { return As().GetOutputRegisterOrFlagList(); } + template LowLevelILSSARegisterOrFlagList GetOutputSSARegisterOrFlagList() const { return As().GetOutputSSARegisterOrFlagList(); } template LowLevelILIndexList GetSourceMemoryVersions() const { return As().GetSourceMemoryVersions(); } template LowLevelILIndexList GetTargetList() const { return As().GetTargetList(); } template std::map GetRegisterStackAdjustments() const { return As().GetRegisterStackAdjustments(); } @@ -632,6 +740,7 @@ namespace BinaryNinja template void SetDestMemoryVersion(size_t version) { As().SetDestMemoryVersion(version); } template void SetSourceMemoryVersion(size_t version) { As().SetSourceMemoryVersion(version); } template void SetOutputSSARegisters(const std::vector& regs) { As().SetOutputSSARegisters(regs); } + template void SetOutputSSARegisterOrFlagList(const std::vector& outputs) { As().SetOutputSSARegisterOrFlagList(outputs); } bool GetOperandIndexForUsage(LowLevelILOperandUsage usage, size_t& operandIndex) const; @@ -664,6 +773,7 @@ namespace BinaryNinja SSARegister GetHighSSARegister() const; uint32_t GetLowRegister() const; SSARegister GetLowSSARegister() const; + uint32_t GetIntrinsic() const; int64_t GetConstant() const; int64_t GetVector() const; size_t GetStackAdjustment() const; @@ -679,6 +789,8 @@ namespace BinaryNinja LowLevelILSSARegisterList GetSourceSSARegisters() const; LowLevelILSSARegisterStackList GetSourceSSARegisterStacks() const; LowLevelILSSAFlagList GetSourceSSAFlags() const; + LowLevelILRegisterOrFlagList GetOutputRegisterOrFlagList() const; + LowLevelILSSARegisterOrFlagList GetOutputSSARegisterOrFlagList() const; LowLevelILIndexList GetSourceMemoryVersions() const; LowLevelILIndexList GetTargetList() const; std::map GetRegisterStackAdjustments() const; @@ -706,6 +818,7 @@ namespace BinaryNinja uint32_t GetFlag() const; uint32_t GetSemanticFlagClass() const; uint32_t GetSemanticFlagGroup() const; + uint32_t GetIntrinsic() const; BNLowLevelILFlagCondition GetFlagCondition() const; SSARegister GetSSARegister() const; SSARegisterStack GetSSARegisterStack() const; @@ -715,6 +828,8 @@ namespace BinaryNinja LowLevelILSSARegisterList GetSSARegisterList() const; LowLevelILSSARegisterStackList GetSSARegisterStackList() const; LowLevelILSSAFlagList GetSSAFlagList() const; + LowLevelILRegisterOrFlagList GetRegisterOrFlagList() const; + LowLevelILSSARegisterOrFlagList GetSSARegisterOrFlagList() const; std::map GetRegisterStackAdjustments() const; }; @@ -1022,6 +1137,20 @@ namespace BinaryNinja void SetOutputSSARegisters(const std::vector& regs) { GetRawOperandAsExpr(0).UpdateRawOperandAsSSARegisterList(1, regs); } }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILRegisterOrFlagList GetOutputRegisterOrFlagList() const { return GetRawOperandAsRegisterOrFlagList(0); } + uint32_t GetIntrinsic() const { return GetRawOperandAsRegister(2); } + LowLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(3).GetRawOperandAsExprList(0); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase + { + LowLevelILSSARegisterOrFlagList GetOutputSSARegisterOrFlagList() const { return GetRawOperandAsSSARegisterOrFlagList(0); } + uint32_t GetIntrinsic() const { return GetRawOperandAsRegister(2); } + LowLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExpr(3).GetRawOperandAsExprList(0); } + void SetOutputSSARegisterOrFlagList(const std::vector& outputs) { UpdateRawOperandAsSSARegisterOrFlagList(0, outputs); } + }; + template <> struct LowLevelILInstructionAccessor: public LowLevelILInstructionBase { SSARegister GetDestSSARegister() const { return GetRawOperandAsSSARegister(0); } diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index e911c298..7e1e663f 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -54,6 +54,7 @@ unordered_map {OffsetMediumLevelOperandUsage, IntegerMediumLevelOperand}, {ConstantMediumLevelOperandUsage, IntegerMediumLevelOperand}, {VectorMediumLevelOperandUsage, IntegerMediumLevelOperand}, + {IntrinsicMediumLevelOperandUsage, IntrinsicMediumLevelOperand}, {TargetMediumLevelOperandUsage, IndexMediumLevelOperand}, {TrueTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, {FalseTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, @@ -64,6 +65,7 @@ unordered_map {OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, {OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand}, {OutputSSAVariablesMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, + {OutputSSAVariablesSubExprMediumLevelOperandUsage, SSAVariableListMediumLevelOperand}, {OutputSSAMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, {ParameterExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, {SourceExprsMediumLevelOperandUsage, ExprListMediumLevelOperand}, @@ -127,23 +129,27 @@ unordered_map> {MLIL_SYSCALL, {OutputVariablesMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, {MLIL_SYSCALL_UNTYPED, {OutputVariablesSubExprMediumLevelOperandUsage, ParameterVariablesMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, - {MLIL_CALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + {MLIL_CALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - {MLIL_CALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + {MLIL_CALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterSSAVariablesMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, - {MLIL_SYSCALL_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + {MLIL_SYSCALL_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage}}, - {MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesMediumLevelOperandUsage, + {MLIL_SYSCALL_UNTYPED_SSA, {OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterSSAVariablesMediumLevelOperandUsage, ParameterSSAMemoryVersionMediumLevelOperandUsage, StackExprMediumLevelOperandUsage}}, {MLIL_RET, {SourceExprsMediumLevelOperandUsage}}, {MLIL_IF, {ConditionExprMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, FalseTargetMediumLevelOperandUsage}}, {MLIL_GOTO, {TargetMediumLevelOperandUsage}}, + {MLIL_INTRINSIC, {OutputVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage}}, + {MLIL_INTRINSIC_SSA, {OutputSSAVariablesMediumLevelOperandUsage, IntrinsicMediumLevelOperandUsage, + ParameterExprsMediumLevelOperandUsage}}, {MLIL_TRAP, {VectorMediumLevelOperandUsage}}, {MLIL_VAR_PHI, {DestSSAVariableMediumLevelOperandUsage, SourceSSAVariablesMediumLevelOperandUsages}}, {MLIL_MEM_PHI, {DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage}}, @@ -243,7 +249,7 @@ static unordered_map()) + i.VisitExprs(func); + break; + case MLIL_INTRINSIC_SSA: + for (auto& i : GetParameterExprs()) + i.VisitExprs(func); + break; default: break; } @@ -1609,6 +1631,16 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, return dest->Breakpoint(*this); case MLIL_TRAP: return dest->Trap(GetVector(), *this); + case MLIL_INTRINSIC: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->Intrinsic(GetOutputVariables(), + GetIntrinsic(), params, *this); + case MLIL_INTRINSIC_SSA: + for (auto& i : GetParameterExprs()) + params.push_back(subExprHandler(i)); + return dest->IntrinsicSSA(GetOutputSSAVariables(), + GetIntrinsic(), params, *this); case MLIL_UNDEF: return dest->Undefined(*this); case MLIL_UNIMPL: @@ -1796,6 +1828,15 @@ int64_t MediumLevelILInstruction::GetVector() const } +uint32_t MediumLevelILInstruction::GetIntrinsic() const +{ + size_t operandIndex; + if (GetOperandIndexForUsage(IntrinsicMediumLevelOperandUsage, operandIndex)) + return (uint32_t)GetRawOperandAsInteger(operandIndex); + throw MediumLevelILInstructionAccessException(); +} + + size_t MediumLevelILInstruction::GetTarget() const { size_t operandIndex; @@ -1878,6 +1919,8 @@ MediumLevelILSSAVariableList MediumLevelILInstruction::GetOutputSSAVariables() c { size_t operandIndex; if (GetOperandIndexForUsage(OutputSSAVariablesMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsSSAVariableList(operandIndex); + if (GetOperandIndexForUsage(OutputSSAVariablesSubExprMediumLevelOperandUsage, operandIndex)) return GetRawOperandAsExpr(operandIndex).GetRawOperandAsSSAVariableList(1); throw MediumLevelILInstructionAccessException(); } @@ -2577,6 +2620,22 @@ ExprId MediumLevelILFunction::Trap(int64_t vector, const ILSourceLocation& loc) } +ExprId MediumLevelILFunction::Intrinsic(const vector& outputs, uint32_t intrinsic, + const vector& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_INTRINSIC, loc, 0, outputs.size(), AddVariableList(outputs), + intrinsic, params.size(), AddOperandList(params)); +} + + +ExprId MediumLevelILFunction::IntrinsicSSA(const vector& outputs, uint32_t intrinsic, + const vector& params, const ILSourceLocation& loc) +{ + return AddExprWithLocation(MLIL_INTRINSIC_SSA, loc, 0, outputs.size() * 2, AddSSAVariableList(outputs), + intrinsic, params.size(), AddOperandList(params)); +} + + ExprId MediumLevelILFunction::Undefined(const ILSourceLocation& loc) { return AddExprWithLocation(MLIL_UNDEF, loc, 0); diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 8e671aaf..de92764d 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -70,6 +70,7 @@ namespace BinaryNinja { IntegerMediumLevelOperand, IndexMediumLevelOperand, + IntrinsicMediumLevelOperand, ExprMediumLevelOperand, VariableMediumLevelOperand, SSAVariableMediumLevelOperand, @@ -100,6 +101,7 @@ namespace BinaryNinja OffsetMediumLevelOperandUsage, ConstantMediumLevelOperandUsage, VectorMediumLevelOperandUsage, + IntrinsicMediumLevelOperandUsage, TargetMediumLevelOperandUsage, TrueTargetMediumLevelOperandUsage, FalseTargetMediumLevelOperandUsage, @@ -110,6 +112,7 @@ namespace BinaryNinja OutputVariablesMediumLevelOperandUsage, OutputVariablesSubExprMediumLevelOperandUsage, OutputSSAVariablesMediumLevelOperandUsage, + OutputSSAVariablesSubExprMediumLevelOperandUsage, OutputSSAMemoryVersionMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage, SourceExprsMediumLevelOperandUsage, @@ -485,6 +488,7 @@ namespace BinaryNinja template uint64_t GetOffset() const { return As().GetOffset(); } template int64_t GetConstant() const { return As().GetConstant(); } template int64_t GetVector() const { return As().GetVector(); } + template uint32_t GetIntrinsic() const { return As().GetIntrinsic(); } template size_t GetTarget() const { return As().GetTarget(); } template size_t GetTrueTarget() const { return As().GetTrueTarget(); } template size_t GetFalseTarget() const { return As().GetFalseTarget(); } @@ -535,6 +539,7 @@ namespace BinaryNinja uint64_t GetOffset() const; int64_t GetConstant() const; int64_t GetVector() const; + uint32_t GetIntrinsic() const; size_t GetTarget() const; size_t GetTrueTarget() const; size_t GetFalseTarget() const; @@ -567,6 +572,7 @@ namespace BinaryNinja uint64_t GetInteger() const; size_t GetIndex() const; + uint32_t GetIntrinsic() const; MediumLevelILInstruction GetExpr() const; Variable GetVariable() const; SSAVariable GetSSAVariable() const; @@ -902,6 +908,20 @@ namespace BinaryNinja size_t GetTarget() const { return GetRawOperandAsIndex(0); } }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILVariableList GetOutputVariables() const { return GetRawOperandAsVariableList(0); } + uint32_t GetIntrinsic() const { return (uint32_t)GetRawOperandAsInteger(2); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase + { + MediumLevelILSSAVariableList GetOutputSSAVariables() const { return GetRawOperandAsSSAVariableList(0); } + uint32_t GetIntrinsic() const { return (uint32_t)GetRawOperandAsInteger(2); } + MediumLevelILInstructionList GetParameterExprs() const { return GetRawOperandAsExprList(3); } + void SetOutputSSAVariables(const std::vector& vars) { UpdateRawOperandAsSSAVariableList(0, vars); } + }; + template <> struct MediumLevelILInstructionAccessor: public MediumLevelILInstructionBase { int64_t GetVector() const { return GetRawOperandAsInteger(0); } diff --git a/python/architecture.py b/python/architecture.py index 2b422962..3ccd2b11 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -33,6 +33,7 @@ import callingconvention import platform import log import databuffer +import types class _ArchitectureMetaClass(type): @@ -128,6 +129,7 @@ class Architecture(object): flags_written_by_flag_write_type = {} semantic_class_for_flag_write_type = {} reg_stacks = {} + intrinsics = {} __metaclass__ = _ArchitectureMetaClass next_address = 0 @@ -304,6 +306,27 @@ class Architecture(object): top = core.BNGetArchitectureRegisterName(self.handle, info.stackTopReg) self.reg_stacks[name] = function.RegisterStackInfo(storage, top_rel, top, regs[i]) core.BNFreeRegisterList(regs) + + count = ctypes.c_ulonglong() + intrinsics = core.BNGetAllArchitectureIntrinsics(self.handle, count) + self.__dict__["intrinsics"] = {} + for i in xrange(0, count.value): + name = core.BNGetArchitectureIntrinsicName(self.handle, intrinsics[i]) + input_count = ctypes.c_ulonglong() + inputs = core.BNGetArchitectureIntrinsicInputs(self.handle, intrinsics[i], input_count) + input_list = [] + for j in xrange(0, input_count.value): + input_name = inputs[j].name + type_obj = types.Type(core.BNNewTypeReference(inputs[j].type), confidence = inputs[j].typeConfidence) + input_list.append(function.IntrinsicInput(type_obj, input_name)) + core.BNFreeNameAndTypeList(inputs, input_count.value) + output_count = ctypes.c_ulonglong() + outputs = core.BNGetArchitectureIntrinsicOutputs(self.handle, intrinsics[i], output_count) + output_list = [] + for j in xrange(0, output_count.value): + output_list.append(types.Type(core.BNNewTypeReference(outputs[j].type), confidence = outputs[j].confidence)) + core.BNFreeOutputTypeList(outputs, output_count.value) + self.intrinsics[name] = function.IntrinsicInfo(input_list, output_list) else: startup._init_plugins() @@ -365,6 +388,12 @@ class Architecture(object): self._cb.getRegisterStackName = self._cb.getRegisterStackName.__class__(self._get_register_stack_name) self._cb.getAllRegisterStacks = self._cb.getAllRegisterStacks.__class__(self._get_all_register_stacks) self._cb.getRegisterStackInfo = self._cb.getRegisterStackInfo.__class__(self._get_register_stack_info) + self._cb.getIntrinsicName = self._cb.getIntrinsicName.__class__(self._get_intrinsic_name) + self._cb.getAllIntrinsics = self._cb.getAllIntrinsics.__class__(self._get_all_intrinsics) + self._cb.getIntrinsicInputs = self._cb.getIntrinsicInputs.__class__(self._get_intrinsic_inputs) + self._cb.freeNameAndTypeList = self._cb.freeNameAndTypeList.__class__(self._free_name_and_type_list) + self._cb.getIntrinsicOutputs = self._cb.getIntrinsicOutputs.__class__(self._get_intrinsic_outputs) + self._cb.freeTypeList = self._cb.freeTypeList.__class__(self._free_type_list) self._cb.assemble = self._cb.assemble.__class__(self._assemble) self._cb.isNeverBranchPatchAvailable = self._cb.isNeverBranchPatchAvailable.__class__( self._is_never_branch_patch_available) @@ -514,9 +543,28 @@ class Architecture(object): self.__dict__["global_regs"] = self.__class__.global_regs + self._intrinsics = {} + self._intrinsics_by_index = {} + self.__dict__["intrinsics"] = self.__class__.intrinsics + intrinsic_index = 0 + for intrinsic in self.__class__.intrinsics.keys(): + if intrinsic not in self._intrinsics: + info = self.__class__.intrinsics[intrinsic] + for i in xrange(0, len(info.inputs)): + if isinstance(info.inputs[i], types.Type): + info.inputs[i] = function.IntrinsicInput(info.inputs[i]) + elif isinstance(info.inputs[i], tuple): + info.inputs[i] = function.IntrinsicInput(info.inputs[i][0], info.inputs[i][1]) + info.index = intrinsic_index + self._intrinsics[intrinsic] = intrinsic_index + self._intrinsics_by_index[intrinsic_index] = (intrinsic, info) + intrinsic_index += 1 + self._pending_reg_lists = {} self._pending_token_lists = {} self._pending_condition_lists = {} + self._pending_name_and_type_lists = {} + self._pending_type_lists = {} def __eq__(self, value): if not isinstance(value, Architecture): @@ -1116,6 +1164,95 @@ class Architecture(object): result[0].topRelativeCount = 0 result[0].stackTopReg = 0 + def _get_intrinsic_name(self, ctxt, intrinsic): + try: + if intrinsic in self._intrinsics_by_index: + return core.BNAllocString(self._intrinsics_by_index[intrinsic][0]) + return core.BNAllocString("") + except (KeyError, OSError): + log.log_error(traceback.format_exc()) + return core.BNAllocString("") + + def _get_all_intrinsics(self, ctxt, count): + try: + regs = self._intrinsics_by_index.keys() + count[0] = len(regs) + reg_buf = (ctypes.c_uint * len(regs))() + for i in xrange(0, len(regs)): + reg_buf[i] = regs[i] + result = ctypes.cast(reg_buf, ctypes.c_void_p) + self._pending_reg_lists[result.value] = (result, reg_buf) + return result.value + except KeyError: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _get_intrinsic_inputs(self, ctxt, intrinsic, count): + try: + if intrinsic in self._intrinsics_by_index: + inputs = self._intrinsics_by_index[intrinsic][1].inputs + count[0] = len(inputs) + input_buf = (core.BNNameAndType * len(inputs))() + for i in xrange(0, len(inputs)): + input_buf[i].name = inputs[i].name + input_buf[i].type = core.BNNewTypeReference(inputs[i].type.handle) + input_buf[i].typeConfidence = inputs[i].type.confidence + result = ctypes.cast(input_buf, ctypes.c_void_p) + self._pending_name_and_type_lists[result.value] = (result, input_buf, len(inputs)) + return result.value + count[0] = 0 + return None + except: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _free_name_and_type_list(self, ctxt, buf_raw): + try: + buf = ctypes.cast(buf_raw, ctypes.c_void_p) + if buf.value not in self._pending_name_and_type_lists: + raise ValueError("freeing name and type list that wasn't allocated") + name_and_types = self._pending_name_and_type_lists[buf.value][1] + count = self._pending_name_and_type_lists[buf.value][2] + for i in xrange(0, count): + core.BNFreeType(name_and_types[i].type) + del self._pending_name_and_type_lists[buf.value] + except (ValueError, KeyError): + log.log_error(traceback.format_exc()) + + def _get_intrinsic_outputs(self, ctxt, intrinsic, count): + try: + if intrinsic in self._intrinsics_by_index: + outputs = self._intrinsics_by_index[intrinsic][1].outputs + count[0] = len(outputs) + output_buf = (core.BNTypeWithConfidence * len(outputs))() + for i in xrange(0, len(outputs)): + output_buf[i].type = core.BNNewTypeReference(outputs[i].handle) + output_buf[i].confidence = outputs[i].confidence + result = ctypes.cast(output_buf, ctypes.c_void_p) + self._pending_type_lists[result.value] = (result, output_buf, len(outputs)) + return result.value + count[0] = 0 + return None + except: + log.log_error(traceback.format_exc()) + count[0] = 0 + return None + + def _free_type_list(self, ctxt, buf_raw): + try: + buf = ctypes.cast(buf_raw, ctypes.c_void_p) + if buf.value not in self._pending_type_lists: + raise ValueError("freeing type list that wasn't allocated") + types = self._pending_type_lists[buf.value][1] + count = self._pending_type_lists[buf.value][2] + for i in xrange(0, count): + core.BNFreeType(types[i].type) + del self._pending_type_lists[buf.value] + except (ValueError, KeyError): + log.log_error(traceback.format_exc()) + def _assemble(self, ctxt, code, addr, result, errors): try: data, error_str = self.perform_assemble(code, addr) @@ -1701,6 +1838,23 @@ class Architecture(object): return sem_group.index return sem_group + def get_intrinsic_name(self, intrinsic): + """ + ``get_intrinsic_name`` gets an intrinsic name from an intrinsic number. + + :param int intrinsic: intrinsic number + :return: the corresponding intrinsic string + :rtype: str + """ + return core.BNGetArchitectureIntrinsicName(self.handle, intrinsic) + + def get_intrinsic_index(self, intrinsic): + if isinstance(intrinsic, str): + return self._intrinsics[intrinsic] + elif isinstance(intrinsic, lowlevelil.ILIntrinsic): + return intrinsic.index + return intrinsic + def get_flag_write_type_name(self, write_type): """ ``get_flag_write_type_name`` gets the flag write type name for the given flag. diff --git a/python/function.py b/python/function.py index 10583b58..7607657f 100644 --- a/python/function.py +++ b/python/function.py @@ -427,7 +427,7 @@ class Function(object): """Function platform (read-only)""" if self._platform: return self._platform - else: + else: plat = core.BNGetFunctionPlatform(self.handle) if plat is None: return None @@ -1878,6 +1878,27 @@ class RegisterStackInfo(object): return "" % (len(self.storage_regs), self.stack_top_reg) +class IntrinsicInput(object): + def __init__(self, type_obj, name=""): + self.name = name + self.type = type_obj + + def __repr__(self): + if len(self.name) == 0: + return "" % str(self.type) + return "" % (str(self.type), self.name) + + +class IntrinsicInfo(object): + def __init__(self, inputs, outputs, index=None): + self.inputs = inputs + self.outputs = outputs + self.index = index + + def __repr__(self): + return " %s>" % (repr(self.inputs), repr(self.outputs)) + + class InstructionBranch(object): def __init__(self, branch_type, target = 0, arch = None): self.type = branch_type diff --git a/python/lowlevelil.py b/python/lowlevelil.py index a2d77c9f..33296ce8 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -131,6 +131,25 @@ class ILSemanticFlagGroup(object): return self.index == other.index +class ILIntrinsic(object): + def __init__(self, arch, intrinsic): + self.arch = arch + self.index = intrinsic + self.name = self.arch.get_intrinsic_name(self.index) + if self.name in self.arch.intrinsics: + self.inputs = self.arch.intrinsics[self.name].inputs + self.outputs = self.arch.intrinsics[self.name].outputs + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + def __eq__(self, other): + return self.index == other.index + + class SSARegister(object): def __init__(self, reg, version): self.reg = reg @@ -158,6 +177,15 @@ class SSAFlag(object): return "" % (repr(self.flag), self.version) +class SSARegisterOrFlag(object): + def __init__(self, reg_or_flag, version): + self.reg_or_flag = reg_or_flag + self.version = version + + def __repr__(self): + return "" % (repr(self.reg_or_flag), self.version) + + class LowLevelILOperationAndSize(object): def __init__(self, operation, size): self.operation = operation @@ -250,6 +278,8 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_BOOL_TO_INT: [("src", "expr")], LowLevelILOperation.LLIL_ADD_OVERFLOW: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_SYSCALL: [], + LowLevelILOperation.LLIL_INTRINSIC: [("output", "reg_or_flag_list"), ("intrinsic", "intrinsic"), ("param", "expr")], + LowLevelILOperation.LLIL_INTRINSIC_SSA: [("output", "reg_or_flag_ssa_list"), ("intrinsic", "intrinsic"), ("param", "expr")], LowLevelILOperation.LLIL_BP: [], LowLevelILOperation.LLIL_TRAP: [("vector", "int")], LowLevelILOperation.LLIL_UNDEF: [], @@ -292,7 +322,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")], LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")], LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg_ssa"), ("src_memory", "int")], - LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "expr_list")], + LowLevelILOperation.LLIL_CALL_PARAM: [("src", "expr_list")], LowLevelILOperation.LLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], LowLevelILOperation.LLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg_ssa"), ("src", "reg_ssa_list")], @@ -336,6 +366,8 @@ class LowLevelILInstruction(object): value = ILRegister(func.arch, instr.operands[i]) elif operand_type == "reg_stack": value = ILRegisterStack(func.arch, instr.operands[i]) + elif operand_type == "intrinsic": + value = ILIntrinsic(func.arch, instr.operands[i]) elif operand_type == "reg_ssa": reg = ILRegister(func.arch, instr.operands[i]) i += 1 @@ -369,25 +401,36 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for i in xrange(count.value): - value.append(operand_list[i]) + for j in xrange(count.value): + value.append(operand_list[j]) core.BNLowLevelILFreeOperandList(operand_list) elif operand_type == "expr_list": count = ctypes.c_ulonglong() operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for i in xrange(count.value): - value.append(LowLevelILInstruction(func, operand_list[i])) + for j in xrange(count.value): + value.append(LowLevelILInstruction(func, operand_list[j])) + core.BNLowLevelILFreeOperandList(operand_list) + elif operand_type == "reg_or_flag_list": + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = [] + for j in xrange(count.value): + if (operand_list[j] & (1 << 32)) != 0: + value.append(ILFlag(func.arch, operand_list[j] & 0xffffffff)) + else: + value.append(ILRegister(func.arch, operand_list[j] & 0xffffffff)) core.BNLowLevelILFreeOperandList(operand_list) elif operand_type == "reg_ssa_list": count = ctypes.c_ulonglong() operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for i in xrange(count.value / 2): - reg = operand_list[i * 2] - reg_version = operand_list[(i * 2) + 1] + for j in xrange(count.value / 2): + reg = operand_list[j * 2] + reg_version = operand_list[(j * 2) + 1] value.append(SSARegister(ILRegister(func.arch, reg), reg_version)) core.BNLowLevelILFreeOperandList(operand_list) elif operand_type == "reg_stack_ssa_list": @@ -395,9 +438,9 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for i in xrange(count.value / 2): - reg_stack = operand_list[i * 2] - reg_version = operand_list[(i * 2) + 1] + for j in xrange(count.value / 2): + reg_stack = operand_list[j * 2] + reg_version = operand_list[(j * 2) + 1] value.append(SSARegisterStack(ILRegisterStack(func.arch, reg_stack), reg_version)) core.BNLowLevelILFreeOperandList(operand_list) elif operand_type == "flag_ssa_list": @@ -405,19 +448,32 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for i in xrange(count.value / 2): - flag = operand_list[i * 2] - flag_version = operand_list[(i * 2) + 1] + for j in xrange(count.value / 2): + flag = operand_list[j * 2] + flag_version = operand_list[(j * 2) + 1] value.append(SSAFlag(ILFlag(func.arch, flag), flag_version)) core.BNLowLevelILFreeOperandList(operand_list) + elif operand_type == "reg_or_flag_ssa_list": + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = [] + for j in xrange(count.value / 2): + if (operand_list[j * 2] & (1 << 32)) != 0: + reg_or_flag = ILFlag(func.arch, operand_list[j * 2] & 0xffffffff) + else: + reg_or_flag = ILRegister(func.arch, operand_list[j * 2] & 0xffffffff) + reg_version = operand_list[(j * 2) + 1] + value.append(SSARegisterOrFlag(reg_or_flag, reg_version)) + core.BNLowLevelILFreeOperandList(operand_list) elif operand_type == "reg_stack_adjust": count = ctypes.c_ulonglong() operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = {} - for i in xrange(count.value / 2): - reg_stack = operand_list[i * 2] - adjust = operand_list[(i * 2) + 1] + for j in xrange(count.value / 2): + reg_stack = operand_list[j * 2] + adjust = operand_list[(j * 2) + 1] if adjust & 0x80000000: adjust |= ~0x80000000 value[func.arch.get_reg_stack_name(reg_stack)] = adjust @@ -1714,6 +1770,25 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_SYSCALL) + def intrinsic(self, outputs, intrinsic, params): + """ + ``intrinsic`` return an intrinsic expression. + + :return: an intrinsic expression. + :rtype: LowLevelILExpr + """ + output_list = [] + for output in outputs: + if isinstance(output, ILFlag): + output_list.append((1 << 32) | output.index) + else: + output_list.append(output.index) + param_list = [] + for param in params: + param_list.append(param.index) + return self.expr(LowLevelILOperation.LLIL_INTRINSIC, len(outputs), self.add_operand_list(output_list), + self.arch.get_intrinsic_index(intrinsic), len(params), self.add_operand_list(param_list)) + def breakpoint(self): """ ``breakpoint`` returns a processor breakpoint expression. diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 8594ea36..3c4ba3fd 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -150,6 +150,8 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_BP: [], MediumLevelILOperation.MLIL_TRAP: [("vector", "int")], + MediumLevelILOperation.MLIL_INTRINSIC: [("output", "var_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_INTRINSIC_SSA: [("output", "var_ssa_list"), ("intrinsic", "intrinsic"), ("params", "expr_list")], MediumLevelILOperation.MLIL_UNDEF: [], MediumLevelILOperation.MLIL_UNIMPL: [], MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], @@ -223,6 +225,8 @@ class MediumLevelILInstruction(object): value = instr.operands[i] elif operand_type == "expr": value = MediumLevelILInstruction(func, instr.operands[i]) + elif operand_type == "intrinsic": + value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i]) elif operand_type == "var": value = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) elif operand_type == "var_ssa": -- cgit v1.3.1 From ef91ab7f3b648051b72fd06dd05eff3c57fa7f65 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Fri, 23 Feb 2018 14:54:44 -0500 Subject: Add APIs for subclassing or hooking an existing architecture in C/C++ --- architecture.cpp | 378 ++++++++++++++++- binaryninjaapi.h | 89 ++++ binaryninjacore.h | 4 + examples/x86_extension/src/x86_extension.cpp | 585 +-------------------------- 4 files changed, 490 insertions(+), 566 deletions(-) (limited to 'architecture.cpp') diff --git a/architecture.cpp b/architecture.cpp index 90f8e622..a1aaca2d 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -640,6 +640,13 @@ bool Architecture::SkipAndReturnValueCallback(void* ctxt, uint8_t* data, uint64_ } +void Architecture::Register(BNCustomArchitecture* callbacks) +{ + AddRefForRegistration(); + BNRegisterArchitecture(m_nameForRegister.c_str(), callbacks); +} + + void Architecture::Register(Architecture* arch) { BNCustomArchitecture callbacks; @@ -701,8 +708,7 @@ void Architecture::Register(Architecture* arch) callbacks.alwaysBranch = AlwaysBranchCallback; callbacks.invertBranch = InvertBranchCallback; callbacks.skipAndReturnValue = SkipAndReturnValueCallback; - arch->AddRefForRegistration(); - BNRegisterArchitecture(arch->m_nameForRegister.c_str(), &callbacks); + arch->Register(&callbacks); } @@ -1228,6 +1234,12 @@ Ref Architecture::GetStandalonePlatform() } +void Architecture::AddArchitectureRedirection(Architecture* from, Architecture* to) +{ + BNAddArchitectureRedirection(m_object, from->GetObject(), to->GetObject()); +} + + CoreArchitecture::CoreArchitecture(BNArchitecture* arch): Architecture(arch) { } @@ -1712,3 +1724,365 @@ bool CoreArchitecture::SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t l { return BNArchitectureSkipAndReturnValue(m_object, data, addr, len, value); } + + +ArchitectureExtension::ArchitectureExtension(const string& name, Architecture* base): Architecture(name), m_base(base) +{ +} + + +void ArchitectureExtension::Register(BNCustomArchitecture* callbacks) +{ + AddRefForRegistration(); + BNRegisterArchitectureExtension(m_nameForRegister.c_str(), m_base->GetObject(), callbacks); +} + + +BNEndianness ArchitectureExtension::GetEndianness() const +{ + return m_base->GetEndianness(); +} + + +size_t ArchitectureExtension::GetAddressSize() const +{ + return m_base->GetAddressSize(); +} + + +size_t ArchitectureExtension::GetDefaultIntegerSize() const +{ + return m_base->GetDefaultIntegerSize(); +} + + +size_t ArchitectureExtension::GetInstructionAlignment() const +{ + return m_base->GetInstructionAlignment(); +} + + +size_t ArchitectureExtension::GetMaxInstructionLength() const +{ + return m_base->GetMaxInstructionLength(); +} + + +size_t ArchitectureExtension::GetOpcodeDisplayLength() const +{ + return m_base->GetOpcodeDisplayLength(); +} + + +Ref ArchitectureExtension::GetAssociatedArchitectureByAddress(uint64_t& addr) +{ + Ref result = m_base->GetAssociatedArchitectureByAddress(addr); + if (result == m_base) + return this; + return result; +} + + +bool ArchitectureExtension::GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) +{ + return m_base->GetInstructionInfo(data, addr, maxLen, result); +} + + +bool ArchitectureExtension::GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, + vector& result) +{ + return m_base->GetInstructionText(data, addr, len, result); +} + + +bool ArchitectureExtension::GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) +{ + return m_base->GetInstructionLowLevelIL(data, addr, len, il); +} + + +string ArchitectureExtension::GetRegisterName(uint32_t reg) +{ + return m_base->GetRegisterName(reg); +} + + +string ArchitectureExtension::GetFlagName(uint32_t flag) +{ + return m_base->GetFlagName(flag); +} + + +string ArchitectureExtension::GetFlagWriteTypeName(uint32_t flags) +{ + return m_base->GetFlagWriteTypeName(flags); +} + + +string ArchitectureExtension::GetSemanticFlagClassName(uint32_t semClass) +{ + return m_base->GetSemanticFlagClassName(semClass); +} + + +string ArchitectureExtension::GetSemanticFlagGroupName(uint32_t semGroup) +{ + return m_base->GetSemanticFlagGroupName(semGroup); +} + + +vector ArchitectureExtension::GetFullWidthRegisters() +{ + return m_base->GetFullWidthRegisters(); +} + + +vector ArchitectureExtension::GetAllRegisters() +{ + return m_base->GetAllRegisters(); +} + + +vector ArchitectureExtension::GetAllFlags() +{ + return m_base->GetAllFlags(); +} + + +vector ArchitectureExtension::GetAllFlagWriteTypes() +{ + return m_base->GetAllFlagWriteTypes(); +} + + +vector ArchitectureExtension::GetAllSemanticFlagClasses() +{ + return m_base->GetAllSemanticFlagClasses(); +} + + +vector ArchitectureExtension::GetAllSemanticFlagGroups() +{ + return m_base->GetAllSemanticFlagGroups(); +} + + +BNFlagRole ArchitectureExtension::GetFlagRole(uint32_t flag, uint32_t semClass) +{ + return m_base->GetFlagRole(flag, semClass); +} + + +vector ArchitectureExtension::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, + uint32_t semClass) +{ + return m_base->GetFlagsRequiredForFlagCondition(cond, semClass); +} + + +vector ArchitectureExtension::GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) +{ + return m_base->GetFlagsRequiredForSemanticFlagGroup(semGroup); +} + + +map ArchitectureExtension::GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) +{ + return m_base->GetFlagConditionsForSemanticFlagGroup(semGroup); +} + + +vector ArchitectureExtension::GetFlagsWrittenByFlagWriteType(uint32_t writeType) +{ + return m_base->GetFlagsWrittenByFlagWriteType(writeType); +} + + +uint32_t ArchitectureExtension::GetSemanticClassForFlagWriteType(uint32_t writeType) +{ + return m_base->GetSemanticClassForFlagWriteType(writeType); +} + + +ExprId ArchitectureExtension::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, + uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) +{ + return m_base->GetFlagWriteLowLevelIL(op, size, flagWriteType, flag, operands, operandCount, il); +} + + +ExprId ArchitectureExtension::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) +{ + return m_base->GetFlagConditionLowLevelIL(cond, semClass, il); +} + + +ExprId ArchitectureExtension::GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) +{ + return m_base->GetSemanticFlagGroupLowLevelIL(semGroup, il); +} + + +BNRegisterInfo ArchitectureExtension::GetRegisterInfo(uint32_t reg) +{ + return m_base->GetRegisterInfo(reg); +} + + +uint32_t ArchitectureExtension::GetStackPointerRegister() +{ + return m_base->GetStackPointerRegister(); +} + + +uint32_t ArchitectureExtension::GetLinkRegister() +{ + return m_base->GetLinkRegister(); +} + + +vector ArchitectureExtension::GetGlobalRegisters() +{ + return m_base->GetGlobalRegisters(); +} + + +string ArchitectureExtension::GetRegisterStackName(uint32_t regStack) +{ + return m_base->GetRegisterStackName(regStack); +} + + +vector ArchitectureExtension::GetAllRegisterStacks() +{ + return m_base->GetAllRegisterStacks(); +} + + +BNRegisterStackInfo ArchitectureExtension::GetRegisterStackInfo(uint32_t regStack) +{ + return m_base->GetRegisterStackInfo(regStack); +} + + +string ArchitectureExtension::GetIntrinsicName(uint32_t intrinsic) +{ + return m_base->GetIntrinsicName(intrinsic); +} + + +vector ArchitectureExtension::GetAllIntrinsics() +{ + return m_base->GetAllIntrinsics(); +} + + +vector ArchitectureExtension::GetIntrinsicInputs(uint32_t intrinsic) +{ + return m_base->GetIntrinsicInputs(intrinsic); +} + + +vector>> ArchitectureExtension::GetIntrinsicOutputs(uint32_t intrinsic) +{ + return m_base->GetIntrinsicOutputs(intrinsic); +} + + +bool ArchitectureExtension::Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) +{ + return m_base->Assemble(code, addr, result, errors); +} + + +bool ArchitectureExtension::IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsNeverBranchPatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsAlwaysBranchPatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsInvertBranchPatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsSkipAndReturnValuePatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->IsSkipAndReturnValuePatchAvailable(data, addr, len); +} + + +bool ArchitectureExtension::ConvertToNop(uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->ConvertToNop(data, addr, len); +} + + +bool ArchitectureExtension::AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->AlwaysBranch(data, addr, len); +} + + +bool ArchitectureExtension::InvertBranch(uint8_t* data, uint64_t addr, size_t len) +{ + return m_base->InvertBranch(data, addr, len); +} + + +bool ArchitectureExtension::SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) +{ + return m_base->SkipAndReturnValue(data, addr, len, value); +} + + +ArchitectureHook::ArchitectureHook(Architecture* base): CoreArchitecture(nullptr), m_base(base) +{ + // Architecture hooks allow existing architecture implementations to be extended without creating + // a new Architecture object for the changes. By deriving from the ArchitectureHook class and passing + // the original Architecture object of the architecture to be extended, any reimplemented functions + // will be called first before the original architecture's implementation. You MUST call the base + // class method to call the original implementation's version of the function, as calling the + // same function on the original Architecture object will call your implementation again. + + // Example of a hook to modify the lifting process: + + // class ArchitectureHookExample: public ArchitectureHook + // { + // public: + // ArchitectureHookExample(Architecture* existingArch) : ArchitectureHook(existingArch) + // { + // } + // + // virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, + // LowLevelILFunction& il) override + // { + // // Perform extra lifting here + // // ... + // // For unhandled cases, call the original architecture's implementation + // return ArchitectureHook::GetInstructionLowLevelIL(data, addr, len, il); + // } + // }; +} + + +void ArchitectureHook::Register(BNCustomArchitecture* callbacks) +{ + AddRefForRegistration(); + m_object = BNRegisterArchitectureHook(m_base->GetObject(), callbacks); +} diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 91162af7..89eba009 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1668,6 +1668,8 @@ namespace BinaryNinja static bool InvertBranchCallback(void* ctxt, uint8_t* data, uint64_t addr, size_t len); static bool SkipAndReturnValueCallback(void* ctxt, uint8_t* data, uint64_t addr, size_t len, uint64_t value); + virtual void Register(BNCustomArchitecture* callbacks); + public: Architecture(const std::string& name); @@ -1832,6 +1834,8 @@ namespace BinaryNinja Ref GetStdcallCallingConvention(); Ref GetFastcallCallingConvention(); Ref GetStandalonePlatform(); + + void AddArchitectureRedirection(Architecture* from, Architecture* to); }; class CoreArchitecture: public Architecture @@ -1900,6 +1904,91 @@ namespace BinaryNinja virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override; }; + class ArchitectureExtension: public Architecture + { + protected: + Ref m_base; + + virtual void Register(BNCustomArchitecture* callbacks) override; + + public: + ArchitectureExtension(const std::string& name, Architecture* base); + + Ref GetBaseArchitecture() const { return m_base; } + + virtual BNEndianness GetEndianness() const override; + virtual size_t GetAddressSize() const override; + virtual size_t GetDefaultIntegerSize() const override; + virtual size_t GetInstructionAlignment() const override; + virtual size_t GetMaxInstructionLength() const override; + virtual size_t GetOpcodeDisplayLength() const override; + virtual Ref GetAssociatedArchitectureByAddress(uint64_t& addr) override; + virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override; + virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, + std::vector& result) override; + virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override; + virtual std::string GetRegisterName(uint32_t reg) override; + virtual std::string GetFlagName(uint32_t flag) override; + virtual std::string GetFlagWriteTypeName(uint32_t flags) override; + virtual std::string GetSemanticFlagClassName(uint32_t semClass) override; + virtual std::string GetSemanticFlagGroupName(uint32_t semGroup) override; + virtual std::vector GetFullWidthRegisters() override; + virtual std::vector GetAllRegisters() override; + virtual std::vector GetAllFlags() override; + virtual std::vector GetAllFlagWriteTypes() override; + virtual std::vector GetAllSemanticFlagClasses() override; + virtual std::vector GetAllSemanticFlagGroups() override; + virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass = 0) override; + virtual std::vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond, + uint32_t semClass = 0) override; + virtual std::vector GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) override; + virtual std::map GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) override; + virtual std::vector GetFlagsWrittenByFlagWriteType(uint32_t writeType) override; + virtual uint32_t GetSemanticClassForFlagWriteType(uint32_t writeType) override; + virtual ExprId GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, + uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override; + virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, + uint32_t semClass, LowLevelILFunction& il) override; + virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) override; + virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override; + virtual uint32_t GetStackPointerRegister() override; + virtual uint32_t GetLinkRegister() override; + virtual std::vector GetGlobalRegisters() override; + + virtual std::string GetRegisterStackName(uint32_t regStack) override; + virtual std::vector GetAllRegisterStacks() override; + virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack) override; + + virtual std::string GetIntrinsicName(uint32_t intrinsic) override; + virtual std::vector GetAllIntrinsics() override; + virtual std::vector GetIntrinsicInputs(uint32_t intrinsic) override; + virtual std::vector>> GetIntrinsicOutputs(uint32_t intrinsic) override; + + virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors) override; + + virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; + virtual bool IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; + virtual bool IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; + virtual bool IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; + virtual bool IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override; + + virtual bool ConvertToNop(uint8_t* data, uint64_t addr, size_t len) override; + virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override; + virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override; + virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override; + }; + + class ArchitectureHook: public CoreArchitecture + { + protected: + Ref m_base; + + virtual void Register(BNCustomArchitecture* callbacks) override; + + public: + ArchitectureHook(Architecture* base); + }; + class Structure; class NamedTypeReference; class Enumeration; diff --git a/binaryninjacore.h b/binaryninjacore.h index fa7a818a..5329a1d9 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2085,6 +2085,10 @@ extern "C" BINARYNINJACOREAPI BNArchitecture** BNGetArchitectureList(size_t* count); BINARYNINJACOREAPI void BNFreeArchitectureList(BNArchitecture** archs); BINARYNINJACOREAPI BNArchitecture* BNRegisterArchitecture(const char* name, BNCustomArchitecture* arch); + BINARYNINJACOREAPI BNArchitecture* BNRegisterArchitectureExtension(const char* name, + BNArchitecture* base, BNCustomArchitecture* arch); + BINARYNINJACOREAPI void BNAddArchitectureRedirection(BNArchitecture* arch, BNArchitecture* from, BNArchitecture* to); + BINARYNINJACOREAPI BNArchitecture* BNRegisterArchitectureHook(BNArchitecture* base, BNCustomArchitecture* arch); BINARYNINJACOREAPI char* BNGetArchitectureName(BNArchitecture* arch); BINARYNINJACOREAPI BNEndianness BNGetArchitectureEndianness(BNArchitecture* arch); diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp index a2ba4c9c..87f2c2cb 100644 --- a/examples/x86_extension/src/x86_extension.cpp +++ b/examples/x86_extension/src/x86_extension.cpp @@ -10,572 +10,37 @@ using namespace std; using namespace asmx86; -#define IL_FLAG_C 0 -#define IL_FLAG_P 2 -#define IL_FLAG_A 4 -#define IL_FLAG_Z 6 -#define IL_FLAG_S 7 -#define IL_FLAG_D 10 -#define IL_FLAG_O 11 - -#define IL_FLAGWRITE_ALL 1 -#define IL_FLAGWRITE_NOCARRY 2 -#define IL_FLAGWRITE_CO 3 - -#define REG_FSBASE 0x100 -#define REG_GSBASE 0x101 - -#define TRAP_DIV 0 -#define TRAP_ICEBP 1 -#define TRAP_NMI 2 -#define TRAP_BP 3 -#define TRAP_OVERFLOW 4 -#define TRAP_BOUND 5 -#define TRAP_ILL 6 -#define TRAP_NOT_AVAIL 7 -#define TRAP_DOUBLE 8 -#define TRAP_TSS 10 -#define TRAP_NO_SEG 11 -#define TRAP_STACK 12 -#define TRAP_GPF 13 -#define TRAP_PAGE 14 -#define TRAP_FPU 16 -#define TRAP_ALIGN 17 -#define TRAP_MCE 18 -#define TRAP_SIMD 19 - -static uint8_t GetShiftCountForScale(uint8_t scale) -{ - switch (scale) - { - case 2: - return 1; - case 4: - return 2; - case 8: - return 3; - default: - return 0; - } -} - - -static uint32_t GetStackPointer(size_t addrSize) -{ - switch (addrSize) - { - case 2: - return REG_SP; - case 4: - return REG_ESP; - default: - return REG_RSP; - } -} - - -static uint32_t GetFramePointer(size_t addrSize) -{ - switch (addrSize) - { - case 2: - return REG_BP; - case 4: - return REG_EBP; - default: - return REG_RBP; - } -} - - -static uint32_t GetCountRegister(size_t addrSize) -{ - switch (addrSize) - { - case 2: - return REG_CX; - case 4: - return REG_ECX; - default: - return REG_RCX; - } -} - - -static size_t GetILOperandMemoryAddress(LowLevelILFunction& il, InstructionOperand& operand, size_t i, size_t addrSize) -{ - size_t offset; - if (operand.operand != MEM) - offset = il.Operand(i, il.Undefined()); - else if ((operand.components[0] == NONE) && (operand.components[1] == NONE) && operand.relative) - offset = il.Operand(i, il.ConstPointer(addrSize, operand.immediate)); - else if ((operand.components[0] == NONE) && (operand.components[1] == NONE)) - offset = il.Operand(i, il.Const(addrSize, operand.immediate)); - else if ((operand.components[1] == NONE) && (operand.immediate == 0)) - offset = il.Operand(i, il.Register(addrSize, operand.components[0])); - else if (operand.components[1] == NONE) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.Const(addrSize, operand.immediate))); - } - else if ((operand.components[0] == NONE) && (operand.scale == 1) && (operand.immediate == 0)) - offset = il.Operand(i, il.Register(addrSize, operand.components[1])); - else if ((operand.components[0] == NONE) && (operand.scale == 1)) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(addrSize, operand.immediate))); - } - else if ((operand.components[0] == NONE) && (operand.immediate == 0)) - { - offset = il.Operand(i, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale)))); - } - else if (operand.components[0] == NONE) - { - offset = il.Operand(i, il.Add(addrSize, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale))), il.Const(addrSize, operand.immediate))); - } - else if ((operand.scale == 1) && (operand.immediate == 0)) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.Register(addrSize, operand.components[1]))); - } - else if (operand.scale == 1) - { - offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.Register(addrSize, operand.components[1])), il.Const(addrSize, operand.immediate))); - } - else if (operand.immediate == 0) - { - offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale))))); - } - else - { - offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]), - il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]), - il.Const(1, GetShiftCountForScale(operand.scale)))), il.Const(addrSize, operand.immediate))); - } - - if (operand.segment == SEG_FS) - return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_FSBASE), offset)); - if (operand.segment == SEG_GS) - return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_GSBASE), offset)); - return offset; -} - - -static size_t ReadILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, bool isAddress = false) -{ - InstructionOperand& operand = instr.operands[i]; - switch (operand.operand) - { - case NONE: - return il.Undefined(); - case IMM: - if (isAddress) - return il.Operand(i, il.ConstPointer(operand.size, operand.immediate)); - else - return il.Operand(i, il.Const(operand.size, operand.immediate)); - case MEM: - return il.Operand(i, il.Load(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize))); - default: - return il.Operand(i, il.Register(operand.size, operand.operand)); - } -} - - -static size_t WriteILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, size_t value) -{ - InstructionOperand& operand = instr.operands[i]; - switch (operand.operand) - { - case NONE: - case IMM: - return il.Undefined(); - case MEM: - return il.Operand(i, il.Store(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize), value)); - default: - return il.Operand(i, il.SetRegister(operand.size, operand.operand, value)); - } -} - - -static size_t DirectJump(Architecture* arch, LowLevelILFunction& il, uint64_t target, size_t addrSize) -{ - BNLowLevelILLabel* label = il.GetLabelForAddress(arch, target); - if (label) - return il.Goto(*label); - else - return il.Jump(il.ConstPointer(addrSize, target)); -} - - -static void ConditionalJump(Architecture* arch, LowLevelILFunction& il, size_t cond, size_t addrSize, uint64_t t, uint64_t f) -{ - BNLowLevelILLabel* trueLabel = il.GetLabelForAddress(arch, t); - BNLowLevelILLabel* falseLabel = il.GetLabelForAddress(arch, f); - - if (trueLabel && falseLabel) - { - il.AddInstruction(il.If(cond, *trueLabel, *falseLabel)); - return; - } - - LowLevelILLabel trueCode, falseCode; - - if (trueLabel) - { - il.AddInstruction(il.If(cond, *trueLabel, falseCode)); - il.MarkLabel(falseCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f))); - return; - } - - if (falseLabel) - { - il.AddInstruction(il.If(cond, trueCode, *falseLabel)); - il.MarkLabel(trueCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t))); - return; - } - - il.AddInstruction(il.If(cond, trueCode, falseCode)); - il.MarkLabel(trueCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t))); - il.MarkLabel(falseCode); - il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f))); -} - - -static void DirFlagIf(size_t addrSize, - LowLevelILFunction& il, - std::function addPreTestIl, - std::function addDirFlagSetIl, - std::function addDirFlagClearIl) -{ - LowLevelILLabel dirFlagSet, dirFlagClear, dirFlagDone; - - addPreTestIl(addrSize, il); - - il.AddInstruction(il.If(il.Flag(IL_FLAG_D), dirFlagSet, dirFlagClear)); - il.MarkLabel(dirFlagSet); - - addDirFlagSetIl(addrSize, il); - - il.AddInstruction(il.Goto(dirFlagDone)); - il.MarkLabel(dirFlagClear); - - addDirFlagClearIl(addrSize, il); - - il.AddInstruction(il.Goto(dirFlagDone)); - il.MarkLabel(dirFlagDone); -} - - -static void Repeat(size_t addrSize, - Instruction& instr, - LowLevelILFunction& il, - std::function addil) -{ - LowLevelILLabel trueLabel, falseLabel, doneLabel; - if (instr.flags & X86_FLAG_ANY_REP) - { - il.AddInstruction(il.Goto(trueLabel)); - il.MarkLabel(trueLabel); - il.AddInstruction(il.If(il.CompareEqual(addrSize, il.Register(addrSize, GetCountRegister(addrSize)), - il.Const(addrSize, 0)), doneLabel, falseLabel)); - il.MarkLabel(falseLabel); - } - - addil(addrSize, il); - - if (instr.flags & X86_FLAG_ANY_REP) - { - il.AddInstruction(il.SetRegister(addrSize, GetCountRegister(addrSize), - il.Sub(addrSize, il.Register(addrSize, GetCountRegister(addrSize)), - il.Const(addrSize, 1)))); - if (instr.flags & X86_FLAG_REPE) - il.AddInstruction(il.If(il.FlagCondition(LLFC_E), trueLabel, doneLabel)); - else if (instr.flags & X86_FLAG_REPNE) - il.AddInstruction(il.If(il.FlagCondition(LLFC_NE), trueLabel, doneLabel)); - else - il.AddInstruction(il.Goto(trueLabel)); - il.MarkLabel(doneLabel); - } -} - - // This is a wrapper for the x86 architecture. Its useful for extending and improving // the existing core x86 architecture. -class x86ArchitectureExtension: public Architecture +class x86ArchitectureExtension: public ArchitectureHook { - Architecture* m_arch; public: - x86ArchitectureExtension() : Architecture("x86_extension") - { - m_arch = new CoreArchitecture(BNGetArchitectureByName("x86")); - } - - virtual size_t GetAddressSize() const override - { - return 4; - } - - virtual BNEndianness GetEndianness() const override + x86ArchitectureExtension(Architecture* x86) : ArchitectureHook(x86) { - return LittleEndian; - } - - virtual size_t GetInstructionAlignment() const override - { - return 1; - } - - virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override - { - return m_arch->GetInstructionInfo(data, addr, maxLen, result); - } - - virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, vector& result) override - { - return m_arch->GetInstructionText(data, addr, len, result); } virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override { Instruction instr; - if (!asmx86::Disassemble32(data, addr, len, &instr)) + if (asmx86::Disassemble32(data, addr, len, &instr)) { - il.AddInstruction(il.Undefined()); - return false; + switch (instr.operation) + { + case CPUID: + // The default implementation of CPUID doesn't set registers to constant values + // Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1 + il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read + il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3))); + il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800))); + il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf))); + il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff))); + len = instr.length; + return true; + default: + break; + } } - - size_t addrSize = 4; - switch (instr.operation) - { - case CPUID: - // The default implementation of CPUID doesn't set registers to constant values - // Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1 - il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read - il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3))); - il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800))); - il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf))); - il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff))); - len = instr.length; - return true; - - case JMP: - if (instr.operands[0].operand == IMM) - il.AddInstruction(DirectJump(this, il, instr.operands[0].immediate, addrSize)); - else - il.AddInstruction(il.Jump(ReadILOperand(il, instr, 0, addrSize, true))); - return false; - - case JO: - ConditionalJump(this, il, il.FlagCondition(LLFC_O), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JNO: - ConditionalJump(this, il, il.FlagCondition(LLFC_NO), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JB: - ConditionalJump(this, il, il.FlagCondition(LLFC_ULT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JAE: - ConditionalJump(this, il, il.FlagCondition(LLFC_UGE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JE: - ConditionalJump(this, il, il.FlagCondition(LLFC_E), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JNE: - ConditionalJump(this, il, il.FlagCondition(LLFC_NE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JBE: - ConditionalJump(this, il, il.FlagCondition(LLFC_ULE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JA: - ConditionalJump(this, il, il.FlagCondition(LLFC_UGT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JS: - ConditionalJump(this, il, il.FlagCondition(LLFC_NEG), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JNS: - ConditionalJump(this, il, il.FlagCondition(LLFC_POS), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JPE: - ConditionalJump(this, il, il.Not(0, il.Flag(IL_FLAG_P)), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JPO: - ConditionalJump(this, il, il.Flag(IL_FLAG_P), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JL: - ConditionalJump(this, il, il.FlagCondition(LLFC_SLT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JGE: - ConditionalJump(this, il, il.FlagCondition(LLFC_SGE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JLE: - ConditionalJump(this, il, il.FlagCondition(LLFC_SLE), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JG: - ConditionalJump(this, il, il.FlagCondition(LLFC_SGT), addrSize, instr.operands[0].immediate, addr + instr.length); - return false; - - case JCXZ: - ConditionalJump(this, il, il.CompareEqual(2, il.Register(2, REG_CX), il.Const(2, 0)), addrSize, - instr.operands[0].immediate, addr + instr.length); - return false; - - case JECXZ: - ConditionalJump(this, il, il.CompareEqual(4, il.Register(4, REG_ECX), il.Const(4, 0)), addrSize, - instr.operands[0].immediate, addr + instr.length); - return false; - - case JRCXZ: - ConditionalJump(this, il, il.CompareEqual(8, il.Register(8, REG_RCX), il.Const(8, 0)), addrSize, - instr.operands[0].immediate, addr + instr.length); - return false; - - default: - return m_arch->GetInstructionLowLevelIL(data, addr, len, il); - } - } - - virtual size_t GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, - uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override - { - return m_arch->GetFlagWriteLowLevelIL(op,size, flagWriteType, flag, operands, operandCount, il); - } - - virtual string GetRegisterName(uint32_t reg) override - { - return m_arch->GetRegisterName(reg); - } - - virtual string GetFlagName(uint32_t flag) override - { - return m_arch->GetFlagName(flag); - } - - virtual vector GetAllFlags() override - { - return m_arch->GetAllFlags(); - } - - virtual string GetFlagWriteTypeName(uint32_t flags) override - { - return m_arch->GetFlagWriteTypeName(flags); - } - - virtual vector GetAllFlagWriteTypes() override - { - return m_arch->GetAllFlagWriteTypes(); - } - - virtual BNFlagRole GetFlagRole(uint32_t flag) override - { - return m_arch->GetFlagRole(flag); - } - - virtual vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override - { - return m_arch->GetFlagsRequiredForFlagCondition(cond); - } - - virtual vector GetFlagsWrittenByFlagWriteType(uint32_t writeType) override - { - return m_arch->GetFlagsWrittenByFlagWriteType(writeType); - } - - virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsNeverBranchPatchAvailable(data, addr, len); - } - - virtual bool IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsAlwaysBranchPatchAvailable(data, addr, len); - } - - virtual bool IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsInvertBranchPatchAvailable(data, addr, len); - } - - virtual bool IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsSkipAndReturnZeroPatchAvailable(data, addr, len); - } - - virtual bool IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->IsSkipAndReturnValuePatchAvailable(data, addr, len); - } - - virtual bool ConvertToNop(uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->ConvertToNop(data, addr, len); - } - - virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->AlwaysBranch(data, addr, len); - } - - virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override - { - return m_arch->InvertBranch(data, addr, len); - } - - virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override - { - return m_arch->SkipAndReturnValue(data, addr, len, value); - } - - virtual vector GetFullWidthRegisters() override - { - return m_arch->GetFullWidthRegisters(); - } - - virtual vector GetGlobalRegisters() override - { - return m_arch->GetGlobalRegisters(); - } - - virtual vector GetAllRegisters() override - { - return m_arch->GetAllRegisters(); - } - - virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override - { - return m_arch->GetRegisterInfo(reg); - } - - virtual uint32_t GetStackPointerRegister() override - { - return m_arch->GetStackPointerRegister(); - } - - virtual bool Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) override - { - return m_arch->Assemble(code, addr, result, errors); + return ArchitectureHook::GetInstructionLowLevelIL(data, addr, len, il); } }; @@ -585,21 +50,13 @@ extern "C" BINARYNINJAPLUGIN void CorePluginDependencies() { // Make sure we load after the original x86 plugin loads - SetCurrentPluginLoadOrder(LatePluginLoadOrder); + AddRequiredPluginDependency("arch_x86"); } BINARYNINJAPLUGIN bool CorePluginInit() { - Architecture* x86ext = new x86ArchitectureExtension(); + Architecture* x86ext = new x86ArchitectureExtension(Architecture::GetByName("x86")); Architecture::Register(x86ext); - - // Register the architectures with the binary format parsers so that they know when to use - // these architectures for disassembling an executable file - BinaryViewType::RegisterArchitecture("ELF", 3, LittleEndian, x86ext); - BinaryViewType::RegisterArchitecture("PE", 0x14c, LittleEndian, x86ext); - BinaryViewType::RegisterArchitecture("Mach-O", 0x00000007, LittleEndian, x86ext); - x86ext->SetBinaryViewTypeConstant("ELF", "R_COPY", 5); - x86ext->SetBinaryViewTypeConstant("ELF", "R_JUMP_SLOT", 7); return true; } } -- cgit v1.3.1