Skip to content

Commit 64f0668

Browse files
committed
[Thumb2] Fix IT instruction info
1 parent b1246d8 commit 64f0668

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

arch/armv7/thumb2_disasm/arch_thumb2.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,117 @@ class Thumb2Architecture: public ArmCommonArchitecture
187187

188188
result.length = decomp.instrSize / 8;
189189

190+
if ((decomp.mnem == armv7::ARMV7_IT) && (decomp.fields[FIELD_mask] != 0))
191+
{
192+
// IT block: consume all instructions and handle contained branches
193+
uint32_t offset = decomp.instrSize / 8;
194+
uint32_t mask = decomp.fields[FIELD_mask];
195+
uint32_t cond = decomp.fields[FIELD_firstcond];
196+
197+
size_t instrCount;
198+
if (mask & 1)
199+
instrCount = 4;
200+
else if (mask & 2)
201+
instrCount = 3;
202+
else if (mask & 4)
203+
instrCount = 2;
204+
else
205+
instrCount = 1;
206+
207+
// First branch/return in each condition path
208+
bool trueTerminated = false;
209+
bool falseTerminated = false;
210+
bool trueBranched = false;
211+
bool falseBranched = false;
212+
bool trueReturned = false;
213+
bool falseReturned = false;
214+
215+
uint64_t trueBranchTargetAddr = 0;
216+
uint64_t falseBranchTargetAddr = 0;
217+
218+
for (size_t i = 0; i < instrCount; i++)
219+
{
220+
bool isTrue = (i == 0) || (((mask >> (4 - i)) & 1) == (cond & 1));
221+
222+
InstructionInfo innerResult;
223+
if (!GetInstructionInfo(data + offset, addr + offset, maxLen - offset, innerResult))
224+
break;
225+
if ((offset + innerResult.length) > maxLen)
226+
break;
227+
228+
bool& terminated = isTrue ? trueTerminated : falseTerminated;
229+
bool& branched = isTrue ? trueBranched : falseBranched;
230+
bool& returned = isTrue ? trueReturned : falseReturned;
231+
uint64_t& branchTarget = isTrue ? trueBranchTargetAddr : falseBranchTargetAddr;
232+
233+
// Only process if the conditional branch we're following isn't terminated
234+
// Otherwise, just track if the arch is switching and the offset
235+
if (!terminated)
236+
{
237+
for (size_t j = 0; j < innerResult.branchCount; j++)
238+
{
239+
switch (innerResult.branchType[j])
240+
{
241+
case UnconditionalBranch:
242+
case TrueBranch:
243+
case FalseBranch:
244+
branched = true;
245+
terminated = true;
246+
branchTarget = innerResult.branchTarget[j];
247+
break;
248+
case FunctionReturn:
249+
returned = true;
250+
terminated = true;
251+
break;
252+
case CallDestination:
253+
result.AddBranch(CallDestination, innerResult.branchTarget[j],
254+
innerResult.branchArch[j] ? m_armArch : this);
255+
break;
256+
case UnresolvedBranch:
257+
case IndirectBranch:
258+
case ExceptionBranch:
259+
// We don't know the branch target so just set terminated
260+
terminated = true;
261+
break;
262+
default:
263+
break;
264+
}
265+
}
266+
}
267+
268+
if (innerResult.archTransitionByTargetAddr)
269+
result.archTransitionByTargetAddr = true;
270+
271+
offset += innerResult.length;
272+
}
273+
274+
result.length = offset;
275+
276+
uint64_t fallThroughAddr = (addr + offset) & 0xffffffffLL;
277+
// The targets for true/false branches either go somewhere or fall through to the next instr
278+
uint64_t trueTargetAddr = trueBranched ? trueBranchTargetAddr : fallThroughAddr;
279+
uint64_t falseTargetAddr = falseBranched ? falseBranchTargetAddr : fallThroughAddr;
280+
281+
if (trueReturned && falseReturned)
282+
{
283+
// If both paths return
284+
result.AddBranch(FunctionReturn);
285+
}
286+
else if (trueTargetAddr != falseTargetAddr)
287+
{
288+
// True and false go to different locations (either branch or fallthrough)
289+
result.AddBranch(TrueBranch, trueTargetAddr, this);
290+
result.AddBranch(FalseBranch, falseTargetAddr, this);
291+
}
292+
else if (trueTargetAddr != fallThroughAddr)
293+
{
294+
// True and false branch to the same location that isn't the fallthrough address
295+
result.AddBranch(UnconditionalBranch, trueTargetAddr, this);
296+
}
297+
298+
return true;
299+
}
300+
190301
switch (decomp.mnem)
191302
{
192303
case armv7::ARMV7_LDR:

0 commit comments

Comments
 (0)