Rizin
unix-like reverse engineering framework and cli tools
arm_it.h File Reference
#include <rz_util.h>
#include <ht_uu.h>
#include <capstone/capstone.h>

Go to the source code of this file.

Classes

struct  rz_arm_it_context_t
 

Typedefs

typedef struct rz_arm_it_context_t RzArmITContext
 

Functions

RZ_API void rz_arm_it_context_init (RzArmITContext *ctx)
 
RZ_API void rz_arm_it_context_fini (RzArmITContext *ctx)
 
RZ_API void rz_arm_it_update_block (RzArmITContext *ctx, cs_insn *insn)
 
RZ_API void rz_arm_it_update_nonblock (RzArmITContext *ctx, cs_insn *insn)
 
RZ_API bool rz_arm_it_apply_cond (RzArmITContext *ctx, cs_insn *insn)
 

Detailed Description

Tracking of Arm thumb IT blocks during disassembly. Note: all of this is really just a best guess approach.

Definition in file arm_it.h.

Typedef Documentation

◆ RzArmITContext

Function Documentation

◆ rz_arm_it_apply_cond()

RZ_API bool rz_arm_it_apply_cond ( RzArmITContext ctx,
cs_insn *  insn 
)

Apply any previously tracked IT condition to insn

Returns
true if a condition was found and applied

Definition at line 87 of file arm_it.c.

87  {
88  const ut64 addr = insn->address;
89  bool found;
90  ArmCSITCond cond = { .packed = ht_uu_find(ctx->ht_itcond, addr, &found) };
91  if (!found) {
92  return false;
93  }
94  insn->detail->arm.cc = cond.cond;
95  insn->detail->arm.update_flags = 0;
96 
97  // Readjust if we detected that the previous assumption of all-2-byte instructions in
98  // analysis_itblock() was incorrect. See also the comment there.
99  if (insn->size != 4) {
100  return true;
101  }
102  cond.packed = ht_uu_find(ctx->ht_itcond, addr + 2, &found);
103  if (!found) {
104  // Everything fine, nothing to adjust
105  return true;
106  }
107  // Now readjust everything starting with the addr+2 cond
108  ut64 blockaddr = addr + 2 - cond.off;
109  ArmCSITBlock itblock = { .packed = ht_uu_find(ctx->ht_itblock, blockaddr, &found) };
110  if (!found) {
111  return true;
112  }
113  for (size_t i = 0; i < 4; i++) {
114  size_t idx = 3 - i; // Reverse loop so we don't overwrite anything by accident
115  if (!itblock.off[idx]) {
116  continue;
117  }
118  if (itblock.off[idx] < cond.off) {
119  break;
120  }
121  ArmCSITCond adjcond = { .packed = ht_uu_find(ctx->ht_itcond, blockaddr + itblock.off[idx], &found) };
122  if (!found) {
123  continue;
124  }
125  ht_uu_delete(ctx->ht_itcond, blockaddr + itblock.off[idx]);
126  adjcond.off = itblock.off[idx] += 2;
127  ht_uu_update(ctx->ht_itcond, blockaddr + itblock.off[idx], adjcond.packed);
128  }
129  ht_uu_update(ctx->ht_itblock, blockaddr, itblock.packed);
130  return true;
131 }
lzma_index ** i
Definition: index.h:629
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
int idx
Definition: setup.py:197
#define cond(bop, top, mask, flags)
ut64 packed
for putting into HtUU
Definition: arm_it.c:9
ut8 off[4]
offsets of the up to 4 conditioned instructions from the addr of the it, 0-terminated if less than 4.
Definition: arm_it.c:8
ut64 packed
for putting into HtUU
Definition: arm_it.c:17
ut8 off
offset of this instruction from the it, for back-referencing to the ArmCSITBlock
Definition: arm_it.c:15
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58

References addr, cond, found, i, setup::idx, arm_cs_itblock_t::off, arm_cs_itcond_t::off, arm_cs_itblock_t::packed, arm_cs_itcond_t::packed, and ut64().

Referenced by anop32(), and disassemble().

◆ rz_arm_it_context_fini()

RZ_API void rz_arm_it_context_fini ( RzArmITContext ctx)

Definition at line 25 of file arm_it.c.

25  {
26  ht_uu_free(ctx->ht_itblock);
27  ht_uu_free(ctx->ht_itcond);
28 }

Referenced by arm_fini(), and fini().

◆ rz_arm_it_context_init()

RZ_API void rz_arm_it_context_init ( RzArmITContext ctx)

Definition at line 20 of file arm_it.c.

20  {
21  ctx->ht_itcond = ht_uu_new0();
22  ctx->ht_itblock = ht_uu_new0();
23 }

Referenced by arm_init(), and init().

◆ rz_arm_it_update_block()

RZ_API void rz_arm_it_update_block ( RzArmITContext ctx,
cs_insn *  insn 
)

Signal a newly detected IT block insn must be ARM_INS_IT

Definition at line 34 of file arm_it.c.

34  {
35  rz_return_if_fail(ctx && insn && insn->id == ARM_INS_IT);
36  bool found;
37  ht_uu_find(ctx->ht_itblock, insn->address, &found);
38  if (found) {
39  return;
40  }
41  ArmCSITBlock block = { 0 };
42  size_t size = rz_str_nlen(insn->mnemonic, 5);
43  for (size_t i = 1; i < size; i++) {
44  // At this point, we can't know whether each instruction in the block
45  // is 2 or 4 bytes. We build up everything for 2 bytes for now and if
46  // we later encounter a 4 byte instruction with a condition inside of it,
47  // we readjust everything accordingly.
48  ArmCSITCond cond = { 0 };
49  cond.off = block.off[i - 1] = 2 * i;
50  switch (insn->mnemonic[i]) {
51  case 0x74: //'t'
52  cond.cond = insn->detail->arm.cc;
53  break;
54  case 0x65: //'e'
55  cond.cond = (insn->detail->arm.cc % 2) ? insn->detail->arm.cc + 1 : insn->detail->arm.cc - 1;
56  break;
57  default:
58  break;
59  }
60  RZ_STATIC_ASSERT(sizeof(cond) == sizeof(cond.packed));
61  ht_uu_update(ctx->ht_itcond, insn->address + cond.off, cond.packed);
62  }
63  RZ_STATIC_ASSERT(sizeof(block) == sizeof(block.packed));
64  ht_uu_update(ctx->ht_itblock, insn->address, block.packed);
65 }
@ ARM_INS_IT
Definition: arm.h:857
voidpf void uLong size
Definition: ioapi.h:138
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define RZ_STATIC_ASSERT(x)
Definition: rz_assert.h:10
RZ_API size_t rz_str_nlen(const char *s, size_t n)
Definition: str.c:1949

References ARM_INS_IT, cond, found, i, arm_cs_itblock_t::off, arm_cs_itblock_t::packed, rz_return_if_fail, RZ_STATIC_ASSERT, and rz_str_nlen().

Referenced by anop32(), and disassemble().

◆ rz_arm_it_update_nonblock()

RZ_API void rz_arm_it_update_nonblock ( RzArmITContext ctx,
cs_insn *  insn 
)

Signal that a non-IT instruction was disassembled and clear any block at the same address.

Definition at line 70 of file arm_it.c.

70  {
71  rz_return_if_fail(ctx && insn);
72  bool found;
73  ArmCSITBlock block = { .packed = ht_uu_find(ctx->ht_itblock, insn->address, &found) };
74  if (!found) {
75  return;
76  }
77  for (size_t i = 0; i < 4 && block.off[i]; i++) {
78  ht_uu_delete(ctx->ht_itcond, insn->address + block.off[i]);
79  }
80  ht_uu_delete(ctx->ht_itblock, insn->address);
81 }

References found, i, arm_cs_itblock_t::off, arm_cs_itblock_t::packed, and rz_return_if_fail.

Referenced by anop32(), and disassemble().