summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2019-12-19 16:04:11 -0500
committerRusty Wagner <rusty@vector35.com>2019-12-19 16:04:11 -0500
commit741fb0538e0ac6ab14928f78697196803dbd2ed5 (patch)
treedd0b8da88791b03553d659e6672c8d5ba0fdecfa
parent98771ab9f325e310ae07120cf559f601837380f9 (diff)
LLIL_JUMP_TO/MLIL_JUMP_TO now contain mappings from address to destination instruction
-rw-r--r--binaryninjaapi.h8
-rw-r--r--binaryninjacore.h7
-rw-r--r--lowlevelil.cpp14
-rw-r--r--lowlevelilinstruction.cpp103
-rw-r--r--lowlevelilinstruction.h38
-rw-r--r--mediumlevelil.cpp15
-rw-r--r--mediumlevelilinstruction.cpp103
-rw-r--r--mediumlevelilinstruction.h38
-rw-r--r--python/lowlevelil.py12
-rw-r--r--python/mediumlevelil.py12
m---------suite/binaries0
-rw-r--r--suite/testcommon.py37
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))