diff options
| author | Rusty Wagner <rusty@vector35.com> | 2019-12-19 16:04:11 -0500 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2019-12-19 16:04:11 -0500 |
| commit | 741fb0538e0ac6ab14928f78697196803dbd2ed5 (patch) | |
| tree | dd0b8da88791b03553d659e6672c8d5ba0fdecfa | |
| parent | 98771ab9f325e310ae07120cf559f601837380f9 (diff) | |
LLIL_JUMP_TO/MLIL_JUMP_TO now contain mappings from address to destination instruction
| -rw-r--r-- | binaryninjaapi.h | 8 | ||||
| -rw-r--r-- | binaryninjacore.h | 7 | ||||
| -rw-r--r-- | lowlevelil.cpp | 14 | ||||
| -rw-r--r-- | lowlevelilinstruction.cpp | 103 | ||||
| -rw-r--r-- | lowlevelilinstruction.h | 38 | ||||
| -rw-r--r-- | mediumlevelil.cpp | 15 | ||||
| -rw-r--r-- | mediumlevelilinstruction.cpp | 103 | ||||
| -rw-r--r-- | mediumlevelilinstruction.h | 38 | ||||
| -rw-r--r-- | python/lowlevelil.py | 12 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 12 | ||||
| m--------- | suite/binaries | 0 | ||||
| -rw-r--r-- | suite/testcommon.py | 37 |
12 files changed, 331 insertions, 56 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index c4911697..b4b9a602 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -3468,7 +3468,7 @@ __attribute__ ((format (printf, 1, 2))) ExprId LowPart(size_t size, ExprId a, uint32_t flags = 0, const ILSourceLocation& loc = ILSourceLocation()); ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); - ExprId JumpTo(ExprId dest, const std::vector<BNLowLevelILLabel*>& targets, + ExprId JumpTo(ExprId dest, const std::map<uint64_t, BNLowLevelILLabel*>& targets, const ILSourceLocation& loc = ILSourceLocation()); ExprId Call(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId CallStackAdjust(ExprId dest, int64_t adjust, const std::map<uint32_t, int32_t>& regStackAdjust, @@ -3562,7 +3562,7 @@ __attribute__ ((format (printf, 1, 2))) void MarkLabel(BNLowLevelILLabel& label); std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand); - ExprId AddLabelList(const std::vector<BNLowLevelILLabel*>& labels); + ExprId AddLabelMap(const std::map<uint64_t, BNLowLevelILLabel*>& labels); ExprId AddOperandList(const std::vector<ExprId> operands); ExprId AddIndexList(const std::vector<size_t> operands); ExprId AddRegisterOrFlagList(const std::vector<RegisterOrFlag>& regs); @@ -3792,7 +3792,7 @@ __attribute__ ((format (printf, 1, 2))) ExprId ZeroExtend(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId LowPart(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation()); ExprId Jump(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); - ExprId JumpTo(ExprId dest, const std::vector<BNMediumLevelILLabel*>& targets, + ExprId JumpTo(ExprId dest, const std::map<uint64_t, BNMediumLevelILLabel*>& targets, const ILSourceLocation& loc = ILSourceLocation()); ExprId ReturnHint(ExprId dest, const ILSourceLocation& loc = ILSourceLocation()); ExprId Call(const std::vector<Variable>& output, ExprId dest, const std::vector<ExprId>& params, @@ -3897,7 +3897,7 @@ __attribute__ ((format (printf, 1, 2))) ExprId AddInstruction(ExprId expr); std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand); - ExprId AddLabelList(const std::vector<BNMediumLevelILLabel*>& labels); + ExprId AddLabelMap(const std::map<uint64_t, BNMediumLevelILLabel*>& labels); ExprId AddOperandList(const std::vector<ExprId> operands); ExprId AddIndexList(const std::vector<size_t>& operands); ExprId AddVariableList(const std::vector<Variable>& vars); diff --git a/binaryninjacore.h b/binaryninjacore.h index 55f9bfa0..2988637f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -3219,7 +3219,8 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI void BNPrepareToCopyLowLevelILBasicBlock(BNLowLevelILFunction* func, BNBasicBlock* block); BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLabelForLowLevelILSourceInstruction(BNLowLevelILFunction* func, size_t instr); - BINARYNINJACOREAPI size_t BNLowLevelILAddLabelList(BNLowLevelILFunction* func, BNLowLevelILLabel** labels, size_t count); + BINARYNINJACOREAPI size_t BNLowLevelILAddLabelMap(BNLowLevelILFunction* func, uint64_t* values, + BNLowLevelILLabel** labels, size_t count); BINARYNINJACOREAPI size_t BNLowLevelILAddOperandList(BNLowLevelILFunction* func, uint64_t* operands, size_t count); BINARYNINJACOREAPI uint64_t* BNLowLevelILGetOperandList(BNLowLevelILFunction* func, size_t expr, size_t operand, size_t* count); @@ -3344,8 +3345,8 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI BNMediumLevelILLabel* BNGetLabelForMediumLevelILSourceInstruction(BNMediumLevelILFunction* func, size_t instr); - BINARYNINJACOREAPI size_t BNMediumLevelILAddLabelList(BNMediumLevelILFunction* func, - BNMediumLevelILLabel** labels, size_t count); + BINARYNINJACOREAPI size_t BNMediumLevelILAddLabelMap(BNMediumLevelILFunction* func, + uint64_t* values, BNMediumLevelILLabel** labels, size_t count); BINARYNINJACOREAPI size_t BNMediumLevelILAddOperandList(BNMediumLevelILFunction* func, uint64_t* operands, size_t count); BINARYNINJACOREAPI uint64_t* BNMediumLevelILGetOperandList(BNMediumLevelILFunction* func, size_t expr, diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 61450c8f..afaacf08 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -184,12 +184,18 @@ vector<uint64_t> LowLevelILFunction::GetOperandList(ExprId expr, size_t listOper } -ExprId LowLevelILFunction::AddLabelList(const vector<BNLowLevelILLabel*>& labels) +ExprId LowLevelILFunction::AddLabelMap(const map<uint64_t, BNLowLevelILLabel*>& labels) { + uint64_t* valueList = new uint64_t[labels.size()]; BNLowLevelILLabel** labelList = new BNLowLevelILLabel*[labels.size()]; - for (size_t i = 0; i < labels.size(); i++) - labelList[i] = labels[i]; - ExprId result = (ExprId)BNLowLevelILAddLabelList(m_object, labelList, labels.size()); + size_t i = 0; + for (auto& j : labels) + { + valueList[i] = j.first; + labelList[i] = j.second; + i++; + } + ExprId result = (ExprId)BNLowLevelILAddLabelMap(m_object, valueList, labelList, labels.size()); delete[] labelList; return result; } diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp index a79910f0..afb82c94 100644 --- a/lowlevelilinstruction.cpp +++ b/lowlevelilinstruction.cpp @@ -84,7 +84,7 @@ unordered_map<LowLevelILOperandUsage, LowLevelILOperandType> {OutputRegisterOrFlagListLowLevelOperandUsage, RegisterOrFlagListLowLevelOperand}, {OutputSSARegisterOrFlagListLowLevelOperandUsage, SSARegisterOrFlagListLowLevelOperand}, {SourceMemoryVersionsLowLevelOperandUsage, IndexListLowLevelOperand}, - {TargetListLowLevelOperandUsage, IndexListLowLevelOperand}, + {TargetsLowLevelOperandUsage, IndexMapLowLevelOperand}, {RegisterStackAdjustmentsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperand} }; @@ -144,7 +144,7 @@ unordered_map<BNLowLevelILOperation, vector<LowLevelILOperandUsage>> {LLIL_FLAG_SSA, {SourceSSAFlagLowLevelOperandUsage}}, {LLIL_FLAG_BIT_SSA, {SourceSSAFlagLowLevelOperandUsage, BitIndexLowLevelOperandUsage}}, {LLIL_JUMP, {DestExprLowLevelOperandUsage}}, - {LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetListLowLevelOperandUsage}}, + {LLIL_JUMP_TO, {DestExprLowLevelOperandUsage, TargetsLowLevelOperandUsage}}, {LLIL_CALL, {DestExprLowLevelOperandUsage}}, {LLIL_CALL_STACK_ADJUST, {DestExprLowLevelOperandUsage, StackAdjustmentLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperandUsage}}, @@ -288,6 +288,7 @@ static unordered_map<BNLowLevelILOperation, unordered_map<LowLevelILOperandUsage case SSARegisterStackLowLevelOperand: case SSAFlagLowLevelOperand: case IndexListLowLevelOperand: + case IndexMapLowLevelOperand: case SSARegisterListLowLevelOperand: case SSARegisterStackListLowLevelOperand: case SSAFlagListLowLevelOperand: @@ -740,6 +741,64 @@ LowLevelILIndexList::operator vector<size_t>() const } +const pair<uint64_t, size_t> LowLevelILIndexMap::ListIterator::operator*() +{ + LowLevelILIntegerList::const_iterator cur = pos; + uint64_t value = *cur; + ++cur; + size_t target = (size_t)*cur; + return pair<uint64_t, size_t>(value, target); +} + + +LowLevelILIndexMap::LowLevelILIndexMap(LowLevelILFunction* func, + const BNLowLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +LowLevelILIndexMap::const_iterator LowLevelILIndexMap::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +LowLevelILIndexMap::const_iterator LowLevelILIndexMap::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t LowLevelILIndexMap::size() const +{ + return m_list.size() / 2; +} + + +size_t LowLevelILIndexMap::operator[](uint64_t value) const +{ + for (auto iter = begin(); iter != end(); ++iter) + { + if ((*iter).first == value) + return (*iter).second; + } + throw LowLevelILInstructionAccessException(); +} + + +LowLevelILIndexMap::operator map<uint64_t, size_t>() const +{ + map<uint64_t, size_t> result; + for (auto& i : *this) + result[i.first] = i.second; + return result; +} + + const LowLevelILInstruction LowLevelILInstructionList::ListIterator::operator*() { return LowLevelILInstruction(pos.GetFunction(), pos.GetFunction()->GetRawExpr((size_t)*pos), @@ -1218,6 +1277,14 @@ LowLevelILIndexList LowLevelILOperand::GetIndexList() const } +LowLevelILIndexMap LowLevelILOperand::GetIndexMap() const +{ + if (m_type != IndexMapLowLevelOperand) + throw LowLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsIndexMap(m_operandIndex); +} + + LowLevelILInstructionList LowLevelILOperand::GetExprList() const { if (m_type != ExprListLowLevelOperand) @@ -1457,6 +1524,12 @@ LowLevelILIndexList LowLevelILInstructionBase::GetRawOperandAsIndexList(size_t o } +LowLevelILIndexMap LowLevelILInstructionBase::GetRawOperandAsIndexMap(size_t operand) const +{ + return LowLevelILIndexMap(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + LowLevelILInstructionList LowLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const { return LowLevelILInstructionList(function, function->GetRawExpr(operands[operand + 1]), operands[operand], @@ -1938,7 +2011,6 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest) const ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, const std::function<ExprId(const LowLevelILInstruction& subExpr)>& subExprHandler) const { - vector<BNLowLevelILLabel*> labelList; vector<ExprId> params; BNLowLevelILLabel* labelA; BNLowLevelILLabel* labelB; @@ -2060,14 +2132,17 @@ ExprId LowLevelILInstruction::CopyTo(LowLevelILFunction* dest, case LLIL_RET: return dest->Return(subExprHandler(GetDestExpr<LLIL_RET>()), *this); case LLIL_JUMP_TO: - for (auto target : GetTargetList<LLIL_JUMP_TO>()) { - labelA = dest->GetLabelForSourceInstruction(target); - if (!labelA) - return dest->Jump(subExprHandler(GetDestExpr<LLIL_JUMP_TO>()), *this); - labelList.push_back(labelA); + map<uint64_t, BNLowLevelILLabel*> labelList; + for (auto target : GetTargets<LLIL_JUMP_TO>()) + { + labelA = dest->GetLabelForSourceInstruction(target.second); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr<LLIL_JUMP_TO>()), *this); + labelList[target.first] = labelA; + } + return dest->JumpTo(subExprHandler(GetDestExpr<LLIL_JUMP_TO>()), labelList, *this); } - return dest->JumpTo(subExprHandler(GetDestExpr<LLIL_JUMP_TO>()), labelList, *this); case LLIL_GOTO: labelA = dest->GetLabelForSourceInstruction(GetTarget<LLIL_GOTO>()); if (!labelA) @@ -2663,11 +2738,11 @@ LowLevelILIndexList LowLevelILInstruction::GetSourceMemoryVersions() const } -LowLevelILIndexList LowLevelILInstruction::GetTargetList() const +LowLevelILIndexMap LowLevelILInstruction::GetTargets() const { size_t operandIndex; - if (GetOperandIndexForUsage(TargetListLowLevelOperandUsage, operandIndex)) - return GetRawOperandAsIndexList(operandIndex); + if (GetOperandIndexForUsage(TargetsLowLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexMap(operandIndex); throw LowLevelILInstructionAccessException(); } @@ -3173,10 +3248,10 @@ ExprId LowLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc) } -ExprId LowLevelILFunction::JumpTo(ExprId dest, const vector<BNLowLevelILLabel*>& targets, +ExprId LowLevelILFunction::JumpTo(ExprId dest, const map<uint64_t, BNLowLevelILLabel*>& targets, const ILSourceLocation& loc) { - return AddExprWithLocation(LLIL_JUMP_TO, loc, 0, 0, dest, targets.size(), AddLabelList(targets)); + return AddExprWithLocation(LLIL_JUMP_TO, loc, 0, 0, dest, targets.size() * 2, AddLabelMap(targets)); } diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h index af005943..206a51d9 100644 --- a/lowlevelilinstruction.h +++ b/lowlevelilinstruction.h @@ -158,6 +158,7 @@ namespace BinaryNinja SSARegisterStackLowLevelOperand, SSAFlagLowLevelOperand, IndexListLowLevelOperand, + IndexMapLowLevelOperand, ExprListLowLevelOperand, RegisterOrFlagListLowLevelOperand, SSARegisterListLowLevelOperand, @@ -218,7 +219,7 @@ namespace BinaryNinja OutputRegisterOrFlagListLowLevelOperandUsage, OutputSSARegisterOrFlagListLowLevelOperandUsage, SourceMemoryVersionsLowLevelOperandUsage, - TargetListLowLevelOperandUsage, + TargetsLowLevelOperandUsage, RegisterStackAdjustmentsLowLevelOperandUsage, OffsetLowLevelOperandUsage }; @@ -385,6 +386,33 @@ namespace BinaryNinja operator std::vector<size_t>() const; }; + class LowLevelILIndexMap + { + 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 std::pair<uint64_t, size_t> operator*(); + }; + + LowLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + LowLevelILIndexMap(LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](uint64_t value) const; + + operator std::map<uint64_t, size_t>() const; + }; + class LowLevelILInstructionList { struct ListIterator @@ -577,6 +605,7 @@ namespace BinaryNinja SSARegisterStack GetRawOperandAsPartialSSARegisterStackSource(size_t operand) const; SSAFlag GetRawOperandAsSSAFlag(size_t operand) const; LowLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + LowLevelILIndexMap GetRawOperandAsIndexMap(size_t operand) const; LowLevelILInstructionList GetRawOperandAsExprList(size_t operand) const; LowLevelILRegisterOrFlagList GetRawOperandAsRegisterOrFlagList(size_t operand) const; LowLevelILSSARegisterList GetRawOperandAsSSARegisterList(size_t operand) const; @@ -731,7 +760,7 @@ namespace BinaryNinja template <BNLowLevelILOperation N> LowLevelILRegisterOrFlagList GetOutputRegisterOrFlagList() const { return As<N>().GetOutputRegisterOrFlagList(); } template <BNLowLevelILOperation N> LowLevelILSSARegisterOrFlagList GetOutputSSARegisterOrFlagList() const { return As<N>().GetOutputSSARegisterOrFlagList(); } template <BNLowLevelILOperation N> LowLevelILIndexList GetSourceMemoryVersions() const { return As<N>().GetSourceMemoryVersions(); } - template <BNLowLevelILOperation N> LowLevelILIndexList GetTargetList() const { return As<N>().GetTargetList(); } + template <BNLowLevelILOperation N> LowLevelILIndexMap GetTargets() const { return As<N>().GetTargets(); } template <BNLowLevelILOperation N> std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const { return As<N>().GetRegisterStackAdjustments(); } template <BNLowLevelILOperation N> void SetDestSSAVersion(size_t version) { As<N>().SetDestSSAVersion(version); } @@ -796,7 +825,7 @@ namespace BinaryNinja LowLevelILRegisterOrFlagList GetOutputRegisterOrFlagList() const; LowLevelILSSARegisterOrFlagList GetOutputSSARegisterOrFlagList() const; LowLevelILIndexList GetSourceMemoryVersions() const; - LowLevelILIndexList GetTargetList() const; + LowLevelILIndexMap GetTargets() const; std::map<uint32_t, int32_t> GetRegisterStackAdjustments() const; }; @@ -828,6 +857,7 @@ namespace BinaryNinja SSARegisterStack GetSSARegisterStack() const; SSAFlag GetSSAFlag() const; LowLevelILIndexList GetIndexList() const; + LowLevelILIndexMap GetIndexMap() const; LowLevelILInstructionList GetExprList() const; LowLevelILSSARegisterList GetSSARegisterList() const; LowLevelILSSARegisterStackList GetSSARegisterStackList() const; @@ -1104,7 +1134,7 @@ namespace BinaryNinja template <> struct LowLevelILInstructionAccessor<LLIL_JUMP_TO>: public LowLevelILInstructionBase { LowLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } - LowLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + LowLevelILIndexMap GetTargets() const { return GetRawOperandAsIndexMap(1); } }; template <> struct LowLevelILInstructionAccessor<LLIL_CALL>: public LowLevelILInstructionBase { diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp index 3c2f623a..6ce556f4 100644 --- a/mediumlevelil.cpp +++ b/mediumlevelil.cpp @@ -165,12 +165,19 @@ vector<uint64_t> MediumLevelILFunction::GetOperandList(ExprId expr, size_t listO } -ExprId MediumLevelILFunction::AddLabelList(const vector<BNMediumLevelILLabel*>& labels) +ExprId MediumLevelILFunction::AddLabelMap(const map<uint64_t, BNMediumLevelILLabel*>& labels) { + uint64_t* valueList = new uint64_t[labels.size()]; BNMediumLevelILLabel** labelList = new BNMediumLevelILLabel*[labels.size()]; - for (size_t i = 0; i < labels.size(); i++) - labelList[i] = labels[i]; - ExprId result = (ExprId)BNMediumLevelILAddLabelList(m_object, labelList, labels.size()); + size_t i = 0; + for (auto& j : labels) + { + valueList[i] = j.first; + labelList[i] = j.second; + i++; + } + ExprId result = (ExprId)BNMediumLevelILAddLabelMap(m_object, valueList, labelList, labels.size()); + delete[] valueList; delete[] labelList; return result; } diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp index 237580ef..9d03f89b 100644 --- a/mediumlevelilinstruction.cpp +++ b/mediumlevelilinstruction.cpp @@ -60,7 +60,7 @@ unordered_map<MediumLevelILOperandUsage, MediumLevelILOperandType> {FalseTargetMediumLevelOperandUsage, IndexMediumLevelOperand}, {DestMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, {SourceMemoryVersionMediumLevelOperandUsage, IndexMediumLevelOperand}, - {TargetListMediumLevelOperandUsage, IndexListMediumLevelOperand}, + {TargetsMediumLevelOperandUsage, IndexMapMediumLevelOperand}, {SourceMemoryVersionsMediumLevelOperandUsage, IndexListMediumLevelOperand}, {OutputVariablesMediumLevelOperandUsage, VariableListMediumLevelOperand}, {OutputVariablesSubExprMediumLevelOperandUsage, VariableListMediumLevelOperand}, @@ -121,7 +121,7 @@ unordered_map<BNMediumLevelILOperation, vector<MediumLevelILOperandUsage>> {MLIL_ADDRESS_OF, {SourceVariableMediumLevelOperandUsage}}, {MLIL_ADDRESS_OF_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}}, {MLIL_JUMP, {DestExprMediumLevelOperandUsage}}, - {MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetListMediumLevelOperandUsage}}, + {MLIL_JUMP_TO, {DestExprMediumLevelOperandUsage, TargetsMediumLevelOperandUsage}}, {MLIL_RET_HINT, {DestExprMediumLevelOperandUsage}}, {MLIL_CALL, {OutputVariablesMediumLevelOperandUsage, DestExprMediumLevelOperandUsage, ParameterExprsMediumLevelOperandUsage}}, @@ -280,6 +280,7 @@ static unordered_map<BNMediumLevelILOperation, unordered_map<MediumLevelILOperan { case SSAVariableMediumLevelOperand: case IndexListMediumLevelOperand: + case IndexMapMediumLevelOperand: case VariableListMediumLevelOperand: case SSAVariableListMediumLevelOperand: case ExprListMediumLevelOperand: @@ -507,6 +508,64 @@ MediumLevelILIndexList::operator vector<size_t>() const } +const pair<uint64_t, size_t> MediumLevelILIndexMap::ListIterator::operator*() +{ + MediumLevelILIntegerList::const_iterator cur = pos; + uint64_t value = *cur; + ++cur; + size_t target = (size_t)*cur; + return pair<uint64_t, size_t>(value, target); +} + + +MediumLevelILIndexMap::MediumLevelILIndexMap(MediumLevelILFunction* func, + const BNMediumLevelILInstruction& instr, size_t count): m_list(func, instr, count & (~1)) +{ +} + + +MediumLevelILIndexMap::const_iterator MediumLevelILIndexMap::begin() const +{ + const_iterator result; + result.pos = m_list.begin(); + return result; +} + + +MediumLevelILIndexMap::const_iterator MediumLevelILIndexMap::end() const +{ + const_iterator result; + result.pos = m_list.end(); + return result; +} + + +size_t MediumLevelILIndexMap::size() const +{ + return m_list.size() / 2; +} + + +size_t MediumLevelILIndexMap::operator[](uint64_t value) const +{ + for (auto iter = begin(); iter != end(); ++iter) + { + if ((*iter).first == value) + return (*iter).second; + } + throw MediumLevelILInstructionAccessException(); +} + + +MediumLevelILIndexMap::operator map<uint64_t, size_t>() const +{ + map<uint64_t, size_t> result; + for (auto& i : *this) + result[i.first] = i.second; + return result; +} + + const Variable MediumLevelILVariableList::ListIterator::operator*() { return Variable::FromIdentifier(*pos); @@ -749,6 +808,14 @@ MediumLevelILIndexList MediumLevelILOperand::GetIndexList() const } +MediumLevelILIndexMap MediumLevelILOperand::GetIndexMap() const +{ + if (m_type != IndexMapMediumLevelOperand) + throw MediumLevelILInstructionAccessException(); + return m_instr.GetRawOperandAsIndexMap(m_operandIndex); +} + + MediumLevelILVariableList MediumLevelILOperand::GetVariableList() const { if (m_type != VariableListMediumLevelOperand) @@ -941,6 +1008,12 @@ MediumLevelILIndexList MediumLevelILInstructionBase::GetRawOperandAsIndexList(si } +MediumLevelILIndexMap MediumLevelILInstructionBase::GetRawOperandAsIndexMap(size_t operand) const +{ + return MediumLevelILIndexMap(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); +} + + MediumLevelILVariableList MediumLevelILInstructionBase::GetRawOperandAsVariableList(size_t operand) const { return MediumLevelILVariableList(function, function->GetRawExpr(operands[operand + 1]), operands[operand]); @@ -1425,7 +1498,6 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, const std::function<ExprId(const MediumLevelILInstruction& subExpr)>& subExprHandler) const { vector<ExprId> params; - vector<BNMediumLevelILLabel*> labelList; BNMediumLevelILLabel* labelA; BNMediumLevelILLabel* labelB; switch (operation) @@ -1664,14 +1736,17 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest, subExprHandler(AsTwoOperandWithCarry().GetRightExpr()), subExprHandler(AsTwoOperandWithCarry().GetCarryExpr())); case MLIL_JUMP_TO: - for (auto target : GetTargetList<MLIL_JUMP_TO>()) { - labelA = dest->GetLabelForSourceInstruction(target); - if (!labelA) - return dest->Jump(subExprHandler(GetDestExpr<MLIL_JUMP_TO>()), *this); - labelList.push_back(labelA); + map<uint64_t, BNMediumLevelILLabel*> labelList; + for (auto target : GetTargets<MLIL_JUMP_TO>()) + { + labelA = dest->GetLabelForSourceInstruction(target.second); + if (!labelA) + return dest->Jump(subExprHandler(GetDestExpr<MLIL_JUMP_TO>()), *this); + labelList[target.first] = labelA; + } + return dest->JumpTo(subExprHandler(GetDestExpr<MLIL_JUMP_TO>()), labelList, *this); } - return dest->JumpTo(subExprHandler(GetDestExpr<MLIL_JUMP_TO>()), labelList, *this); case MLIL_GOTO: labelA = dest->GetLabelForSourceInstruction(GetTarget<MLIL_GOTO>()); if (!labelA) @@ -1961,11 +2036,11 @@ size_t MediumLevelILInstruction::GetSourceMemoryVersion() const } -MediumLevelILIndexList MediumLevelILInstruction::GetTargetList() const +MediumLevelILIndexMap MediumLevelILInstruction::GetTargets() const { size_t operandIndex; - if (GetOperandIndexForUsage(TargetListMediumLevelOperandUsage, operandIndex)) - return GetRawOperandAsIndexList(operandIndex); + if (GetOperandIndexForUsage(TargetsMediumLevelOperandUsage, operandIndex)) + return GetRawOperandAsIndexMap(operandIndex); throw MediumLevelILInstructionAccessException(); } @@ -2502,10 +2577,10 @@ ExprId MediumLevelILFunction::Jump(ExprId dest, const ILSourceLocation& loc) } -ExprId MediumLevelILFunction::JumpTo(ExprId dest, const vector<BNMediumLevelILLabel*>& targets, +ExprId MediumLevelILFunction::JumpTo(ExprId dest, const map<uint64_t, BNMediumLevelILLabel*>& targets, const ILSourceLocation& loc) { - return AddExprWithLocation(MLIL_JUMP_TO, loc, 0, dest, targets.size(), AddLabelList(targets)); + return AddExprWithLocation(MLIL_JUMP_TO, loc, 0, dest, targets.size() * 2, AddLabelMap(targets)); } diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h index 7d11d35d..a5fff2f9 100644 --- a/mediumlevelilinstruction.h +++ b/mediumlevelilinstruction.h @@ -75,6 +75,7 @@ namespace BinaryNinja VariableMediumLevelOperand, SSAVariableMediumLevelOperand, IndexListMediumLevelOperand, + IndexMapMediumLevelOperand, VariableListMediumLevelOperand, SSAVariableListMediumLevelOperand, ExprListMediumLevelOperand @@ -107,7 +108,7 @@ namespace BinaryNinja FalseTargetMediumLevelOperandUsage, DestMemoryVersionMediumLevelOperandUsage, SourceMemoryVersionMediumLevelOperandUsage, - TargetListMediumLevelOperandUsage, + TargetsMediumLevelOperandUsage, SourceMemoryVersionsMediumLevelOperandUsage, OutputVariablesMediumLevelOperandUsage, OutputVariablesSubExprMediumLevelOperandUsage, @@ -249,6 +250,33 @@ namespace BinaryNinja operator std::vector<size_t>() const; }; + class MediumLevelILIndexMap + { + struct ListIterator + { + MediumLevelILIntegerList::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 std::pair<uint64_t, size_t> operator*(); + }; + + MediumLevelILIntegerList m_list; + + public: + typedef ListIterator const_iterator; + + MediumLevelILIndexMap(MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t count); + + const_iterator begin() const; + const_iterator end() const; + size_t size() const; + size_t operator[](uint64_t) const; + + operator std::map<uint64_t, size_t>() const; + }; + class MediumLevelILVariableList { struct ListIterator @@ -357,6 +385,7 @@ namespace BinaryNinja SSAVariable GetRawOperandAsSSAVariable(size_t operand) const; SSAVariable GetRawOperandAsPartialSSAVariableSource(size_t operand) const; MediumLevelILIndexList GetRawOperandAsIndexList(size_t operand) const; + MediumLevelILIndexMap GetRawOperandAsIndexMap(size_t operand) const; MediumLevelILVariableList GetRawOperandAsVariableList(size_t operand) const; MediumLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const; MediumLevelILInstructionList GetRawOperandAsExprList(size_t operand) const; @@ -494,7 +523,7 @@ namespace BinaryNinja template <BNMediumLevelILOperation N> size_t GetFalseTarget() const { return As<N>().GetFalseTarget(); } template <BNMediumLevelILOperation N> size_t GetDestMemoryVersion() const { return As<N>().GetDestMemoryVersion(); } template <BNMediumLevelILOperation N> size_t GetSourceMemoryVersion() const { return As<N>().GetSourceMemoryVersion(); } - template <BNMediumLevelILOperation N> MediumLevelILIndexList GetTargetList() const { return As<N>().GetTargetList(); } + template <BNMediumLevelILOperation N> MediumLevelILIndexMap GetTargets() const { return As<N>().GetTargets(); } template <BNMediumLevelILOperation N> MediumLevelILIndexList GetSourceMemoryVersions() const { return As<N>().GetSourceMemoryVersions(); } template <BNMediumLevelILOperation N> MediumLevelILVariableList GetOutputVariables() const { return As<N>().GetOutputVariables(); } template <BNMediumLevelILOperation N> MediumLevelILSSAVariableList GetOutputSSAVariables() const { return As<N>().GetOutputSSAVariables(); } @@ -545,7 +574,7 @@ namespace BinaryNinja size_t GetFalseTarget() const; size_t GetDestMemoryVersion() const; size_t GetSourceMemoryVersion() const; - MediumLevelILIndexList GetTargetList() const; + MediumLevelILIndexMap GetTargets() const; MediumLevelILIndexList GetSourceMemoryVersions() const; MediumLevelILVariableList GetOutputVariables() const; MediumLevelILSSAVariableList GetOutputSSAVariables() const; @@ -577,6 +606,7 @@ namespace BinaryNinja Variable GetVariable() const; SSAVariable GetSSAVariable() const; MediumLevelILIndexList GetIndexList() const; + MediumLevelILIndexMap GetIndexMap() const; MediumLevelILVariableList GetVariableList() const; MediumLevelILSSAVariableList GetSSAVariableList() const; MediumLevelILInstructionList GetExprList() const; @@ -812,7 +842,7 @@ namespace BinaryNinja template <> struct MediumLevelILInstructionAccessor<MLIL_JUMP_TO>: public MediumLevelILInstructionBase { MediumLevelILInstruction GetDestExpr() const { return GetRawOperandAsExpr(0); } - MediumLevelILIndexList GetTargetList() const { return GetRawOperandAsIndexList(1); } + MediumLevelILIndexMap GetTargets() const { return GetRawOperandAsIndexMap(1); } }; template <> struct MediumLevelILInstructionAccessor<MLIL_RET_HINT>: public MediumLevelILInstructionBase { diff --git a/python/lowlevelil.py b/python/lowlevelil.py index b77ce10a..5f71b80c 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -550,7 +550,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_ZX: [("src", "expr")], LowLevelILOperation.LLIL_LOW_PART: [("src", "expr")], LowLevelILOperation.LLIL_JUMP: [("dest", "expr")], - LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], + LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "target_map")], LowLevelILOperation.LLIL_CALL: [("dest", "expr")], LowLevelILOperation.LLIL_CALL_STACK_ADJUST: [("dest", "expr"), ("stack_adjustment", "int"), ("reg_stack_adjustments", "reg_stack_adjust")], LowLevelILOperation.LLIL_TAILCALL: [("dest", "expr")], @@ -785,6 +785,16 @@ class LowLevelILInstruction(object): adjust |= ~0x80000000 value[func.arch.get_reg_stack_name(reg_stack)] = adjust core.BNLowLevelILFreeOperandList(operand_list) + elif operand_type == "target_map": + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = {} + for j in range(count.value // 2): + key = operand_list[j * 2] + target = operand_list[(j * 2) + 1] + value[key] = target + core.BNLowLevelILFreeOperandList(operand_list) self._operands.append(value) self.__dict__[name] = value i += 1 diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 806dc063..24b87ac7 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -170,7 +170,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_ZX: [("src", "expr")], MediumLevelILOperation.MLIL_LOW_PART: [("src", "expr")], MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], - MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], + MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "target_map")], MediumLevelILOperation.MLIL_RET_HINT: [("dest", "expr")], MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], MediumLevelILOperation.MLIL_CALL_UNTYPED: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], @@ -335,6 +335,16 @@ class MediumLevelILInstruction(object): for j in range(count.value): value.append(MediumLevelILInstruction(func, operand_list[j])) core.BNMediumLevelILFreeOperandList(operand_list) + elif operand_type == "target_map": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self._expr_index, i, count) + i += 1 + value = {} + for j in range(count.value // 2): + key = operand_list[j * 2] + target = operand_list[(j * 2) + 1] + value[key] = target + core.BNMediumLevelILFreeOperandList(operand_list) self._operands.append(value) self.__dict__[name] = value i += 1 diff --git a/suite/binaries b/suite/binaries -Subproject f17026111d327e1604d89daad9737831fe83292 +Subproject 24abb8fd8fe00a7188b5255bdcf9df36edc5feb diff --git a/suite/testcommon.py b/suite/testcommon.py index cb034f30..06ef1b5b 100644 --- a/suite/testcommon.py +++ b/suite/testcommon.py @@ -189,8 +189,29 @@ class BinaryViewTestBuilder(Builder): retinfo.append("Function: {:x} Instruction: {:x} Mapped MLIL: {}".format(func.start, ins.address, str(ins.mapped_medium_level_il))) retinfo.append("Function: {:x} Instruction: {:x} Value: {}".format(func.start, ins.address, str(ins.value))) retinfo.append("Function: {:x} Instruction: {:x} Possible Values: {}".format(func.start, ins.address, str(ins.possible_values))) - retinfo.append("Function: {:x} Instruction: {:x} Prefix operands: {}".format(func.start, ins.address, str(ins.prefix_operands))) - retinfo.append("Function: {:x} Instruction: {:x} Postfix operands: {}".format(func.start, ins.address, str(ins.postfix_operands))) + + prefixList = [] + for i in ins.prefix_operands: + if isinstance(i, dict): + contents = [] + for j in sorted(i.keys()): + contents.append((j, i[j])) + prefixList.append(str(contents)) + else: + prefixList.append(i) + retinfo.append("Function: {:x} Instruction: {:x} Prefix operands: {}".format(func.start, ins.address, str(prefixList))) + + postfixList = [] + for i in ins.postfix_operands: + if isinstance(i, dict): + contents = [] + for j in sorted(i.keys()): + contents.append((j, i[j])) + postfixList.append(str(contents)) + else: + postfixList.append(i) + retinfo.append("Function: {:x} Instruction: {:x} Postfix operands: {}".format(func.start, ins.address, str(postfixList))) + retinfo.append("Function: {:x} Instruction: {:x} SSA form: {}".format(func.start, ins.address, str(ins.ssa_form))) retinfo.append("Function: {:x} Instruction: {:x} Non-SSA form: {}".format(func.start, ins.address, str(ins.non_ssa_form))) return fixOutput(retinfo) @@ -236,15 +257,25 @@ class BinaryViewTestBuilder(Builder): prefixList.append(str(round(i, 21))) elif isinstance(i, float): prefixList.append(str(round(i, 11))) + elif isinstance(i, dict): + contents = [] + for j in sorted(i.keys()): + contents.append((j, i[j])) + prefixList.append(str(contents)) else: prefixList.append(str(i)) retinfo.append("Function: {:x} Instruction: {:x} Prefix operands: {}".format(func.start, ins.address, str(sorted(prefixList)))) postfixList = [] - for i in ins.prefix_operands: + for i in ins.postfix_operands: if isinstance(i, float) and 'e' in str(i): postfixList.append(str(round(i, 21))) elif isinstance(i, float): postfixList.append(str(round(i, 11))) + elif isinstance(i, dict): + contents = [] + for j in sorted(i.keys()): + contents.append((j, i[j])) + postfixList.append(str(contents)) else: postfixList.append(str(i)) |
