Rizin
unix-like reverse engineering framework and cli tools
profile.c File Reference
#include <rz_list.h>
#include <rz_util/rz_log.h>
#include <rz_util/rz_str.h>
#include <rz_reg.h>
#include <rz_util.h>
#include <rz_util/rz_assert.h>
#include <rz_lib.h>
#include <string.h>

Go to the source code of this file.

Functions

static void rz_reg_profile_def_free (RzRegProfileDef *def)
 
static void rz_reg_profile_alias_free (RzRegProfileAlias *alias)
 
static int expect_reg_type_by_name (const char *str)
 
static bool parse_type (RZ_OUT RzRegProfileDef *def, const char *type_str)
 Parses a register type string. More...
 
static ut32 parse_size (char *s)
 Parses the size of a register definition. Sizes with . in front are in bits. Otherwise in bytes. More...
 
static bool parse_offset (const char *s, RZ_OUT RzRegProfileDef *def)
 Parses the offset of a register defintion and sets the offset in def->offset. More...
 
static bool parse_alias (RZ_OUT RzList *alias_list, RZ_BORROW RzList *tokens)
 Parses a register alias. More...
 
static bool parse_def (RZ_OUT RzList *def_list, RZ_BORROW RzList *tokens)
 Parses a register definition. More...
 
static bool parse_reg_profile_str (RZ_OUT RzList *alias_list, RZ_OUT RzList *def_list, const char *profile_str)
 Parses a register profile string. Each line is either a register alias or a register definiton. More...
 
static void add_item_to_regset (RZ_BORROW RzReg *reg, RZ_BORROW RzRegItem *item)
 
RZ_API bool rz_reg_set_reg_profile (RZ_BORROW RzReg *reg)
 Fills reg->regset with the definitions and alias of the register profile. More...
 
RZ_API bool rz_reg_set_profile_string (RZ_NONNULL RzReg *reg, RZ_NONNULL const char *profile_str)
 Parses a register profile string and sets up all registers accordingly in reg. More...
 
RZ_API bool rz_reg_set_profile (RzReg *reg, const char *profile)
 
static char * gdb_to_rz_profile (const char *gdb)
 
RZ_API char * rz_reg_parse_gdb_profile (const char *profile_file)
 
RZ_API char * rz_reg_profile_to_cc (RzReg *reg)
 

Function Documentation

◆ add_item_to_regset()

static void add_item_to_regset ( RZ_BORROW RzReg reg,
RZ_BORROW RzRegItem item 
)
static

Definition at line 345 of file profile.c.

345  {
346  rz_return_if_fail(reg && item);
347  RzRegisterType t = item->arena;
348 
349  if (!reg->regset[t].regs) {
350  reg->regset[t].regs = rz_list_newf((RzListFree)rz_reg_item_free);
351  }
352  if (!reg->regset[t].ht_regs) {
353  reg->regset[t].ht_regs = ht_pp_new0();
354  }
355 
356  // Dynamically update the list of supported bit sizes
357  reg->bits |= item->size;
358  rz_list_append(reg->regset[t].regs, item);
359  ht_pp_insert(reg->regset[t].ht_regs, item->name, item);
360 
361  // Update the overall type of registers into a regset
362  if (item->type == RZ_REG_TYPE_ANY) {
363  reg->regset[t].maskregstype = UT32_MAX;
364  return;
365  }
366  reg->regset[t].maskregstype |= ((int)1 << item->type);
367 }
#define reg(n)
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_reg_item_free(RzRegItem *item)
Definition: reg.c:96
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
RzRegisterType
Definition: rz_reg.h:20
@ RZ_REG_TYPE_ANY
Definition: rz_reg.h:35
#define UT32_MAX
Definition: rz_types_base.h:99
static int
Definition: sfsocketcall.h:114

References int, reg, rz_list_append(), rz_list_newf(), rz_reg_item_free(), RZ_REG_TYPE_ANY, rz_return_if_fail, and UT32_MAX.

Referenced by rz_reg_set_reg_profile().

◆ expect_reg_type_by_name()

static int expect_reg_type_by_name ( const char *  str)
static

Like rz_reg_type_by_name, but warn if non-existent

Definition at line 35 of file profile.c.

35  {
36  int r = rz_reg_type_by_name(str);
37  if (r < 0) {
38  RZ_LOG_WARN("No register type for type abbreviation \"%s\".\n", str);
39  }
40  return r;
41 }
#define r
Definition: crypto_rc6.c:12
RZ_API int rz_reg_type_by_name(const char *str)
Returns the register type for the given type abbreviation.
Definition: reg.c:83
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56

References r, RZ_LOG_WARN, rz_reg_type_by_name(), and cmd_descs_generate::str.

Referenced by parse_type().

◆ gdb_to_rz_profile()

static char* gdb_to_rz_profile ( const char *  gdb)
static

Definition at line 507 of file profile.c.

507  {
509  RzStrBuf *sb = rz_strbuf_new("");
510  if (!sb) {
511  return NULL;
512  }
513  char *ptr1, *gptr, *gptr1;
514  char name[16], groups[128], type[16];
515  const int all = 1, gpr = 2, save = 4, restore = 8, float_ = 16,
516  sse = 32, vector = 64, system = 128, mmx = 256;
517  int number, rel, offset, size, type_bits, ret;
518  // Every line is -
519  // Name Number Rel Offset Size Type Groups
520  const char *ptr = rz_str_trim_head_ro(gdb);
521 
522  // It's possible someone includes the heading line too. Skip it
523  if (rz_str_startswith(ptr, "Name")) {
524  if (!(ptr = strchr(ptr, '\n'))) {
526  return NULL;
527  }
528  ptr++;
529  }
530  for (;;) {
531  // Skip whitespace at beginning of line and empty lines
532  while (isspace((ut8)*ptr)) {
533  ptr++;
534  }
535  if (!*ptr) {
536  break;
537  }
538  if ((ptr1 = strchr(ptr, '\n'))) {
539  *ptr1 = '\0';
540  } else {
541  eprintf("Could not parse line: %s (missing \\n)\n", ptr);
543  return false;
544  }
545  ret = sscanf(ptr, " %s %d %d %d %d %s %s", name, &number, &rel,
546  &offset, &size, type, groups);
547  // Groups is optional, others not
548  if (ret < 6) {
549  if (*ptr != '*') {
550  eprintf("Could not parse line: %s\n", ptr);
552  return NULL;
553  }
554  ptr = ptr1 + 1;
555  continue;
556  }
557  // If name is '', then skip
558  if (rz_str_startswith(name, "''")) {
559  if (!ptr1) {
560  break;
561  }
562  ptr = ptr1 + 1;
563  continue;
564  }
565  // If size is 0, skip
566  if (size == 0) {
567  if (!ptr1) {
568  break;
569  }
570  ptr = ptr1 + 1;
571  continue;
572  }
573  // Parse group
574  gptr = groups;
575  type_bits = 0;
576  while (1) {
577  if ((gptr1 = strchr(gptr, ','))) {
578  *gptr1 = '\0';
579  }
580  if (rz_str_startswith(gptr, "general")) {
581  type_bits |= gpr;
582  } else if (rz_str_startswith(gptr, "all")) {
583  type_bits |= all;
584  } else if (rz_str_startswith(gptr, "save")) {
585  type_bits |= save;
586  } else if (rz_str_startswith(gptr, "restore")) {
587  type_bits |= restore;
588  } else if (rz_str_startswith(gptr, "float")) {
589  type_bits |= float_;
590  } else if (rz_str_startswith(gptr, "sse")) {
591  type_bits |= sse;
592  } else if (rz_str_startswith(gptr, "mmx")) {
593  type_bits |= mmx;
594  } else if (rz_str_startswith(gptr, "vector")) {
595  type_bits |= vector;
596  } else if (rz_str_startswith(gptr, "system")) {
597  type_bits |= system;
598  }
599  if (!gptr1) {
600  break;
601  }
602  gptr = gptr1 + 1;
603  }
604  // If type is not defined, skip
605  if (!*type) {
606  if (!ptr1) {
607  break;
608  }
609  ptr = ptr1 + 1;
610  continue;
611  }
612  // TODO: More mappings between gdb and rizin reg groups. For now, either fpu or gpr
613  if (!(type_bits & sse) && !(type_bits & float_)) {
614  type_bits |= gpr;
615  }
616  // Print line
617  rz_strbuf_appendf(sb, "%s\t%s\t.%d\t%d\t0\n",
618  // Ref: Comment above about more register type mappings
619  ((type_bits & mmx) || (type_bits & float_) || (type_bits & sse)) ? "fpu" : "gpr",
620  name, size * 8, offset);
621  // Go to next line
622  if (!ptr1) {
623  break;
624  }
625  ptr = ptr1 + 1;
626  continue;
627  }
628  return rz_strbuf_drain(sb);
629 }
static SblHeader sb
Definition: bin_mbn.c:26
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec vector
Definition: sflib.h:82
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
uint8_t ut8
Definition: lh5801.h:11
static int save
Definition: main.c:14
int type
Definition: mipsasm.c:17
#define eprintf(x, y...)
Definition: rlcc.c:7
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API const char * rz_str_trim_head_ro(const char *str)
Definition: str_trim.c:86
RZ_API bool rz_str_startswith(RZ_NONNULL const char *str, RZ_NONNULL const char *needle)
Checks if a string starts with a specifc sequence of characters (case sensitive)
Definition: str.c:3286
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
#define isspace(c)
Definition: safe-ctype.h:141
Definition: z80asm.h:102

References test_group_name::all, eprintf, make_dist_html::groups, isspace, NULL, rz_return_val_if_fail, rz_str_startswith(), rz_str_trim_head_ro(), rz_strbuf_appendf(), rz_strbuf_drain(), rz_strbuf_free(), rz_strbuf_new(), save, sb, type, and vector.

Referenced by rz_reg_parse_gdb_profile().

◆ parse_alias()

static bool parse_alias ( RZ_OUT RzList alias_list,
RZ_BORROW RzList tokens 
)
static

Parses a register alias.

The alias is of the form: "=<alias> <reg name>"

Parameters
regThe RzReg struct with the register profile.
tokensA list with both tokens of the alias string.
Returns
true On success.
false On Failure.

Definition at line 144 of file profile.c.

144  {
145  rz_return_val_if_fail(alias_list && tokens, false);
147  if (!pa) {
148  RZ_LOG_WARN("Unable to allocate memory.\n");
149  return false;
150  }
151 
152  const char *real_name = rz_list_get_n(tokens, 1);
153  const char *alias = rz_list_get_n(tokens, 0);
154  if (!alias) {
155  RZ_LOG_WARN("Failed to get alias name from token.\n");
156  free(pa);
157  return false;
158  }
159 
160  RzRegisterId role = rz_reg_get_name_idx(alias + 1);
161  if (!(role >= 0 && role < RZ_REG_NAME_LAST)) {
162  RZ_LOG_WARN("Invalid alias\n");
163  free(pa);
164  return false;
165  }
166 
167  pa->alias = strdup(alias);
168  pa->reg_name = strdup(real_name);
169  pa->role = role;
170  rz_list_append(alias_list, pa);
171 
172  return true;
173 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
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")
RZ_API int rz_reg_get_name_idx(const char *type)
Definition: reg.c:102
RzRegisterId
Definition: rz_reg.h:42
@ RZ_REG_NAME_LAST
Definition: rz_reg.h:71
#define RZ_NEW0(x)
Definition: rz_types.h:284
RzRegisterId role
Register role (PC, Argument etc.)
Definition: rz_reg.h:96
char * reg_name
Real register name of alias.
Definition: rz_reg.h:98
char * alias
Alias of register.
Definition: rz_reg.h:97

References RzRegProfileAlias::alias, free(), RzRegProfileAlias::reg_name, RzRegProfileAlias::role, rz_list_append(), rz_list_get_n(), RZ_LOG_WARN, RZ_NEW0, rz_reg_get_name_idx(), RZ_REG_NAME_LAST, rz_return_val_if_fail, and strdup().

Referenced by parse_reg_profile_str().

◆ parse_def()

static bool parse_def ( RZ_OUT RzList def_list,
RZ_BORROW RzList tokens 
)
static

Parses a register definition.

Parameters
regRegister struct with the register profile.
tokensList of strings of a single register definition.
Returns
false On failure.
true On success.

Definition at line 183 of file profile.c.

183  {
184  rz_return_val_if_fail(def_list && tokens, false);
185 
187  if (!def) {
188  RZ_LOG_WARN("Unable to allocate memory.\n");
189  return false;
190  }
191  const char *name = rz_list_get_n(tokens, 1);
192  if (!name) {
193  goto reg_parse_error;
194  }
195  def->name = strdup(name);
196 
197  if (!parse_type(def, rz_list_get_n(tokens, 0))) {
198  RZ_LOG_WARN("Invalid register type.\n");
199  goto reg_parse_error;
200  }
201 
202  def->size = parse_size(rz_list_get_n(tokens, 2));
203  if (def->size == UT32_MAX || def->size == 0) {
204  RZ_LOG_WARN("Invalid register size.\n");
205  goto reg_parse_error;
206  }
207 
208  def->packed = parse_size(rz_list_get_n(tokens, 4));
209  if (def->packed == UT32_MAX) {
210  RZ_LOG_WARN("Invalid register packed size.\n");
211  goto reg_parse_error;
212  }
213 
214  if (!parse_offset(rz_list_get_n(tokens, 3), def)) {
215  RZ_LOG_WARN("Invalid register offset.\n");
216  goto reg_parse_error;
217  }
218 
219  // Comments and flags are optional
220  if (rz_list_length(tokens) == 6) {
221  const char *comment_flag = rz_list_get_n(tokens, 5);
222  if (!comment_flag) {
223  goto reg_parse_error;
224  }
225  if (comment_flag[0] == '#') {
226  // Remove # from the comment
227  def->comment = strdup(comment_flag + 1);
228  } else {
229  def->flags = strdup(comment_flag);
230  }
231  }
232 
233  rz_list_append(def_list, def);
234 
235  return true;
236 
237 reg_parse_error:
239  return false;
240 }
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
static ut32 parse_size(char *s)
Parses the size of a register definition. Sizes with . in front are in bits. Otherwise in bytes.
Definition: profile.c:91
static bool parse_type(RZ_OUT RzRegProfileDef *def, const char *type_str)
Parses a register type string.
Definition: profile.c:57
static bool parse_offset(const char *s, RZ_OUT RzRegProfileDef *def)
Parses the offset of a register defintion and sets the offset in def->offset.
Definition: profile.c:111
static void rz_reg_profile_def_free(RzRegProfileDef *def)
Definition: profile.c:13
int def(FILE *source, FILE *dest, int level)
Definition: zpipe.c:36

References def(), parse_offset(), parse_size(), parse_type(), rz_list_append(), rz_list_get_n(), rz_list_length(), RZ_LOG_WARN, RZ_NEW0, rz_reg_profile_def_free(), rz_return_val_if_fail, strdup(), and UT32_MAX.

Referenced by parse_reg_profile_str().

◆ parse_offset()

static bool parse_offset ( const char *  s,
RZ_OUT RzRegProfileDef def 
)
static

Parses the offset of a register defintion and sets the offset in def->offset.

Offset is of the form: <byte>.<bit> .<bit> is optional.

Parameters
sOffset string.
defThe defintion item to store the offset into def->offset in bits.
Returns
false On failure (sets def->offset = UT32_MAX).
true On success.

Definition at line 111 of file profile.c.

111  {
112  rz_return_val_if_fail(s && def, false);
113  if (s[0] == '?') {
114  def->offset = UT32_MAX;
115  return true;
116  } else if (s[0] == '.') {
117  def->offset = strtoul(s + 1, NULL, 0);
118  return true;
119  }
120  def->offset = strtoul(s, NULL, 0) * 8;
121 
122  const char *bi = strchr(s, '.');
123  if (!bi) {
124  // No bit offset given.
125  return true;
126  }
127 
128  ut8 bit_offset = strtoul(bi + 1, NULL, 0);
129  def->offset += bit_offset;
130  return true;
131 }
static RzSocket * s
Definition: rtr.c:28

References def(), NULL, rz_return_val_if_fail, s, and UT32_MAX.

Referenced by parse_def().

◆ parse_reg_profile_str()

static bool parse_reg_profile_str ( RZ_OUT RzList alias_list,
RZ_OUT RzList def_list,
const char *  profile_str 
)
static

Parses a register profile string. Each line is either a register alias or a register definiton.

A register alias string is of the following form: "=<alias> <name>\n"

A register definition string is of the following form: "(<sub-type>@)main-type <name> .<size> <byte offset>(.<bit offset>) <packed> (# <comment> OR <flags>)\n"

Elements in "()" are optional. Each "<...>" token is separated by tab or space characters.

  • alias: Register alias (e.g. PC, A1 etc.)
  • name: Register name.
  • size: Register size in bits.
  • main-type: Register type: gpr, fpr, ctr, flg etc.
  • sub-type: The second register type (e.g. xmm@fpu : xmm is sub-type of fpu)
  • byte offset: Offset into register profile in bytes.
  • bit offset: Offset into the byte offset in bits.
  • packed: Packed size of the register in bytes.
  • comment: A comment about the register.
  • Flags this register holds.
Parameters
regRegister struct which holds all register items.
profileRegister profile string.
Returns
false On failure.
true On success.

Definition at line 270 of file profile.c.

270  {
271  rz_return_val_if_fail(alias_list && def_list && profile_str, false);
272 
273  RzList *def_lines = rz_str_split_duplist_n(profile_str, "\n", 0, true);
274  rz_return_val_if_fail(def_lines, false);
275 
276  st32 l = 0; // Line number
277  const char *line;
278  bool is_alias = false;
279  RzListIter *it;
280  RzList *toks = NULL;
281  rz_list_foreach (def_lines, it, line) {
282  ++l;
283  if (RZ_STR_ISEMPTY(line)) {
284  continue;
285  }
286  if (rz_str_strchr(line, "#")) {
287  RzList *line_and_cmt = rz_str_split_duplist_n_regex(line, "#", 0, true);
288  char *raw_comment = strdup(rz_list_get_top(line_and_cmt));
289  if (!raw_comment) {
290  RZ_LOG_WARN("Comment could not be split from register definition. Line: \"%s\"\n", line);
291  continue;
292  }
293  char *tmp = rz_str_prepend(raw_comment, "#");
294  if (!tmp) {
295  RZ_LOG_WARN("Could not prepend # to comment. Line: \"%s\".\n", line);
296  continue;
297  }
298  char *comment = strdup(tmp);
299  toks = rz_str_split_duplist_n_regex(rz_list_get_bottom(line_and_cmt), "[[:blank:]]+", 0, true);
300  rz_list_append(toks, comment);
301  rz_list_free(line_and_cmt);
302  } else {
303  toks = rz_str_split_duplist_n_regex(line, "[[:blank:]]+", 0, true);
304  }
305  ut32 toks_len = rz_list_length(toks);
306  if (rz_list_empty(toks)) {
307  continue;
308  }
309 
310  const char *first_tok = rz_list_get_n(toks, 0);
311  if (first_tok[0] == '#') { // Comment line
312  continue;
313  } else if (first_tok[0] == '=') { // Alias
314  if (toks_len != 2) {
315  RZ_LOG_WARN("Invalid number of %d columns in alias \"%s\" at line %d. 2 needed.\n", toks_len, line, l);
316  continue;
317  }
318  is_alias = true;
319  } else if (isalpha(first_tok[0])) {
320  if (toks_len != 5 && toks_len != 6) {
321  RZ_LOG_WARN("Invalid number of %d columns in definition \"%s\" at line %d. 5 or 6 needed.\n", toks_len, line, l);
322  continue;
323  }
324  } else {
325  RZ_LOG_WARN("Invalid line \"%s\" at register profiles line %d.\n", line, l);
326  continue;
327  }
328  bool success = is_alias
329  ? parse_alias(alias_list, toks)
330  : parse_def(def_list, toks);
331  if (!success) {
332  RZ_LOG_WARN("Parsing error in \"%s\" at line %d.\n", line, l);
333  rz_list_free(toks);
334  rz_list_free(def_lines);
335  return false;
336  }
337  is_alias = false;
338  rz_list_free(toks);
339  }
340  rz_list_free(def_lines);
341 
342  return true;
343 }
uint32_t ut32
RZ_API RZ_BORROW void * rz_list_get_bottom(RZ_NONNULL const RzList *list)
Returns the first element of the list.
Definition: list.c:467
RZ_API RZ_BORROW void * rz_list_get_top(RZ_NONNULL const RzList *list)
Returns the last element of the list.
Definition: list.c:457
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
line
Definition: setup.py:34
static bool parse_alias(RZ_OUT RzList *alias_list, RZ_BORROW RzList *tokens)
Parses a register alias.
Definition: profile.c:144
static bool parse_def(RZ_OUT RzList *def_list, RZ_BORROW RzList *tokens)
Parses a register definition.
Definition: profile.c:183
RZ_API RZ_OWN RzList * rz_str_split_duplist_n_regex(RZ_NONNULL const char *_str, RZ_NONNULL const char *r, int n, bool trim)
Split the string str according to the regex r and returns a RzList with the result.
Definition: str.c:3506
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
RZ_API char * rz_str_prepend(char *ptr, const char *string)
Definition: str.c:1027
RZ_API const char * rz_str_strchr(RZ_NONNULL const char *str, RZ_NONNULL const char *c)
Returns a pointer to the first occurrence of UTF-8 character c in the string s.
Definition: str.c:768
RZ_API RzList * rz_str_split_duplist_n(const char *str, const char *c, int n, bool trim)
Split the string str according to the substring c and returns a RzList with the result.
Definition: str.c:3485
#define st32
Definition: rz_types_base.h:12
#define isalpha(c)
Definition: safe-ctype.h:125

References isalpha, setup::line, NULL, parse_alias(), parse_def(), rz_list_append(), rz_list_free(), rz_list_get_bottom(), rz_list_get_n(), rz_list_get_top(), rz_list_length(), RZ_LOG_WARN, rz_return_val_if_fail, RZ_STR_ISEMPTY, rz_str_prepend(), rz_str_split_duplist_n(), rz_str_split_duplist_n_regex(), rz_str_strchr(), st32, strdup(), and autogen_x86imm::tmp.

Referenced by rz_reg_set_profile_string().

◆ parse_size()

static ut32 parse_size ( char *  s)
static

Parses the size of a register definition. Sizes with . in front are in bits. Otherwise in bytes.

Parameters
sSize string.
Returns
ut32 The size as integer or UT64_MAX if it fails.

Definition at line 91 of file profile.c.

91  {
93  if (s[0] == '.') {
94  return strtoul(s + 1, NULL, 0);
95  } else {
96  return strtoul(s, NULL, 0) * 8;
97  }
98 }

References NULL, rz_return_val_if_fail, s, and UT32_MAX.

Referenced by parse_def().

◆ parse_type()

static bool parse_type ( RZ_OUT RzRegProfileDef def,
const char *  type_str 
)
static

Parses a register type string.

The type string must be of the following form:

<sub-type><main-type>

"<sub-type>@" is optional.

Parameters
itemRegister item whichs types are set.
type_strThe type string.
Returns
true On success.
false On failure.

Definition at line 57 of file profile.c.

57  {
58  rz_return_val_if_fail(def && type_str, false);
59  char *s = strdup(type_str);
60  char *at = strchr(s, '@');
61  if (at) {
62  // This register has a secondary type e.g. xmm@fpu
63  def->arena_type = expect_reg_type_by_name(at + 1);
64  s[at - s] = '\0';
65  def->type = expect_reg_type_by_name(s);
66  } else {
67  def->type = expect_reg_type_by_name(s);
68  def->arena_type = def->type;
69  if (def->type == RZ_REG_TYPE_FLG) { // Hack to put flgs into gpr arena.
70  def->arena_type = RZ_REG_TYPE_GPR;
71  } else {
72  def->arena_type = def->type;
73  }
74  }
75  bool res = true;
76  if (def->type < 0 || def->arena_type < 0) {
77  RZ_LOG_ERROR("Illegal type abbreviation \"%s\"\n", s);
78  res = false;
79  }
80  free(s);
81  return res;
82 }
static int expect_reg_type_by_name(const char *str)
Definition: profile.c:35
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
@ RZ_REG_TYPE_FLG
Definition: rz_reg.h:27

References def(), expect_reg_type_by_name(), free(), RZ_LOG_ERROR, RZ_REG_TYPE_FLG, RZ_REG_TYPE_GPR, rz_return_val_if_fail, s, and strdup().

Referenced by parse_def().

◆ rz_reg_parse_gdb_profile()

RZ_API char* rz_reg_parse_gdb_profile ( const char *  profile_file)

Definition at line 631 of file profile.c.

631  {
632  char *str = NULL;
633  if (!(str = rz_file_slurp(profile_file, NULL))) {
634  char *base = rz_sys_getenv(RZ_LIB_ENV);
635  if (base) {
636  char *file = rz_str_appendf(base, RZ_SYS_DIR "%s", profile_file);
637  if (file) {
639  free(file);
640  }
641  }
642  }
643  if (str) {
644  char *ret = gdb_to_rz_profile(str);
645  free(str);
646  return ret;
647  }
648  eprintf("rz_reg_parse_gdb_profile: Cannot find '%s'\n", profile_file);
649  return NULL;
650 }
static char * gdb_to_rz_profile(const char *gdb)
Definition: profile.c:507
RZ_API RZ_OWN char * rz_file_slurp(const char *str, RZ_NULLABLE size_t *usz)
Definition: file.c:454
#define RZ_LIB_ENV
Definition: rz_lib.h:23
RZ_API char * rz_str_appendf(char *ptr, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API char * rz_sys_getenv(const char *key)
Get the value of an environment variable named key or NULL if none exists.
Definition: sys.c:483
#define RZ_SYS_DIR
Definition: rz_types.h:218
Definition: gzappend.c:170

References eprintf, free(), gdb_to_rz_profile(), NULL, rz_file_slurp(), RZ_LIB_ENV, rz_str_appendf(), RZ_SYS_DIR, rz_sys_getenv(), and cmd_descs_generate::str.

Referenced by rz_reg_profile_gdb_handler().

◆ rz_reg_profile_alias_free()

static void rz_reg_profile_alias_free ( RzRegProfileAlias alias)
static

Definition at line 23 of file profile.c.

23  {
24  if (!alias) {
25  return;
26  }
27  free(alias->reg_name);
28  free(alias->alias);
29  free(alias);
30 }

References RzRegProfileAlias::alias, free(), and RzRegProfileAlias::reg_name.

Referenced by rz_reg_set_profile_string().

◆ rz_reg_profile_def_free()

static void rz_reg_profile_def_free ( RzRegProfileDef def)
static

Definition at line 13 of file profile.c.

13  {
14  if (!def) {
15  return;
16  }
17  free(def->name);
18  free(def->comment);
19  free(def->flags);
20  free(def);
21 }

References def(), and free().

Referenced by parse_def(), and rz_reg_set_profile_string().

◆ rz_reg_profile_to_cc()

RZ_API char* rz_reg_profile_to_cc ( RzReg reg)

Definition at line 652 of file profile.c.

652  {
653  const char *r0 = rz_reg_get_name_by_type(reg, "R0");
654  const char *a0 = rz_reg_get_name_by_type(reg, "A0");
655  const char *a1 = rz_reg_get_name_by_type(reg, "A1");
656  const char *a2 = rz_reg_get_name_by_type(reg, "A2");
657  const char *a3 = rz_reg_get_name_by_type(reg, "A3");
658 
659  if (!a0) {
660  RZ_LOG_WARN("It is mandatory to have at least one argument register defined in the register profile.\n");
661  return NULL;
662  }
663  if (!r0) {
664  r0 = a0;
665  }
666  if (a3 && a2 && a1) {
667  return rz_str_newf("%s reg(%s, %s, %s, %s)", r0, a0, a1, a2, a3);
668  }
669  if (a2 && a1) {
670  return rz_str_newf("%s reg(%s, %s, %s)", r0, a0, a1, a2);
671  }
672  if (a1) {
673  return rz_str_newf("%s reg(%s, %s)", r0, a0, a1);
674  }
675  return rz_str_newf("%s reg(%s)", r0, a0);
676 }
a0
Definition: insn-good.s.cs:704
RZ_API const char * rz_reg_get_name_by_type(RzReg *reg, const char *alias_name)
Definition: reg.c:72
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1

References a0, NULL, r0, reg, RZ_LOG_WARN, rz_reg_get_name_by_type(), and rz_str_newf().

Referenced by rz_core_analysis_cc_init(), and rz_reg_cc_handler().

◆ rz_reg_set_profile()

RZ_API bool rz_reg_set_profile ( RzReg reg,
const char *  profile 
)

Definition at line 486 of file profile.c.

486  {
487  rz_return_val_if_fail(reg && profile, false);
488  char *base, *file;
489  char *str = rz_file_slurp(profile, NULL);
490  if (!str) {
491  base = rz_sys_getenv(RZ_LIB_ENV);
492  if (base) {
493  file = rz_str_append(base, profile);
495  free(file);
496  }
497  }
498  if (!str) {
499  eprintf("rz_reg_set_profile: Cannot find '%s'\n", profile);
500  return false;
501  }
502  bool ret = rz_reg_set_profile_string(reg, str);
503  free(str);
504  return ret;
505 }
RZ_API bool rz_reg_set_profile_string(RZ_NONNULL RzReg *reg, RZ_NONNULL const char *profile_str)
Parses a register profile string and sets up all registers accordingly in reg.
Definition: profile.c:431
RZ_API char * rz_str_append(char *ptr, const char *string)
Definition: str.c:1063
static int file
Definition: z80asm.c:58

References eprintf, file, free(), NULL, reg, rz_file_slurp(), RZ_LIB_ENV, rz_reg_set_profile_string(), rz_return_val_if_fail, rz_str_append(), rz_sys_getenv(), and cmd_descs_generate::str.

Referenced by rz_reg_profile_open_handler().

◆ rz_reg_set_profile_string()

RZ_API bool rz_reg_set_profile_string ( RZ_NONNULL RzReg reg,
RZ_NONNULL const char *  profile_str 
)

Parses a register profile string and sets up all registers accordingly in reg.

Parameters
regThe RzReg struct which should hold the register data.
profileThe register profile string.
Returns
false On failure;
true On success.

Definition at line 431 of file profile.c.

431  {
432  rz_return_val_if_fail(reg && profile_str, false);
433  // Same profile, no need to change
434  if (reg->reg_profile_str && !strcmp(reg->reg_profile_str, profile_str)) {
435  return true;
436  }
437 
438  // we should reset all the arenas before setting the new reg profile
440  // Purge the old registers
441  rz_reg_free_internal(reg, true);
443 
444  // Cache the profile string
445  reg->reg_profile_str = strdup(profile_str);
446  reg->reg_profile.defs = rz_list_newf((RzListFree)rz_reg_profile_def_free);
447  reg->reg_profile.alias = rz_list_newf((RzListFree)rz_reg_profile_alias_free);
448  rz_return_val_if_fail(reg->reg_profile.defs && reg->reg_profile.alias, true);
449 
450  if (!parse_reg_profile_str(reg->reg_profile.alias, reg->reg_profile.defs, profile_str)) {
451  RZ_LOG_WARN("Could not parse register profile string.\n");
452  rz_reg_free_internal(reg, false);
453  return false;
454  }
455 
456  // Check for duplicates
457  RzListIter *it, *tmp;
459  rz_list_foreach_safe (reg->reg_profile.defs, it, tmp, def) {
460  if (rz_reg_get(reg, def->name, RZ_REG_TYPE_ANY)) {
461  RZ_LOG_WARN("Ignoring duplicated register definition '%s'.\n", def->name);
462  rz_list_delete(reg->reg_profile.defs, it);
463  }
464  }
465 
466  if (!rz_reg_set_reg_profile(reg)) {
467  RZ_LOG_WARN("Could not set reg profile.\n");
468  return false;
469  }
470 
471  reg->size = 0;
472  for (ut32 i = 0; i < RZ_REG_TYPE_LAST; i++) {
473  RzRegSet *rs = &reg->regset[i];
474  if (rs && rs->arena) {
475  reg->size += rs->arena->size; // Sums minimum arena size.
476  }
477  }
478 
480  // dup the last arena to allow regdiffing
483  return true;
484 }
#define rs()
lzma_index ** i
Definition: index.h:629
RZ_API int rz_reg_fit_arena(RzReg *reg)
Definition: arena.c:135
RZ_API int rz_reg_arena_push(RzReg *reg)
Definition: arena.c:236
RZ_API void rz_reg_arena_pop(RzReg *reg)
Definition: arena.c:216
RZ_API void rz_reg_arena_shrink(RzReg *reg)
Definition: arena.c:345
RZ_API void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
static void rz_reg_profile_alias_free(RzRegProfileAlias *alias)
Definition: profile.c:23
RZ_API bool rz_reg_set_reg_profile(RZ_BORROW RzReg *reg)
Fills reg->regset with the definitions and alias of the register profile.
Definition: profile.c:376
static bool parse_reg_profile_str(RZ_OUT RzList *alias_list, RZ_OUT RzList *def_list, const char *profile_str)
Parses a register profile string. Each line is either a register alias or a register definiton.
Definition: profile.c:270
RZ_API void rz_reg_reindex(RzReg *reg)
Definition: reg.c:243
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
RZ_API void rz_reg_free_internal(RzReg *reg, bool init)
Definition: reg.c:191
@ RZ_REG_TYPE_LAST
Definition: rz_reg.h:34

References def(), i, parse_reg_profile_str(), reg, rs, rz_list_delete(), rz_list_newf(), RZ_LOG_WARN, rz_reg_arena_pop(), rz_reg_arena_push(), rz_reg_arena_shrink(), rz_reg_fit_arena(), rz_reg_free_internal(), rz_reg_get(), rz_reg_profile_alias_free(), rz_reg_profile_def_free(), rz_reg_reindex(), rz_reg_set_reg_profile(), RZ_REG_TYPE_ANY, RZ_REG_TYPE_LAST, rz_return_val_if_fail, strdup(), and autogen_x86imm::tmp.

Referenced by rz_analysis_set_reg_profile(), rz_debug_reg_profile_sync(), rz_reg_set_profile(), and setup_regs().

◆ rz_reg_set_reg_profile()

RZ_API bool rz_reg_set_reg_profile ( RZ_BORROW RzReg reg)

Fills reg->regset with the definitions and alias of the register profile.

Parameters
regThe RzReg struct which holds the register profile and an empty reg->regset
Returns
false On failure.
true On success.

Definition at line 376 of file profile.c.

376  {
377  rz_return_val_if_fail(reg, false);
378  rz_return_val_if_fail(reg->reg_profile.alias && reg->reg_profile.defs, false);
379 
380  RzListIter *it;
381  RzRegProfileAlias *alias;
382  rz_list_foreach (reg->reg_profile.alias, it, alias) {
383  if (!rz_reg_set_name(reg, alias->role, alias->reg_name)) {
384  RZ_LOG_WARN("Invalid alias gviven.\n");
385  return false;
386  }
387  }
389  rz_list_foreach (reg->reg_profile.defs, it, def) {
390  RzRegItem *item = RZ_NEW0(RzRegItem);
391  if (!item) {
392  RZ_LOG_WARN("Unable to allocate memory.\n");
393  return false;
394  }
395 
396  item->name = strdup(def->name);
397 
398  item->type = def->type;
399  item->arena = def->arena_type;
400 
401  item->size = def->size;
402  item->offset = def->offset;
403  // Update the overall profile size
404  if (item->offset + item->size > reg->size) {
405  reg->size = item->offset + item->size;
406  }
407 
408  item->packed_size = def->packed;
409 
410  if (def->comment) {
411  item->comment = strdup(def->comment);
412  }
413  if (def->flags) {
414  item->flags = strdup(def->flags);
415  }
416 
417  add_item_to_regset(reg, item);
418  }
419 
420  return true;
421 }
static void add_item_to_regset(RZ_BORROW RzReg *reg, RZ_BORROW RzRegItem *item)
Definition: profile.c:345
RZ_API bool rz_reg_set_name(RZ_NONNULL RzReg *reg, RzRegisterId role, RZ_NONNULL const char *name)
Definition: reg.c:138
RzRegisterType type
Register type.
Definition: rz_reg.h:119
int size
in bits> 8,16,32,64 ... 128/256
Definition: rz_reg.h:120
int arena
In which arena is this reg living. Usually equals type.
Definition: rz_reg.h:127
char * flags
Definition: rz_reg.h:124
int packed_size
0 means no packed register, 1byte pack, 2b pack...
Definition: rz_reg.h:122
int offset
Offset into register profile in bits.
Definition: rz_reg.h:121
char * comment
Comment to register.
Definition: rz_reg.h:125
char * name
Definition: rz_reg.h:118

References add_item_to_regset(), rz_reg_item_t::arena, rz_reg_item_t::comment, def(), rz_reg_item_t::flags, rz_reg_item_t::name, rz_reg_item_t::offset, rz_reg_item_t::packed_size, reg, RzRegProfileAlias::reg_name, RzRegProfileAlias::role, RZ_LOG_WARN, RZ_NEW0, rz_reg_set_name(), rz_return_val_if_fail, rz_reg_item_t::size, strdup(), and rz_reg_item_t::type.

Referenced by rz_reg_set_profile_string().