Rizin
unix-like reverse engineering framework and cli tools
profile.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_list.h>
5 #include <rz_util/rz_log.h>
6 #include <rz_util/rz_str.h>
7 #include <rz_reg.h>
8 #include <rz_util.h>
9 #include <rz_util/rz_assert.h>
10 #include <rz_lib.h>
11 #include <string.h>
12 
14  if (!def) {
15  return;
16  }
17  free(def->name);
18  free(def->comment);
19  free(def->flags);
20  free(def);
21 }
22 
24  if (!alias) {
25  return;
26  }
27  free(alias->reg_name);
28  free(alias->alias);
29  free(alias);
30 }
31 
35 static int expect_reg_type_by_name(const char *str) {
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 }
42 
57 static bool parse_type(RZ_OUT RzRegProfileDef *def, const char *type_str) {
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 }
83 
91 static ut32 parse_size(char *s) {
93  if (s[0] == '.') {
94  return strtoul(s + 1, NULL, 0);
95  } else {
96  return strtoul(s, NULL, 0) * 8;
97  }
98 }
99 
111 static bool parse_offset(const char *s, RZ_OUT RzRegProfileDef *def) {
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 }
132 
144 static bool parse_alias(RZ_OUT RzList *alias_list, RZ_BORROW RzList *tokens) {
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 }
174 
183 static bool parse_def(RZ_OUT RzList *def_list, RZ_BORROW RzList *tokens) {
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 }
241 
270 static bool parse_reg_profile_str(RZ_OUT RzList *alias_list, RZ_OUT RzList *def_list, const char *profile_str) {
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 }
344 
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 }
368 
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 }
422 
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 }
485 
486 RZ_API bool rz_reg_set_profile(RzReg *reg, const char *profile) {
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 }
506 
507 static char *gdb_to_rz_profile(const char *gdb) {
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 }
630 
631 RZ_API char *rz_reg_parse_gdb_profile(const char *profile_file) {
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 }
651 
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 }
#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
static SblHeader sb
Definition: bin_mbn.c:26
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
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
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
a0
Definition: insn-good.s.cs:704
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
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 void * rz_list_get_bottom(RZ_NONNULL const RzList *list)
Returns the first element of the list.
Definition: list.c:467
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
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 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
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
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_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
static int save
Definition: main.c:14
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")
int type
Definition: mipsasm.c:17
line
Definition: setup.py:34
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
static bool parse_alias(RZ_OUT RzList *alias_list, RZ_BORROW RzList *tokens)
Parses a register alias.
Definition: profile.c:144
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 int expect_reg_type_by_name(const char *str)
Definition: profile.c:35
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
static void rz_reg_profile_alias_free(RzRegProfileAlias *alias)
Definition: profile.c:23
static void add_item_to_regset(RZ_BORROW RzReg *reg, RZ_BORROW RzRegItem *item)
Definition: profile.c:345
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
static char * gdb_to_rz_profile(const char *gdb)
Definition: profile.c:507
RZ_API char * rz_reg_parse_gdb_profile(const char *profile_file)
Definition: profile.c:631
RZ_API bool rz_reg_set_profile(RzReg *reg, const char *profile)
Definition: profile.c:486
static bool parse_def(RZ_OUT RzList *def_list, RZ_BORROW RzList *tokens)
Parses a register definition.
Definition: profile.c:183
RZ_API char * rz_reg_profile_to_cc(RzReg *reg)
Definition: profile.c:652
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 const char * rz_reg_get_name_by_type(RzReg *reg, const char *alias_name)
Definition: reg.c:72
RZ_API int rz_reg_get_name_idx(const char *type)
Definition: reg.c:102
RZ_API int rz_reg_type_by_name(const char *str)
Returns the register type for the given type abbreviation.
Definition: reg.c:83
RZ_API void rz_reg_free_internal(RzReg *reg, bool init)
Definition: reg.c:191
RZ_API void rz_reg_item_free(RzRegItem *item)
Definition: reg.c:96
RZ_API bool rz_reg_set_name(RZ_NONNULL RzReg *reg, RzRegisterId role, RZ_NONNULL const char *name)
Definition: reg.c:138
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
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
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RzRegisterType
Definition: rz_reg.h:20
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
@ RZ_REG_TYPE_LAST
Definition: rz_reg.h:34
@ RZ_REG_TYPE_FLG
Definition: rz_reg.h:27
@ RZ_REG_TYPE_ANY
Definition: rz_reg.h:35
RzRegisterId
Definition: rz_reg.h:42
@ RZ_REG_NAME_LAST
Definition: rz_reg.h:71
RZ_API char * rz_str_appendf(char *ptr, const char *fmt,...) RZ_PRINTF_CHECK(2
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
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_append(char *ptr, const char *string)
Definition: str.c:1063
#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_trim_head_ro(const char *str)
Definition: str_trim.c:86
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 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 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
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
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
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_OUT
Definition: rz_types.h:51
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_BORROW
Definition: rz_types.h:63
#define UT32_MAX
Definition: rz_types_base.h:99
#define st32
Definition: rz_types_base.h:12
#define isspace(c)
Definition: safe-ctype.h:141
#define isalpha(c)
Definition: safe-ctype.h:125
static int
Definition: sfsocketcall.h:114
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
Definition: gzappend.c:170
Definition: z80asm.h:102
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
static int file
Definition: z80asm.c:58
int def(FILE *source, FILE *dest, int level)
Definition: zpipe.c:36