Rizin
unix-like reverse engineering framework and cli tools
rz_il_reg.h File Reference
#include <rz_reg.h>

Go to the source code of this file.

Classes

struct  rz_il_reg_binding_item_t
 
struct  rz_il_reg_binding_t
 

Typedefs

typedef struct rz_il_reg_binding_item_t RzILRegBindingItem
 
typedef struct rz_il_reg_binding_t RzILRegBinding
 

Functions

RZ_API RzILRegBindingrz_il_reg_binding_derive (RZ_NONNULL RzReg *reg)
 Calculate a new binding of IL variables against the profile of the given RzReg. More...
 
RZ_API RzILRegBindingrz_il_reg_binding_exactly (RZ_NONNULL RzReg *reg, size_t regs_count, RZ_NONNULL RZ_BORROW const char **regs)
 
RZ_API void rz_il_reg_binding_free (RzILRegBinding *rb)
 
RZ_API void rz_il_vm_setup_reg_binding (RZ_NONNULL struct rz_il_vm_t *vm, RZ_NONNULL RZ_BORROW RzILRegBinding *rb)
 
RZ_API bool rz_il_vm_sync_to_reg (RZ_NONNULL struct rz_il_vm_t *vm, RZ_NONNULL RzILRegBinding *rb, RZ_NONNULL RzReg *reg)
 
RZ_API void rz_il_vm_sync_from_reg (RZ_NONNULL struct rz_il_vm_t *vm, RZ_NONNULL RzILRegBinding *rb, RZ_NONNULL RzReg *reg)
 

Typedef Documentation

◆ RzILRegBinding

An object that describes what registers are bound to variables in an RzILVM. Registers of size 1 are bound as boolean variables, others as bitvector ones.

◆ RzILRegBindingItem

Function Documentation

◆ rz_il_reg_binding_derive()

RZ_API RzILRegBinding* rz_il_reg_binding_derive ( RZ_NONNULL RzReg reg)

Calculate a new binding of IL variables against the profile of the given RzReg.

Because registers can overlap, not all registers may get a binding. Informally, only the "larger" ones, containing "smaller" ones are bound, except for 1-bit registers, which are always preferred.

More specifically, the set of registers to be bound is determined like this: First, bind all 1-bit registers (flags). Then, bind a (sub)set of the remaining registers like this:

  • Begin with the set of all registers.
  • Remove all registers overlapping with an already-bound 1-bit register.
  • Remove all registers that are covered entirely by another register in the same set and are smaller than it.
  • Remove the one marked with RZ_REG_NAME_PC, if it exists.
  • While there still exists at least overlap, from the overlap of two registers at the lowest offset, remove the register with the higher offset.

If two registers have the same offset and size, the result is currently undefined.

Definition at line 35 of file il_reg.c.

35  {
38  if (!rb) {
39  return NULL;
40  }
41  RzVector regs;
43  for (int i = 0; i < RZ_REG_TYPE_LAST; i++) {
44  // bind all flags (1-bit regs) unconditionally
45  RzRegItem *item;
48  if (!flags) {
49  continue;
50  }
51  rz_list_foreach (reg->regset[i].regs, iter, item) {
52  if (item->size != 1) {
53  continue;
54  }
55  // check for same-offset flag
56  RzRegItem *item2;
57  RzListIter *iter2;
58  rz_list_foreach (flags, iter2, item2) {
59  if (item2->offset == item->offset) {
60  goto next_flag;
61  }
62  }
63  // all good, bind it
64  rz_list_push(flags, item);
65  char *name = strdup(item->name);
66  if (!name) {
68  goto err;
69  }
71  if (!bitem) {
72  free(name);
74  goto err;
75  }
76  bitem->name = name;
77  bitem->size = item->size;
78  next_flag:
79  continue;
80  }
81  // for the remaining regs, first filter regs that contain a flag
82  RzList *nonflags = rz_list_new();
83  if (!nonflags) {
85  goto err;
86  }
87  rz_list_foreach (reg->regset[i].regs, iter, item) {
88  RzRegItem *flag;
89  RzListIter *fiter;
90  rz_list_foreach (flags, fiter, flag) {
91  if (flag->offset >= item->offset && flag->offset < item->offset + item->size) {
92  goto next_reg;
93  }
94  }
95  rz_list_push(nonflags, item);
96  next_reg:
97  continue;
98  }
99  // then bind the remaining regs, favoring larger ones on overlaps
100  RzList *items = rz_reg_filter_items_covered(nonflags);
101  rz_list_free(nonflags);
102  if (!items) {
104  continue;
105  }
107  const char *pc = rz_reg_get_name(reg, RZ_REG_NAME_PC);
108  RzRegItem *prev = NULL;
109  rz_list_foreach (items, iter, item) {
110  if (prev && prev->offset + prev->size > item->offset) {
111  // overlap where one reg is not fully contained in another.
112  // this is not supported yet.
113  continue;
114  }
115  if (pc && !strcmp(item->name, pc)) {
116  // pc is handled outside of reg binding
117  continue;
118  }
119  char *name = strdup(item->name);
120  if (!name) {
122  rz_list_free(items);
123  goto err;
124  }
126  if (!bitem) {
127  free(name);
129  rz_list_free(items);
130  goto err;
131  }
132  bitem->name = name;
133  bitem->size = item->size;
134  prev = item;
135  }
136  rz_list_free(items);
138  }
139  // from now on, the array should be treated immutable, so we deliberately don't use RzVector anymore.
140  rb->regs_count = rz_vector_len(&regs);
141  rb->regs = rz_vector_flush(&regs);
143  return rb;
144 err:
146  free(rb);
147  return NULL;
148 }
static char * regs[]
Definition: analysis_sh.c:203
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
#define NULL
Definition: cris-opc.c:27
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
static void reg_binding_item_fini(RzILRegBindingItem *item, void *unused)
Definition: il_reg.c:12
static int reg_offset_cmp(const void *value, const void *list_data)
Definition: il_reg.c:8
#define reg(n)
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
const char * name
Definition: op.c:541
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
RZ_API RZ_OWN RzList * rz_reg_filter_items_covered(RZ_BORROW RZ_NONNULL const RzList *regs)
Filter out all register items that are smaller than but covered entirely by some other register.
Definition: reg.c:489
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
@ RZ_REG_TYPE_LAST
Definition: rz_reg.h:34
@ RZ_REG_NAME_PC
Definition: rz_reg.h:43
#define RZ_NEW0(x)
Definition: rz_types.h:284
void(* RzVectorFree)(void *e, void *user)
Definition: rz_vector.h:42
RZ_API void * rz_vector_flush(RzVector *vec)
Turn the vector into a fixed-size array. This will clear the vector and return an array of its origin...
Definition: vector.c:230
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API void rz_vector_fini(RzVector *vec)
Definition: vector.c:61
static size_t rz_vector_len(const RzVector *vec)
Definition: rz_vector.h:82
RZ_API void rz_vector_init(RzVector *vec, size_t elem_size, RzVectorFree free, void *free_user)
Definition: vector.c:33
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
Definition: z80asm.h:102
ut32 size
number of bits of the register and variable
Definition: rz_il_reg.h:15
char * name
name of both the register and the variable that binds to it
Definition: rz_il_reg.h:14
RzILRegBindingItem * regs
regs_count registers that are bound to variables
Definition: rz_il_reg.h:24
int size
in bits> 8,16,32,64 ... 128/256
Definition: rz_reg.h:120
int offset
Offset into register profile in bits.
Definition: rz_reg.h:121
char * name
Definition: rz_reg.h:118

References err, flags, free(), i, name, rz_il_reg_binding_item_t::name, rz_reg_item_t::name, NULL, rz_reg_item_t::offset, pc, reg, reg_binding_item_fini(), reg_offset_cmp(), regs, rz_il_reg_binding_t::regs, rz_il_reg_binding_t::regs_count, rz_list_free(), rz_list_new(), rz_list_push(), rz_list_sort(), RZ_NEW0, rz_reg_filter_items_covered(), rz_reg_get_name(), RZ_REG_NAME_PC, RZ_REG_TYPE_LAST, rz_return_val_if_fail, rz_vector_fini(), rz_vector_flush(), rz_vector_init(), rz_vector_len(), rz_vector_push(), rz_il_reg_binding_item_t::size, rz_reg_item_t::size, and strdup().

Referenced by setup_regs().

◆ rz_il_reg_binding_exactly()

RZ_API RzILRegBinding* rz_il_reg_binding_exactly ( RZ_NONNULL RzReg reg,
size_t  regs_count,
RZ_NONNULL RZ_BORROW const char **  regs 
)

Create a new binding that binds exactly the given register names, querying reg for any additionally needed info

Parameters
regsarray of regs_count names of registers. Each of these must be part of reg and they must not overlap.

Definition at line 154 of file il_reg.c.

154  {
157  if (!rb) {
158  return NULL;
159  }
160  rb->regs_count = regs_count;
161  rb->regs = RZ_NEWS0(RzILRegBindingItem, regs_count);
162  if (!rb->regs) {
163  goto err_rb;
164  }
165  // all bound items to check for overlaps
166  RzRegItem **items = RZ_NEWS(RzRegItem *, regs_count);
167  if (!items) {
168  goto err_regs;
169  }
170  for (size_t i = 0; i < regs_count; i++) {
172  if (!ri) {
173  goto err_regs;
174  }
175  // Check if this item overlaps any already bound registers.
176  // Overlaps must not happen because they will confuse the VM and analysis.
177  for (size_t j = 0; j < i; j++) {
178  if (items[j]->type != ri->type) {
179  continue;
180  }
181  if (items[j]->offset + items[j]->size <= ri->offset || items[j]->offset >= ri->offset + ri->size) {
182  continue;
183  }
184  // overlap detected
185  goto err_regs;
186  }
187  rb->regs[i].name = strdup(regs[i]);
188  if (!rb->regs[i].name) {
189  goto err_regs;
190  }
191  rb->regs[i].size = ri->size;
192  items[i] = ri;
193  }
194  free(items);
195  return rb;
196 err_regs:
197  for (size_t i = 0; i < regs_count; i++) {
199  }
200  free(rb->regs);
201  free(items);
202 err_rb:
203  free(rb);
204  return NULL;
205 }
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
int type
Definition: mipsasm.c:17
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
@ RZ_REG_TYPE_ANY
Definition: rz_reg.h:35
#define RZ_NEWS(x, y)
Definition: rz_types.h:283
#define RZ_NEW(x)
Definition: rz_types.h:285
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
RzRegisterType type
Register type.
Definition: rz_reg.h:119

References free(), i, rz_il_reg_binding_item_t::name, NULL, rz_reg_item_t::offset, reg, reg_binding_item_fini(), regs, rz_il_reg_binding_t::regs, rz_il_reg_binding_t::regs_count, RZ_NEW, RZ_NEWS, RZ_NEWS0, rz_reg_get(), RZ_REG_TYPE_ANY, rz_return_val_if_fail, rz_il_reg_binding_item_t::size, rz_reg_item_t::size, strdup(), type, and rz_reg_item_t::type.

Referenced by setup_regs().

◆ rz_il_reg_binding_free()

RZ_API void rz_il_reg_binding_free ( RzILRegBinding rb)

Definition at line 207 of file il_reg.c.

207  {
208  if (!rb) {
209  return;
210  }
211  for (size_t i = 0; i < rb->regs_count; i++) {
213  }
214  free(rb->regs);
215  free(rb);
216 }

References free(), i, NULL, reg_binding_item_fini(), rz_il_reg_binding_t::regs, and rz_il_reg_binding_t::regs_count.

Referenced by rz_analysis_il_vm_free().

◆ rz_il_vm_setup_reg_binding()

RZ_API void rz_il_vm_setup_reg_binding ( RZ_NONNULL struct rz_il_vm_t vm,
RZ_NONNULL RZ_BORROW RzILRegBinding rb 
)

◆ rz_il_vm_sync_from_reg()

RZ_API void rz_il_vm_sync_from_reg ( RZ_NONNULL struct rz_il_vm_t vm,
RZ_NONNULL RzILRegBinding rb,
RZ_NONNULL RzReg reg 
)

◆ rz_il_vm_sync_to_reg()

RZ_API bool rz_il_vm_sync_to_reg ( RZ_NONNULL struct rz_il_vm_t vm,
RZ_NONNULL RzILRegBinding rb,
RZ_NONNULL RzReg reg 
)