Rizin
unix-like reverse engineering framework and cli tools
dwarf_process.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2012-2020 houndthe <cgkajm@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_util.h>
5 #include <rz_type.h>
6 #include <sdb.h>
7 #include <rz_analysis.h>
8 #include <rz_bin_dwarf.h>
9 #include <string.h>
10 
11 typedef struct dwarf_parse_context_t {
14  const ut64 count;
15  Sdb *sdb;
16  HtUP /*<ut64 offset, DwarfDie *die>*/ *die_map;
17  HtUP /*<offset, RzBinDwarfLocList*>*/ *locations;
18  char *lang; // for demangling
19 } Context;
20 
21 typedef struct dwarf_function_t {
23  const char *name;
24  const char *signature;
26  bool is_method;
27  bool is_virtual;
28  bool is_trampoline; // intermediary in making call to another func
29  ut8 access; // public = 1, protected = 2, private = 3, if not set assume private
30  ut64 vtable_addr; // location description
31  ut64 call_conv; // normal || program || nocall
33 
34 typedef enum dwarf_location_kind {
41 typedef struct dwarf_var_location_t {
46  const char *reg_name; /* string literal */
48 
49 typedef struct dwarf_variable_t {
51  char *name;
52  char *type;
54 
55 static void variable_free(Variable *var) {
56  free(var->name);
57  free(var->location);
58  free(var->type);
59  free(var);
60 }
61 
62 /* return -1 if attr isn't found */
63 static inline st32 find_attr_idx(const RzBinDwarfDie *die, st32 attr_name) {
64  st32 i;
65  rz_return_val_if_fail(die, -1);
66  for (i = 0; i < die->count; i++) {
67  if (die->attr_values[i].attr_name == attr_name) {
68  return i;
69  }
70  }
71  return -1;
72 }
73 
74 /* return NULL if attr isn't found */
75 static RzBinDwarfAttrValue *find_attr(const RzBinDwarfDie *die, st32 attr_name) {
76  st32 i;
78  for (i = 0; i < die->count; i++) {
79  if (die->attr_values[i].attr_name == attr_name) {
80  return &die->attr_values[i];
81  }
82  }
83  return NULL;
84 }
85 
94 static bool strbuf_rev_prepend_char(RzStrBuf *sb, const char *s, int c) {
95  rz_return_val_if_fail(sb && s, false);
96  size_t l = strlen(s);
97  // fast path if no chars to append
98  if (l == 0) {
99  return true;
100  }
101  size_t newlen = l + sb->len;
102  char *ns = malloc(newlen + 1);
103  bool ret = false;
104  char *sb_str = sb->ptr ? sb->ptr : sb->buf;
105  char *pivot = strrchr(sb_str, c);
106  if (!pivot) {
107  free(ns);
108  return false;
109  }
110  size_t idx = pivot - sb_str;
111  if (ns) {
112  memcpy(ns, sb_str, idx);
113  memcpy(ns + idx, s, l);
114  memcpy(ns + idx + l, sb_str + idx, sb->len - idx);
115  ns[newlen] = 0;
116  ret = rz_strbuf_set(sb, ns) != NULL;
117  free(ns);
118  }
119  return ret;
120 }
129 static bool strbuf_rev_append_char(RzStrBuf *sb, const char *s, const char *needle) {
130  rz_return_val_if_fail(sb && s, false);
131  size_t l = strlen(s);
132  // fast path if no chars to append
133  if (l == 0) {
134  return true;
135  }
136  bool ret = false;
137  char *sb_str = sb->ptr ? sb->ptr : sb->buf;
138  char *pivot = strstr(sb_str, needle);
139  if (!pivot) {
140  return false;
141  }
142  pivot += strlen(needle);
143  size_t idx = pivot - sb_str;
144  size_t newlen = l + sb->len;
145  char *ns = malloc(newlen + 1);
146  if (ns) {
147  memcpy(ns, sb_str, idx);
148  memcpy(ns + idx, s, l);
149  memcpy(ns + idx + l, sb_str + idx, sb->len - idx);
150  ns[newlen] = 0;
151  ret = rz_strbuf_set(sb, ns) != NULL;
152  free(ns);
153  }
154  return ret;
155 }
156 
158  return rz_str_newf("type_0x%" PFMT64x, offset);
159 }
160 
167 static char *get_die_name(const RzBinDwarfDie *die) {
168  char *name = NULL;
169  st32 name_attr_idx = find_attr_idx(die, DW_AT_name);
170  if (name_attr_idx != -1) {
171  const char *s = rz_bin_dwarf_attr_value_get_string_content(&die->attr_values[name_attr_idx]);
172  name = RZ_STR_DUP(s);
173  }
174  return name ? name : create_type_name_from_offset(die->offset);
175 }
176 
183 static ut64 get_die_size(const RzBinDwarfDie *die) {
184  ut64 size = 0;
185  st32 byte_size_idx = find_attr_idx(die, DW_AT_byte_size);
186 
187  if (byte_size_idx != -1) {
188  size = die->attr_values[byte_size_idx].uconstant * CHAR_BIT;
189  } else {
190  st32 bit_size_idx = find_attr_idx(die, DW_AT_bit_size);
191 
192  if (bit_size_idx != -1) {
193  size = die->attr_values[bit_size_idx].uconstant;
194  }
195  }
196  return size;
197 }
198 
208  const RzBinDwarfDie *die = &ctx->all_dies[idx++];
209 
210  if (die->has_children) {
211  int child_depth = 1;
212  size_t j;
213  for (j = idx; child_depth > 0 && j < ctx->count; j++) {
214  const RzBinDwarfDie *child_die = &ctx->all_dies[j];
215  // right now we skip non direct descendats of the structure
216  // can be also DW_TAG_suprogram for class methods or tag for templates
217  if (child_depth == 1 && child_die->tag == DW_TAG_subrange_type) {
218  size_t i;
219  for (i = 0; i < child_die->count; i++) {
220  const RzBinDwarfAttrValue *value = &child_die->attr_values[i];
221  switch (value->attr_name) {
222  case DW_AT_upper_bound:
223  case DW_AT_count:
224  rz_strbuf_appendf(strbuf, "[%" PFMT64d "]", value->uconstant + 1);
225  break;
226 
227  default:
228  break;
229  }
230  }
231  }
232  if (child_die->has_children) {
233  child_depth++;
234  }
235  // sibling list is terminated by null entry
236  if (child_die->abbrev_code == 0) {
237  child_depth--;
238  }
239  }
240  }
241  return 0;
242 }
243 
258 static st32 parse_type(Context *ctx, const ut64 offset, RzStrBuf *strbuf, ut64 *size, RZ_NONNULL SetU *visited) {
259  rz_return_val_if_fail(strbuf && visited, -1);
260  if (set_u_contains(visited, offset)) {
261  return -1;
262  }
263  set_u_add(visited, offset);
264  RzBinDwarfDie *die = ht_up_find(ctx->die_map, offset, NULL);
265  if (!die) {
266  return -1;
267  }
268 
269  st32 type_idx;
270  st32 tag;
271  char *name = NULL;
272  // get size of first type DIE that has size
273  if (size && *size == 0) {
274  *size = get_die_size(die);
275  }
276  switch (die->tag) {
277  // this should be recursive search for the type until you find base/user defined type
278  case DW_TAG_pointer_type:
279  type_idx = find_attr_idx(die, DW_AT_type);
280  if (type_idx == -1) {
281  rz_strbuf_append(strbuf, "void");
282  rz_strbuf_append(strbuf, " *");
283  } else {
284  tag = parse_type(ctx, die->attr_values[type_idx].reference, strbuf, size, visited);
285  if (tag == DW_TAG_subroutine_type) {
286  strbuf_rev_prepend_char(strbuf, "(*)", '(');
287  } else if (tag == DW_TAG_pointer_type) {
288  if (!strbuf_rev_append_char(strbuf, "*", "(*")) {
289  strbuf_rev_prepend_char(strbuf, "*", '*');
290  }
291  } else {
292  rz_strbuf_append(strbuf, " *");
293  }
294  }
295  break;
296  // We won't parse them as a complete type, because that will already be done
297  // so just a name now
298  case DW_TAG_typedef:
299  case DW_TAG_base_type:
302  case DW_TAG_union_type:
303  case DW_TAG_class_type:
304  name = get_die_name(die);
305  rz_strbuf_append(strbuf, name);
306  free(name);
307  break;
309  type_idx = find_attr_idx(die, DW_AT_type);
310  if (type_idx == -1) {
311  rz_strbuf_append(strbuf, "void");
312  } else {
313  parse_type(ctx, die->attr_values[type_idx].reference, strbuf, size, visited);
314  }
315  rz_strbuf_append(strbuf, " (");
316  if (die->has_children) { // has parameters
317  }
318  rz_strbuf_append(strbuf, ")");
319  break;
320  case DW_TAG_array_type:
321  type_idx = find_attr_idx(die, DW_AT_type);
322  if (type_idx != -1) {
323  parse_type(ctx, die->attr_values[type_idx].reference, strbuf, size, visited);
324  }
325  parse_array_type(ctx, die - ctx->all_dies, strbuf);
326  break;
327  case DW_TAG_const_type:
328  type_idx = find_attr_idx(die, DW_AT_type);
329  if (type_idx != -1) {
330  parse_type(ctx, die->attr_values[type_idx].reference, strbuf, size, visited);
331  }
332  rz_strbuf_append(strbuf, " const");
333  break;
335  type_idx = find_attr_idx(die, DW_AT_type);
336  if (type_idx != -1) {
337  parse_type(ctx, die->attr_values[type_idx].reference, strbuf, size, visited);
338  }
339  rz_strbuf_append(strbuf, " volatile");
340  break;
342  type_idx = find_attr_idx(die, DW_AT_type);
343  if (type_idx != -1) {
344  parse_type(ctx, die->attr_values[type_idx].reference, strbuf, size, visited);
345  }
346  rz_strbuf_append(strbuf, " restrict");
347  break;
349  type_idx = find_attr_idx(die, DW_AT_type);
350  if (type_idx != -1) {
351  parse_type(ctx, die->attr_values[type_idx].reference, strbuf, size, visited);
352  }
353  rz_strbuf_append(strbuf, " &&");
354  break;
356  type_idx = find_attr_idx(die, DW_AT_type);
357  if (type_idx != -1) {
358  parse_type(ctx, die->attr_values[type_idx].reference, strbuf, size, visited);
359  }
360  rz_strbuf_append(strbuf, " &");
361  break;
362  default:
363  break;
364  }
365  set_u_delete(visited, offset);
366  return (st32)die->tag;
367 }
368 
374  SetU *visited = set_u_new();
375  if (!visited) {
376  return -1;
377  }
378  st32 r = parse_type(ctx, offset, strbuf, size, visited);
379  set_u_free(visited);
380  return r;
381 }
382 
393  rz_return_val_if_fail(result, NULL);
394  const RzBinDwarfDie *die = &ctx->all_dies[idx];
395 
396  char *name = NULL;
397  char *type = NULL;
398  ut64 offset = 0;
399  ut64 size = 0;
400  RzStrBuf strbuf;
401  rz_strbuf_init(&strbuf);
402  size_t i;
403  for (i = 0; i < die->count; i++) {
405  switch (die->attr_values[i].attr_name) {
406  case DW_AT_name:
407  free(name);
408  name = get_die_name(die);
409  if (!name) {
410  goto cleanup;
411  }
412  break;
413  case DW_AT_type:
414  parse_type_outer(ctx, value->reference, &strbuf, &size);
415  free(type);
416  type = rz_strbuf_drain_nofree(&strbuf);
417  if (!type || !*type) {
418  goto cleanup;
419  }
420  break;
422  /*
423  2 cases, 1.: If val is integer, it offset in bytes from
424  the beginning of containing entity. If containing entity has
425  a bit offset, member has that bit offset aswell
426  2.: value is a location description
427  http://www.dwarfstd.org/doc/DWARF4.pdf#page=39&zoom=100,0,0
428  */
429  offset = value->uconstant;
430  break;
431  case DW_AT_accessibility: // private, public etc.
432  case DW_AT_mutable: // flag is it is mutable
434  /*
435  int that specifies the number of bits from beginning
436  of containing entity to the beginning of the data member
437  */
438  break;
439  // If the size of a data member is not the same as the
440  // size of the type given for the data member
441  case DW_AT_byte_size:
442  size = value->uconstant * CHAR_BIT;
443  break;
444  case DW_AT_bit_size:
445  size = value->uconstant;
446  break;
448  default:
449  break;
450  }
451  }
452 
453  result->name = name;
454  result->type = rz_type_parse_string_single(ctx->analysis->typedb->parser, type, NULL);
455  if (!result->type) {
456  goto cleanup;
457  }
458  result->offset = offset;
459  result->size = size;
460  free(type);
461  return result;
462 
463 cleanup:
464  free(name);
465  free(type);
466  return NULL;
467 }
468 
479  const RzBinDwarfDie *die = &ctx->all_dies[idx];
480 
481  char *name = NULL;
482  int val = 0;
483  size_t i;
484 
485  // Enumerator has DW_AT_name and DW_AT_const_value
486  for (i = 0; i < die->count; i++) {
488  switch (die->attr_values[i].attr_name) {
489  case DW_AT_name:
490  free(name);
491  name = get_die_name(die);
492  if (!name) {
493  goto cleanup;
494  }
495  break;
496  case DW_AT_const_value:
497  // ?? can be block, sdata, data, string w/e
498  val = value->uconstant; // TODO solve the encoding, I don't know in which union member is it store
499  break;
500  default:
501  break;
502  }
503  }
504 
505  result->name = name;
506  result->val = (int)val;
507  return result;
508 cleanup:
509  free(name);
510  return NULL;
511 }
512 
520 // http://www.dwarfstd.org/doc/DWARF4.pdf#page=102&zoom=100,0,0
522  const RzBinDwarfDie *die = &ctx->all_dies[idx];
523 
524  RzBaseTypeKind kind;
525  if (die->tag == DW_TAG_union_type) {
527  } else {
529  }
530 
531  RzBaseType *base_type = rz_type_base_type_new(kind);
532  if (!base_type) {
533  return;
534  }
535 
536  base_type->name = get_die_name(die);
537  if (!base_type->name) {
538  rz_type_base_type_free(base_type);
539  return;
540  }
541 
542  // if it is definition of previous declaration (TODO Fix, big ugly hotfix addition)
543  st32 spec_attr_idx = find_attr_idx(die, DW_AT_specification);
544  if (spec_attr_idx != -1) {
545  RzBinDwarfDie *decl_die = ht_up_find(ctx->die_map, die->attr_values[spec_attr_idx].reference, NULL);
546  if (!decl_die) {
547  rz_type_base_type_free(base_type);
548  return;
549  }
550  st32 name_attr_idx = find_attr_idx(decl_die, DW_AT_name);
551  if (name_attr_idx != -1) {
552  free(base_type->name);
553  base_type->name = get_die_name(decl_die);
554  }
555  }
556 
557  base_type->size = get_die_size(die);
558 
559  RzTypeStructMember member = { 0 };
560  // Parse out all members, can this in someway be extracted to a function?
561  if (die->has_children) {
562  int child_depth = 1; // Direct children of the node
563  size_t j;
564  idx++; // Move to the first children node
565  for (j = idx; child_depth > 0 && j < ctx->count; j++) {
566  const RzBinDwarfDie *child_die = &ctx->all_dies[j];
567  // we take only direct descendats of the structure
568  // can be also DW_TAG_suprogram for class methods or tag for templates
569  if (child_depth == 1 && child_die->tag == DW_TAG_member) {
570  RzTypeStructMember *result = parse_struct_member(ctx, j, &member);
571  if (!result) {
572  rz_type_base_type_free(base_type);
573  return;
574  } else {
575  void *element = rz_vector_push(&base_type->struct_data.members, &member);
576  if (!element) {
577  rz_type_base_type_free(base_type);
578  return;
579  }
580  }
581  }
582  if (child_die->has_children) {
583  child_depth++;
584  }
585  if (child_die->abbrev_code == 0) { // siblings terminator
586  child_depth--;
587  }
588  }
589  }
590  rz_type_db_save_base_type(ctx->analysis->typedb, base_type);
591 }
592 
601  const RzBinDwarfDie *die = &ctx->all_dies[idx];
602 
604  if (!base_type) {
605  return;
606  }
607 
608  base_type->name = get_die_name(die);
609  if (!base_type->name) {
610  rz_type_base_type_free(base_type);
611  return;
612  }
613  base_type->size = get_die_size(die);
614 
615  st32 type_attr_idx = find_attr_idx(die, DW_AT_type);
616  if (type_attr_idx != -1) {
617  RzStrBuf strbuf;
618  rz_strbuf_init(&strbuf);
619  parse_type_outer(ctx, die->attr_values[type_attr_idx].reference, &strbuf, &base_type->size);
620  char *type = rz_strbuf_drain_nofree(&strbuf);
621  base_type->type = rz_type_parse_string_single(ctx->analysis->typedb->parser, type, NULL);
622  free(type);
623  if (!base_type->type) {
624  rz_type_base_type_free(base_type);
625  return;
626  }
627  }
628 
629  RzTypeEnumCase cas;
630  if (die->has_children) {
631  int child_depth = 1; // Direct children of the node
632  size_t j;
633  idx++; // Move to the first children node
634  for (j = idx; child_depth > 0 && j < ctx->count; j++) {
635  const RzBinDwarfDie *child_die = &ctx->all_dies[j];
636  // we take only direct descendats of the structure
637  if (child_depth == 1 && child_die->tag == DW_TAG_enumerator) {
638  RzTypeEnumCase *result = parse_enumerator(ctx, j, &cas);
639  if (!result) {
640  rz_type_base_type_free(base_type);
641  return;
642  } else {
643  void *element = rz_vector_push(&base_type->enum_data.cases, &cas);
644  if (!element) {
646  rz_type_base_type_free(base_type);
647  return;
648  }
649  }
650  }
651  if (child_die->has_children) {
652  child_depth++;
653  }
654  // sibling list is terminated by null entry
655  if (child_die->abbrev_code == 0) {
656  child_depth--;
657  }
658  }
659  }
660  rz_type_db_save_base_type(ctx->analysis->typedb, base_type);
661 }
662 
672 static void parse_typedef(Context *ctx, ut64 idx) {
673  const RzBinDwarfDie *die = &ctx->all_dies[idx];
674 
675  char *name = NULL;
676  char *type = NULL;
677  ut64 size = 0;
678  RzStrBuf strbuf;
679  rz_strbuf_init(&strbuf);
680  size_t i;
681 
682  for (i = 0; i < die->count; i++) {
684  switch (die->attr_values[i].attr_name) {
685  case DW_AT_name:
686  name = get_die_name(die);
687  if (!name) {
688  goto cleanup;
689  }
690  break;
691  case DW_AT_type:
692  parse_type_outer(ctx, value->reference, &strbuf, &size);
693  type = rz_strbuf_drain_nofree(&strbuf);
694  if (!type) {
695  goto cleanup;
696  }
697  break;
698  default:
699  break;
700  }
701  }
702  if (!name || !type) { // type has to have a name for now
703  goto cleanup;
704  }
706  if (!base_type) {
707  goto cleanup;
708  }
709  base_type->name = name;
710  base_type->type = rz_type_parse_string_single(ctx->analysis->typedb->parser, type, NULL);
711  if (!base_type->type) {
712  rz_type_base_type_free(base_type);
713  goto cleanup;
714  }
715  rz_type_db_save_base_type(ctx->analysis->typedb, base_type);
716 
717 cleanup:
718  free(type);
719  rz_strbuf_fini(&strbuf);
720  return;
721 }
722 
724  const RzBinDwarfDie *die = &ctx->all_dies[idx];
725 
726  char *name = NULL;
727  ut64 size = 0;
728  size_t i;
729  // TODO support endiannity and encoding in future?
730  for (i = 0; i < die->count; i++) {
732  switch (die->attr_values[i].attr_name) {
733  case DW_AT_name: {
734  free(name);
736  if (s) {
737  name = strdup(s);
738  } else {
740  }
741  if (!name) {
742  return;
743  }
744  break;
745  }
746  case DW_AT_byte_size:
747  size = value->uconstant * CHAR_BIT;
748  break;
749  case DW_AT_bit_size:
750  size = value->uconstant;
751  break;
752  case DW_AT_encoding:
753  default:
754  break;
755  }
756  }
757  if (!name) { // type has to have a name for now
758  return;
759  }
761  if (!base_type) {
762  free(name);
763  return;
764  }
765  base_type->name = name;
766  base_type->size = size;
767  rz_type_db_save_base_type(ctx->analysis->typedb, base_type);
768 }
769 
770 static const char *get_specification_die_name(const RzBinDwarfDie *die) {
771  st32 linkage_name_attr_idx = find_attr_idx(die, DW_AT_linkage_name);
772  if (linkage_name_attr_idx != -1) {
773  const char *s = rz_bin_dwarf_attr_value_get_string_content(&die->attr_values[linkage_name_attr_idx]);
774  if (s) {
775  return s;
776  }
777  }
778  st32 name_attr_idx = find_attr_idx(die, DW_AT_name);
779  if (name_attr_idx != -1) {
780  const char *s = rz_bin_dwarf_attr_value_get_string_content(&die->attr_values[name_attr_idx]);
781  if (s) {
782  return s;
783  }
784  }
785  return NULL;
786 }
787 
788 static void get_spec_die_type(Context *ctx, RzBinDwarfDie *die, RzStrBuf *ret_type) {
789  st32 attr_idx = find_attr_idx(die, DW_AT_type);
790  if (attr_idx != -1) {
791  ut64 size = 0;
792  parse_type_outer(ctx, die->attr_values[attr_idx].reference, ret_type, &size);
793  }
794 }
795 
796 /* For some languages linkage name is more informative like C++,
797  but for Rust it's rubbish and the normal name is fine */
798 static bool prefer_linkage_name(char *lang) {
799  if (!lang) {
800  return false;
801  }
802  if (!strcmp(lang, "rust")) {
803  return false;
804  } else if (!strcmp(lang, "ada")) {
805  return false;
806  }
807  return true;
808 }
809 
810 static void parse_abstract_origin(Context *ctx, ut64 offset, RzStrBuf *type, const char **name) {
811  RzBinDwarfDie *die = ht_up_find(ctx->die_map, offset, NULL);
812  if (die) {
813  size_t i;
814  ut64 size = 0;
815  bool has_linkage_name = false;
816  bool get_linkage_name = prefer_linkage_name(ctx->lang);
817  for (i = 0; i < die->count; i++) {
818  const RzBinDwarfAttrValue *val = &die->attr_values[i];
819  switch (val->attr_name) {
820  case DW_AT_name:
821  if (!get_linkage_name || !has_linkage_name) {
822  *name = val->string.content;
823  }
824  break;
825  case DW_AT_linkage_name:
827  *name = val->string.content;
828  has_linkage_name = true;
829  break;
830  case DW_AT_type:
831  parse_type_outer(ctx, val->reference, type, &size);
832  break;
833  default:
834  break;
835  }
836  }
837  }
838 }
839 
840 /* x86_64 https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf */
841 static const char *map_dwarf_reg_to_x86_64_reg(ut64 reg_num, VariableLocationKind *kind) {
842  *kind = LOCATION_REGISTER;
843  switch (reg_num) {
844  case 0: return "rax";
845  case 1: return "rdx";
846  case 2: return "rcx";
847  case 3: return "rbx";
848  case 4: return "rsi";
849  case 5: return "rdi";
850  case 6:
851  *kind = LOCATION_BP;
852  return "rbp";
853  case 7:
854  *kind = LOCATION_SP;
855  return "rsp";
856  case 8: return "r8";
857  case 9: return "r9";
858  case 10: return "r10";
859  case 11: return "r11";
860  case 12: return "r12";
861  case 13: return "r13";
862  case 14: return "r14";
863  case 15: return "r15";
864  case 17: return "xmm0";
865  case 18: return "xmm1";
866  case 19: return "xmm2";
867  case 20: return "xmm3";
868  case 21: return "xmm4";
869  case 22: return "xmm5";
870  case 23: return "xmm6";
871  case 24: return "xmm7";
872  default:
873  *kind = LOCATION_UNKNOWN;
874  return "unsupported_reg";
875  }
876 }
877 
878 /* x86 https://01.org/sites/default/files/file_attach/intel386-psabi-1.0.pdf */
879 static const char *map_dwarf_reg_to_x86_reg(ut64 reg_num, VariableLocationKind *kind) {
880  *kind = LOCATION_REGISTER;
881  switch (reg_num) {
882  case 0:
883  case 8:
884  return "eax";
885  case 1: return "edx";
886  case 2: return "ecx";
887  case 3: return "ebx";
888  case 4:
889  *kind = LOCATION_SP;
890  return "esp";
891  case 5:
892  *kind = LOCATION_BP;
893  return "ebp";
894  case 6: return "esi";
895  case 7: return "edi";
896  case 9: return "EFLAGS";
897  case 11: return "st0";
898  case 12: return "st1";
899  case 13: return "st2";
900  case 14: return "st3";
901  case 15: return "st4";
902  case 16: return "st5";
903  case 17: return "st6";
904  case 18: return "st7";
905  case 21: return "xmm0";
906  case 22: return "xmm1";
907  case 23: return "xmm2";
908  case 24: return "xmm3";
909  case 25: return "xmm4";
910  case 26: return "xmm5";
911  case 27: return "xmm6";
912  case 28: return "xmm7";
913  case 29: return "mm0";
914  case 30: return "mm1";
915  case 31: return "mm2";
916  case 32: return "mm3";
917  case 33: return "mm4";
918  case 34: return "mm5";
919  case 35: return "mm6";
920  case 36: return "mm7";
921  case 40: return "es";
922  case 41: return "cs";
923  case 42: return "ss";
924  case 43: return "ds";
925  case 44: return "fs";
926  case 45: return "gs";
927  default:
929  *kind = LOCATION_UNKNOWN;
930  return "unsupported_reg";
931  }
932 }
933 
934 /* https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#DW-REG */
935 static const char *map_dwarf_reg_to_ppc64_reg(ut64 reg_num, VariableLocationKind *kind) {
936  *kind = LOCATION_REGISTER;
937  switch (reg_num) {
938  case 0: return "r0";
939  case 1:
940  *kind = LOCATION_SP;
941  return "r1";
942  case 2: return "r2";
943  case 3: return "r3";
944  case 4: return "r4";
945  case 5: return "r5";
946  case 6: return "r6";
947  case 7: return "r7";
948  case 8: return "r8";
949  case 9: return "r9";
950  case 10: return "r10";
951  case 11: return "r11";
952  case 12: return "r12";
953  case 13: return "r13";
954  case 14: return "r14";
955  case 15: return "r15";
956  case 16: return "r16";
957  case 17: return "r17";
958  case 18: return "r18";
959  case 19: return "r19";
960  case 20: return "r20";
961  case 21: return "r21";
962  case 22: return "r22";
963  case 23: return "r23";
964  case 24: return "r24";
965  case 25: return "r25";
966  case 26: return "r26";
967  case 27: return "r27";
968  case 28: return "r28";
969  case 29: return "r29";
970  case 30: return "r30";
971  case 31: return "r31";
972  default:
974  *kind = LOCATION_UNKNOWN;
975  return "unsupported_reg";
976  }
977 }
978 
979 /* returns string literal register name!
980  TODO add more arches */
981 static const char *get_dwarf_reg_name(RZ_NONNULL char *arch, int reg_num, VariableLocationKind *kind, int bits) {
982  if (!strcmp(arch, "x86")) {
983  if (bits == 64) {
984  return map_dwarf_reg_to_x86_64_reg(reg_num, kind);
985  } else {
986  return map_dwarf_reg_to_x86_reg(reg_num, kind);
987  }
988  } else if (!strcmp(arch, "ppc")) {
989  if (bits == 64) {
990  return map_dwarf_reg_to_ppc64_reg(reg_num, kind);
991  }
992  }
993  *kind = LOCATION_UNKNOWN;
994  return "unsupported_reg";
995 }
996 
998  RzBinDwarfLocRange *largest = NULL;
999  ut64 max_range_size = 0;
1000  RzListIter *iter;
1002  rz_list_foreach (loc_list, iter, range) {
1003  ut64 diff = range->end - range->start;
1004  if (diff > max_range_size) {
1005  max_range_size = diff;
1006  largest = range;
1007  }
1008  }
1009  return largest;
1010 }
1011 
1012 /* TODO move a lot of the parsing here into dwarf.c and do only processing here */
1014  /* reg5 - val is in register 5
1015  fbreg <leb> - offset from frame base
1016  regx <leb> - contents is in register X
1017  addr <addr> - contents is in at addr
1018  bregXX <leb> - contents is at offset from specified register
1019  - we now support 3 options: SP, BP and register based arguments */
1020 
1021  /* Loclist offset is usually CONSTANT or REFERENCE at older DWARF versions, new one has LocListPtr for that */
1022  if (loc->kind != DW_AT_KIND_BLOCK && loc->kind != DW_AT_KIND_LOCLISTPTR && loc->kind != DW_AT_KIND_REFERENCE && loc->kind != DW_AT_KIND_CONSTANT) {
1023  return NULL;
1024  }
1025  RzBinDwarfBlock block;
1026  if (loc->kind == DW_AT_KIND_LOCLISTPTR || loc->kind == DW_AT_KIND_REFERENCE || loc->kind == DW_AT_KIND_CONSTANT) {
1027  ut64 offset = loc->reference;
1028  RzBinDwarfLocList *range_list = ht_up_find(ctx->locations, offset, NULL);
1029  if (!range_list) { /* for some reason offset isn't there, wrong parsing or malformed dwarf */
1030  return NULL;
1031  }
1032  /* use the largest range as a variable */
1034  if (!range) {
1035  return NULL;
1036  }
1037  /* Very rough and sloppy, refactor this hacked up stuff */
1038  block = *range->expression;
1039  // range->expression... etc
1040  } else {
1041  block = loc->block;
1042  }
1044  st64 offset = 0;
1045  ut64 address = 0;
1046  ut64 reg_num = -1;
1047  const char *reg_name = NULL; /* literal */
1048  size_t i;
1049  for (i = 0; i < block.length; i++) {
1050  switch (block.data[i]) {
1051  case DW_OP_fbreg: {
1052  /* TODO sometimes CFA is referenced, but we don't parse that yet
1053  just an offset involving framebase of a function*/
1054  if (i == block.length - 1) {
1055  return NULL;
1056  }
1057  const ut8 *dump = &block.data[++i];
1058  offset = rz_sleb128(&dump, &block.data[loc->block.length]);
1059  if (frame_base) {
1060  /* recursive parsing, but frame_base should be only one, but someone
1061  could make malicious resource exhaustion attack, so a depth counter might be cool? */
1062  VariableLocation *location = parse_dwarf_location(ctx, frame_base, NULL);
1063  if (location) {
1064  location->offset += offset;
1065  return location;
1066  }
1067  return NULL;
1068  } else {
1069  /* Might happen if frame_base has a frame_base reference? I don't think it can tho */
1070  return NULL;
1071  }
1072  } break;
1073  case DW_OP_reg0:
1074  case DW_OP_reg1:
1075  case DW_OP_reg2:
1076  case DW_OP_reg3:
1077  case DW_OP_reg4:
1078  case DW_OP_reg5:
1079  case DW_OP_reg6:
1080  case DW_OP_reg7:
1081  case DW_OP_reg8:
1082  case DW_OP_reg9:
1083  case DW_OP_reg10:
1084  case DW_OP_reg11:
1085  case DW_OP_reg12:
1086  case DW_OP_reg13:
1087  case DW_OP_reg14:
1088  case DW_OP_reg15:
1089  case DW_OP_reg16:
1090  case DW_OP_reg17:
1091  case DW_OP_reg18:
1092  case DW_OP_reg19:
1093  case DW_OP_reg20:
1094  case DW_OP_reg21:
1095  case DW_OP_reg22:
1096  case DW_OP_reg23:
1097  case DW_OP_reg24:
1098  case DW_OP_reg25:
1099  case DW_OP_reg26:
1100  case DW_OP_reg27:
1101  case DW_OP_reg28:
1102  case DW_OP_reg29:
1103  case DW_OP_reg30:
1104  case DW_OP_reg31: {
1105  /* Will mostly be used for SP based arguments */
1106  /* TODO I need to find binaries that uses this so I can test it out*/
1107  reg_num = block.data[i] - DW_OP_reg0; // get the reg number
1108  reg_name = get_dwarf_reg_name(ctx->analysis->cpu, reg_num, &kind, ctx->analysis->bits);
1109  } break;
1110  case DW_OP_breg0:
1111  case DW_OP_breg1:
1112  case DW_OP_breg2:
1113  case DW_OP_breg3:
1114  case DW_OP_breg4:
1115  case DW_OP_breg5:
1116  case DW_OP_breg6:
1117  case DW_OP_breg7:
1118  case DW_OP_breg8:
1119  case DW_OP_breg9:
1120  case DW_OP_breg10:
1121  case DW_OP_breg11:
1122  case DW_OP_breg12:
1123  case DW_OP_breg13:
1124  case DW_OP_breg14:
1125  case DW_OP_breg15:
1126  case DW_OP_breg16:
1127  case DW_OP_breg17:
1128  case DW_OP_breg18:
1129  case DW_OP_breg19:
1130  case DW_OP_breg20:
1131  case DW_OP_breg21:
1132  case DW_OP_breg22:
1133  case DW_OP_breg23:
1134  case DW_OP_breg24:
1135  case DW_OP_breg25:
1136  case DW_OP_breg26:
1137  case DW_OP_breg27:
1138  case DW_OP_breg28:
1139  case DW_OP_breg29:
1140  case DW_OP_breg30:
1141  case DW_OP_breg31: {
1142  if (i == block.length - 1) {
1143  return NULL;
1144  }
1145  /* The single operand of the DW_OP_bregn operations provides
1146  signed LEB128 offset from the specified register. */
1147  reg_num = block.data[i] - DW_OP_breg0; // get the reg number
1148  const ut8 *buffer = &block.data[++i];
1149  offset = rz_sleb128(&buffer, &block.data[block.length]);
1150  /* TODO do a proper expression parsing, move by the amount of bytes sleb reads */
1151  i += buffer - &block.data[0];
1152  reg_name = get_dwarf_reg_name(ctx->analysis->cpu, reg_num, &kind, ctx->analysis->bits);
1153  } break;
1154  case DW_OP_bregx: {
1155  if (i == block.length - 1) {
1156  return NULL;
1157  }
1158  /* 2 operands, reg_number, offset*/
1159  /* I need to find binaries that uses this so I can test it out*/
1160  const ut8 *buffer = &block.data[++i];
1161  const ut8 *buf_end = &block.data[block.length];
1162  buffer = rz_uleb128(buffer, buf_end - buffer, &reg_num, NULL);
1163  if (buffer == buf_end) {
1164  return NULL;
1165  }
1166  offset = rz_sleb128(&buffer, buf_end);
1167  reg_name = get_dwarf_reg_name(ctx->analysis->cpu, reg_num, &kind, ctx->analysis->bits);
1168  } break;
1169  case DW_OP_addr: {
1170  /* The DW_OP_addr operation has a single operand that encodes a machine address and whose
1171  size is the size of an address on the target machine. */
1172  const int addr_size = ctx->analysis->bits / 8;
1173  const ut8 *dump = &block.data[++i];
1174  /* malformed, not enough bytes to represent address */
1175  if (block.length - i < addr_size) {
1176  return NULL;
1177  }
1178  switch (addr_size) {
1179  case 1:
1180  address = rz_read_ble8(dump);
1181  break;
1182  case 2:
1183  address = rz_read_ble16(dump, ctx->analysis->big_endian);
1184  break;
1185  case 4:
1186  address = rz_read_ble32(dump, ctx->analysis->big_endian);
1187  break;
1188  case 8:
1189  address = rz_read_ble64(dump, ctx->analysis->big_endian);
1190  break;
1191  default:
1192  rz_warn_if_reached(); /* weird addr_size */
1193  return NULL;
1194  }
1195  kind = LOCATION_GLOBAL; // address
1196  } break;
1197  case DW_OP_call_frame_cfa: {
1198  // REMOVE XXX
1199  kind = LOCATION_BP;
1200  offset += 16;
1201  } break;
1202  default:
1203  break;
1204  }
1205  }
1206  if (kind == LOCATION_UNKNOWN) {
1207  return NULL;
1208  }
1210  if (location) {
1211  location->reg_name = reg_name;
1212  location->reg_num = reg_num;
1213  location->kind = kind;
1214  location->offset = offset;
1215  location->address = address;
1216  }
1217  return location;
1218 }
1219 
1220 static st32 parse_function_args_and_vars(Context *ctx, ut64 idx, RzStrBuf *args, RzList /*<Variable *>*/ *variables) {
1221  const RzBinDwarfDie *die = &ctx->all_dies[idx++];
1222 
1223  if (die->has_children) {
1224  int child_depth = 1;
1225 
1226  bool get_linkage_name = prefer_linkage_name(ctx->lang);
1227  bool has_linkage_name = false;
1228  int argNumber = 1;
1229  size_t j;
1230  for (j = idx; child_depth > 0 && j < ctx->count; j++) {
1231  const RzBinDwarfDie *child_die = &ctx->all_dies[j];
1232  RzStrBuf type;
1233  rz_strbuf_init(&type);
1234  const char *name = NULL;
1235  if (child_die->tag == DW_TAG_formal_parameter || child_die->tag == DW_TAG_variable) {
1236  Variable *var = RZ_NEW0(Variable);
1237  size_t i;
1238  for (i = 0; i < child_die->count; i++) {
1239  const RzBinDwarfAttrValue *val = &child_die->attr_values[i];
1240  switch (val->attr_name) {
1241  case DW_AT_name:
1242  if (!get_linkage_name || !has_linkage_name) {
1243  name = val->string.content;
1244  }
1245  break;
1246  case DW_AT_linkage_name:
1248  name = val->string.content;
1249  has_linkage_name = true;
1250  break;
1251  case DW_AT_type:
1252  parse_type_outer(ctx, val->reference, &type, NULL);
1253  break;
1254  // abstract origin is supposed to have omitted information
1255  case DW_AT_abstract_origin:
1256  parse_abstract_origin(ctx, val->reference, &type, &name);
1257  break;
1258  case DW_AT_location:
1260  break;
1261  default:
1262  break;
1263  }
1264  }
1265  if (child_die->tag == DW_TAG_formal_parameter && child_depth == 1) {
1266  /* arguments sometimes have only type, create generic argX */
1267  if (type.len) {
1268  if (!name) {
1269  var->name = rz_str_newf("arg%d", argNumber);
1270  } else {
1271  var->name = strdup(name);
1272  }
1273  rz_strbuf_appendf(args, "%s %s,", rz_strbuf_get(&type), var->name);
1274  var->type = strdup(rz_strbuf_get(&type));
1275  rz_list_append(variables, var);
1276  } else {
1277  variable_free(var);
1278  }
1279  argNumber++;
1280  } else { /* DW_TAG_variable */
1281  if (name && type.len) {
1282  var->name = strdup(name);
1283  var->type = strdup(rz_strbuf_get(&type));
1284  rz_list_append(variables, var);
1285  } else {
1286  variable_free(var);
1287  }
1288  rz_strbuf_fini(&type);
1289  }
1290  } else if (child_depth == 1 && child_die->tag == DW_TAG_unspecified_parameters) {
1291  rz_strbuf_appendf(args, "va_args ...,");
1292  }
1293  if (child_die->has_children) {
1294  child_depth++;
1295  }
1296  if (child_die->abbrev_code == 0) { /* sibling list is terminated by null entry */
1297  child_depth--;
1298  }
1299  rz_strbuf_fini(&type);
1300  }
1301  if (args->len > 0) {
1302  rz_strbuf_slice(args, 0, args->len - 1);
1303  }
1304  }
1305  return 0;
1306 }
1307 
1308 static void sdb_save_dwarf_function(Function *dwarf_fcn, RzList /*<Variable *>*/ *variables, Sdb *sdb) {
1309  char *sname = rz_str_sanitize_sdb_key(dwarf_fcn->name);
1310  sdb_set(sdb, sname, "fcn", 0);
1311 
1312  char *addr_key = rz_str_newf("fcn.%s.addr", sname);
1313  char *addr_val = rz_str_newf("0x%" PFMT64x "", dwarf_fcn->addr);
1314  sdb_set(sdb, addr_key, addr_val, 0);
1315  free(addr_key);
1316  free(addr_val);
1317 
1318  /* so we can have name without sanitization */
1319  char *name_key = rz_str_newf("fcn.%s.name", sname);
1320  char *name_val = rz_str_newf("%s", dwarf_fcn->name);
1321  sdb_set(sdb, name_key, name_val, 0);
1322  free(name_key);
1323  free(name_val);
1324 
1325  char *signature_key = rz_str_newf("fcn.%s.sig", sname);
1326  sdb_set(sdb, signature_key, dwarf_fcn->signature, 0);
1327  free(signature_key);
1328 
1329  RzStrBuf vars;
1330  rz_strbuf_init(&vars);
1331  RzListIter *iter;
1332  Variable *var;
1333  rz_list_foreach (variables, iter, var) {
1334  if (!var->location) {
1335  /* NULL location probably means optimized out, maybe put a comment there */
1336  continue;
1337  }
1338  char *key = NULL;
1339  char *val = NULL;
1340  switch (var->location->kind) {
1341  case LOCATION_BP: {
1342  /* value = "type, storage, additional info based on storage (offset)" */
1343 
1344  rz_strbuf_appendf(&vars, "%s,", var->name);
1345  key = rz_str_newf("fcn.%s.var.%s", sname, var->name);
1346  val = rz_str_newf("%s,%" PFMT64d ",%s", "b", var->location->offset, var->type);
1347  sdb_set(sdb, key, val, 0);
1348  } break;
1349  case LOCATION_SP: {
1350  /* value = "type, storage, additional info based on storage (offset)" */
1351 
1352  rz_strbuf_appendf(&vars, "%s,", var->name);
1353  key = rz_str_newf("fcn.%s.var.%s", sname, var->name);
1354  val = rz_str_newf("%s,%" PFMT64d ",%s", "s", var->location->offset, var->type);
1355  sdb_set(sdb, key, val, 0);
1356  } break;
1357  case LOCATION_GLOBAL: {
1358  /* value = "type, storage, additional info based on storage (address)" */
1359 
1360  rz_strbuf_appendf(&vars, "%s,", var->name);
1361  key = rz_str_newf("fcn.%s.var.%s", sname, var->name);
1362  val = rz_str_newf("%s,%" PFMT64u ",%s", "g", var->location->address, var->type);
1363  sdb_set(sdb, key, val, 0);
1364  } break;
1365  case LOCATION_REGISTER: {
1366  /* value = "type, storage, additional info based on storage (register name)" */
1367 
1368  rz_strbuf_appendf(&vars, "%s,", var->name);
1369  key = rz_str_newf("fcn.%s.var.%s", sname, var->name);
1370  val = rz_str_newf("%s,%s,%s", "r", var->location->reg_name, var->type);
1371  sdb_set(sdb, key, val, 0);
1372  } break;
1373 
1374  default:
1375  /* else location is unknown (optimized out), skip the var */
1376  break;
1377  }
1378  free(key);
1379  free(val);
1380  }
1381  if (vars.len > 0) { /* remove the extra , */
1382  rz_strbuf_slice(&vars, 0, vars.len - 1); /* leaks? */
1383  }
1384  char *vars_key = rz_str_newf("fcn.%s.vars", sname);
1385  char *vars_val = rz_str_newf("%s", rz_strbuf_get(&vars));
1386  sdb_set(sdb, vars_key, vars_val, 0);
1387  free(vars_key);
1388  free(vars_val);
1389  rz_strbuf_fini(&vars);
1390  free(sname);
1391 }
1392 
1401  const RzBinDwarfDie *die = &ctx->all_dies[idx];
1402 
1403  Function fcn = { 0 };
1404  bool has_linkage_name = false;
1405  bool get_linkage_name = prefer_linkage_name(ctx->lang);
1406  RzStrBuf ret_type;
1407  rz_strbuf_init(&ret_type);
1408  if (find_attr_idx(die, DW_AT_declaration) != -1) {
1409  return; /* just declaration skip */
1410  }
1411  size_t i;
1412  /* For rust binaries prefer regular name not linkage TODO */
1413  for (i = 0; i < die->count; i++) {
1415  switch (die->attr_values[i].attr_name) {
1416  case DW_AT_name:
1417  if (!get_linkage_name || !has_linkage_name) {
1418  fcn.name = val->kind == DW_AT_KIND_STRING ? val->string.content : fcn.name;
1419  }
1420  break;
1421  case DW_AT_linkage_name:
1423  fcn.name = val->kind == DW_AT_KIND_STRING ? val->string.content : fcn.name;
1424  has_linkage_name = true;
1425  break;
1426  case DW_AT_low_pc:
1427  case DW_AT_entry_pc:
1428  fcn.addr = val->kind == DW_AT_KIND_ADDRESS ? val->address : fcn.addr;
1429  break;
1430  case DW_AT_specification: /* reference to declaration DIE with more info */
1431  {
1432  RzBinDwarfDie *spec_die = ht_up_find(ctx->die_map, val->reference, NULL);
1433  if (spec_die) {
1434  fcn.name = get_specification_die_name(spec_die); /* I assume that if specification has a name, this DIE hasn't */
1435  get_spec_die_type(ctx, spec_die, &ret_type);
1436  }
1437  } break;
1438  case DW_AT_type:
1439  parse_type_outer(ctx, val->reference, &ret_type, NULL);
1440  break;
1441  case DW_AT_virtuality:
1442  fcn.is_method = true; /* method specific attr */
1443  fcn.is_virtual = true;
1444  break;
1445  case DW_AT_object_pointer:
1446  fcn.is_method = true;
1447  break;
1449  fcn.is_method = true;
1450  fcn.vtable_addr = 0; /* TODO we might use this information */
1451  break;
1452  case DW_AT_accessibility:
1453  fcn.is_method = true;
1454  fcn.access = (ut8)val->uconstant;
1455  break;
1456  case DW_AT_external:
1457  fcn.is_external = true;
1458  break;
1459  case DW_AT_trampoline:
1460  fcn.is_trampoline = true;
1461  break;
1462  case DW_AT_ranges:
1463  case DW_AT_high_pc:
1464  default:
1465  break;
1466  }
1467  }
1468  if (!fcn.name || !fcn.addr) { /* we need a name, faddr */
1469  goto cleanup;
1470  }
1471  RzStrBuf args;
1472  rz_strbuf_init(&args);
1473  /* TODO do the same for arguments in future so we can use their location */
1474  RzList /*<Variable*>*/ *variables = rz_list_new();
1475  parse_function_args_and_vars(ctx, idx, &args, variables);
1476 
1477  if (ret_type.len == 0) { /* DW_AT_type is omitted in case of `void` ret type */
1478  rz_strbuf_append(&ret_type, "void");
1479  }
1480  rz_warn_if_fail(ctx->lang);
1481  char *new_name = ctx->analysis->binb.demangle(NULL, ctx->lang, fcn.name, fcn.addr, false);
1482  fcn.name = new_name ? new_name : strdup(fcn.name);
1483  fcn.signature = rz_str_newf("%s %s(%s);", rz_strbuf_get(&ret_type), fcn.name, rz_strbuf_get(&args));
1484  sdb_save_dwarf_function(&fcn, variables, ctx->sdb);
1485 
1486  free((char *)fcn.signature);
1487  free((char *)fcn.name);
1488 
1489  RzListIter *iter;
1490  Variable *var;
1491  rz_list_foreach (variables, iter, var) {
1492  variable_free(var);
1493  }
1494  rz_list_free(variables);
1495  rz_strbuf_fini(&args);
1496 cleanup:
1497  rz_strbuf_fini(&ret_type);
1498 }
1499 
1506 static char *parse_comp_unit_lang(const RzBinDwarfDie *die) {
1508 
1509  int idx = find_attr_idx(die, DW_AT_language);
1510  char *lang = "cxx"; // default fallback
1511  if (idx == -1) {
1512  /* What to do now, it should have one?, just assume C++ */
1513  return lang;
1514  }
1515  const RzBinDwarfAttrValue *val = &die->attr_values[idx];
1517 
1518  switch (val->uconstant) {
1519  case DW_LANG_Java:
1520  return "java";
1521  case DW_LANG_ObjC:
1522  /* subideal, TODO research if dwarf gives me enough info to properly separate C++ and ObjC mangling */
1524  return "objc";
1525  case DW_LANG_D:
1526  return "dlang";
1527  case DW_LANG_Rust:
1528  return "rust";
1529  case DW_LANG_C_plus_plus:
1531  /* no demangling available */
1532  case DW_LANG_Ada83:
1533  case DW_LANG_Cobol74:
1534  case DW_LANG_Cobol85:
1535  case DW_LANG_Fortran77:
1536  case DW_LANG_Fortran90:
1537  case DW_LANG_Pascal83:
1538  case DW_LANG_Modula2:
1539  case DW_LANG_Ada95:
1540  case DW_LANG_Fortran95:
1541  case DW_LANG_PLI:
1542  case DW_LANG_Python:
1543  case DW_LANG_Swift:
1544  case DW_LANG_Julia:
1545  case DW_LANG_Dylan:
1546  case DW_LANG_Fortran03:
1547  case DW_LANG_Fortran08:
1548  case DW_LANG_UPC:
1549  case DW_LANG_C:
1550  case DW_LANG_C89:
1551  case DW_LANG_C99:
1552  case DW_LANG_C11:
1553  default:
1554  return lang;
1555  }
1556  return lang;
1557 }
1558 
1567 
1568  const RzBinDwarfDie *die = &ctx->all_dies[idx];
1569  switch (die->tag) {
1570  case DW_TAG_structure_type:
1571  case DW_TAG_union_type:
1572  case DW_TAG_class_type:
1574  break;
1577  break;
1578  case DW_TAG_typedef:
1579  parse_typedef(ctx, idx);
1580  break;
1581  case DW_TAG_base_type:
1583  break;
1584  case DW_TAG_subprogram:
1586  break;
1587  case DW_TAG_compile_unit:
1588  /* used for name demangling */
1589  ctx->lang = parse_comp_unit_lang(die);
1590  default:
1591  break;
1592  }
1593 }
1594 
1603  rz_return_if_fail(ctx && analysis);
1604  Sdb *dwarf_sdb = sdb_ns(analysis->sdb, "dwarf", 1);
1605  size_t i, j;
1606  const RzBinDwarfDebugInfo *info = ctx->info;
1607  for (i = 0; i < info->count; i++) {
1608  RzBinDwarfCompUnit *unit = &info->comp_units[i];
1609  Context dw_context = { // context per unit?
1610  .analysis = analysis,
1611  .all_dies = unit->dies,
1612  .count = unit->count,
1613  .die_map = info->lookup_table,
1614  .sdb = dwarf_sdb,
1615  .locations = ctx->loc,
1616  .lang = NULL
1617  };
1618  for (j = 0; j < unit->count; j++) {
1619  parse_type_entry(&dw_context, j);
1620  }
1621  }
1622 }
1623 
1624 bool filter_sdb_function_names(void *user, const char *k, const char *v) {
1625  (void)user;
1626  (void)k;
1627  return !strcmp(v, "fcn");
1628 }
1629 
1638  rz_return_if_fail(analysis && dwarf_sdb);
1639 
1640  /* get all entries with value == func */
1641  SdbList *sdb_list = sdb_foreach_list_filter(dwarf_sdb, filter_sdb_function_names, false);
1642  SdbListIter *it;
1643  SdbKv *kv;
1644  /* iterate all function entries */
1645  ls_foreach (sdb_list, it, kv) {
1646  char *func_sname = kv->base.key;
1647 
1648  char *addr_key = rz_str_newf("fcn.%s.addr", func_sname);
1649  ut64 faddr = sdb_num_get(dwarf_sdb, addr_key, 0);
1650  free(addr_key);
1651 
1652  /* if the function is analyzed so we can edit */
1653  RzAnalysisFunction *fcn = rz_analysis_get_function_at(analysis, faddr);
1654  if (fcn) {
1655  /* prepend dwarf debug info stuff with dbg. */
1656  char *real_name_key = rz_str_newf("fcn.%s.name", func_sname);
1657  char *real_name = sdb_get(dwarf_sdb, real_name_key, 0);
1658  free(real_name_key);
1659 
1660  char *dwf_name = rz_str_newf("dbg.%s", real_name);
1661  free(real_name);
1662 
1663  rz_analysis_function_rename(fcn, dwf_name);
1664  free(dwf_name);
1665 
1666  char *tmp = rz_str_newf("fcn.%s.sig", func_sname);
1667  char *fcnstr = sdb_get(dwarf_sdb, tmp, 0);
1668  free(tmp);
1669  /* Apply signature as a comment at a function address */
1670  rz_meta_set_string(analysis, RZ_META_TYPE_COMMENT, faddr, fcnstr);
1671  free(fcnstr);
1672  }
1673  char *var_names_key = rz_str_newf("fcn.%s.vars", func_sname);
1674  char *vars = sdb_get(dwarf_sdb, var_names_key, NULL);
1675  char *var_name;
1676  sdb_aforeach(var_name, vars) {
1677  char *var_key = rz_str_newf("fcn.%s.var.%s", func_sname, var_name);
1678  char *var_data = sdb_get(dwarf_sdb, var_key, NULL);
1679  if (!var_data) {
1680  goto loop_end;
1681  }
1682  char *extra = NULL;
1683  char *kind = sdb_anext(var_data, &extra);
1684  char *type = NULL;
1685  extra = sdb_anext(extra, &type);
1686  RzType *ttype = rz_type_parse_string_single(analysis->typedb->parser, type, NULL);
1687  if (!ttype) {
1688  goto loop_end;
1689  }
1690  st64 offset = 0;
1691  if (*kind != 'r') {
1692  offset = strtol(extra, NULL, 10);
1693  }
1694  if (*kind == 'g') { /* global, fixed addr TODO add size to variables? */
1695  char *global_name = rz_str_newf("global_%s", var_name);
1697  rz_flag_set_next(flags, global_name, offset, 4);
1698  free(global_name);
1699  } else if (*kind == 's' && fcn) {
1700  rz_analysis_function_set_var(fcn, offset - fcn->maxstack, *kind, ttype, 4, false, var_name);
1701  } else if (*kind == 'r' && fcn) {
1702  RzRegItem *i = rz_reg_get(analysis->reg, extra, -1);
1703  if (!i) {
1704  goto loop_end;
1705  }
1706  rz_analysis_function_set_var(fcn, i->index, *kind, ttype, 4, false, var_name);
1707  } else if (fcn) { /* kind == 'b' */
1708  rz_analysis_function_set_var(fcn, offset - fcn->bp_off, *kind, ttype, 4, false, var_name);
1709  }
1710  rz_type_free(ttype);
1711  free(var_key);
1712  free(var_data);
1713  loop_end:
1714  sdb_aforeach_next(var_name);
1715  }
1716  free(var_names_key);
1717  free(vars);
1718  }
1719  ls_free(sdb_list);
1720 }
RZ_API RzAnalysisFunction * rz_analysis_get_function_at(RzAnalysis *analysis, ut64 addr)
Definition: function.c:184
RZ_API bool rz_analysis_function_rename(RzAnalysisFunction *fcn, const char *name)
Definition: function.c:240
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
RZ_API void rz_type_base_type_free(RzBaseType *type)
Frees the RzBaseType instance and all of its members.
Definition: base.c:132
RZ_API void rz_type_base_enum_case_free(void *e, void *user)
Definition: base.c:8
RZ_API RZ_OWN RzBaseType * rz_type_base_type_new(RzBaseTypeKind kind)
Allocates a new instance of RzBaseType given the kind.
Definition: base.c:162
RZ_API void rz_type_db_save_base_type(const RzTypeDB *typedb, const RzBaseType *type)
Saves RzBaseType into the Types DB.
Definition: base.c:191
static SblHeader sb
Definition: bin_mbn.c:26
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
int bits(struct state *s, int need)
Definition: blast.c:72
RZ_API RZ_OWN RzType * rz_type_parse_string_single(RzTypeParser *parser, const char *code, char **error_msg)
Parses the single C type definition.
Definition: c_cpp_parser.c:309
#define CHAR_BIT
Definition: readbits.h:99
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
cs_arch arch
Definition: cstool.c:13
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 static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
#define ut8
Definition: dcpu16.h:8
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
static void parse_typedef(Context *ctx, ut64 idx)
Parses a typedef entry into RzBaseType and saves it using rz_analysis_save_base_type ()
static bool strbuf_rev_append_char(RzStrBuf *sb, const char *s, const char *needle)
Pasted from rz_strbuf_* Appends string after a first occurence of character c Used to replicate prope...
static st32 find_attr_idx(const RzBinDwarfDie *die, st32 attr_name)
Definition: dwarf_process.c:63
static st32 parse_function_args_and_vars(Context *ctx, ut64 idx, RzStrBuf *args, RzList *variables)
static RzTypeStructMember * parse_struct_member(Context *ctx, ut64 idx, RzTypeStructMember *result)
Parses structured entry into *result RzTypeStructMember http://www.dwarfstd.org/doc/DWARF4....
static void sdb_save_dwarf_function(Function *dwarf_fcn, RzList *variables, Sdb *sdb)
static const char * map_dwarf_reg_to_x86_reg(ut64 reg_num, VariableLocationKind *kind)
static void variable_free(Variable *var)
Definition: dwarf_process.c:55
enum dwarf_location_kind VariableLocationKind
static VariableLocation * parse_dwarf_location(Context *ctx, const RzBinDwarfAttrValue *loc, const RzBinDwarfAttrValue *frame_base)
static bool strbuf_rev_prepend_char(RzStrBuf *sb, const char *s, int c)
Pasted from rz_strbuf_* Prepends string before a last occurence of character c Used to replicate prop...
Definition: dwarf_process.c:94
static st32 parse_type_outer(Context *ctx, const ut64 offset, RzStrBuf *strbuf, ut64 *size)
Convenience function for calling parse_type with an empty visited set See documentation of parse_type...
static void parse_structure_type(Context *ctx, ut64 idx)
Parses a structured entry (structs, classes, unions) into RzBaseType and saves it using rz_analysis_s...
static st32 parse_array_type(Context *ctx, ut64 idx, RzStrBuf *strbuf)
Parses array type entry signature into strbuf.
struct dwarf_function_t Function
static RzBinDwarfLocRange * find_largest_loc_range(RzList *loc_list)
struct dwarf_parse_context_t Context
struct dwarf_variable_t Variable
static bool prefer_linkage_name(char *lang)
dwarf_location_kind
Definition: dwarf_process.c:34
@ LOCATION_SP
Definition: dwarf_process.c:38
@ LOCATION_UNKNOWN
Definition: dwarf_process.c:35
@ LOCATION_GLOBAL
Definition: dwarf_process.c:36
@ LOCATION_BP
Definition: dwarf_process.c:37
@ LOCATION_REGISTER
Definition: dwarf_process.c:39
static void parse_enum_type(Context *ctx, ut64 idx)
Parses a enum entry into RzBaseType and saves it int Sdb using rz_analysis_save_base_type ()
static char * create_type_name_from_offset(ut64 offset)
static char * parse_comp_unit_lang(const RzBinDwarfDie *die)
Get's language from comp unit for demangling.
static const char * map_dwarf_reg_to_x86_64_reg(ut64 reg_num, VariableLocationKind *kind)
static void parse_abstract_origin(Context *ctx, ut64 offset, RzStrBuf *type, const char **name)
static char * get_die_name(const RzBinDwarfDie *die)
Get the DIE name or create unique one from its offset.
RZ_API void rz_analysis_dwarf_process_info(const RzAnalysis *analysis, RzAnalysisDwarfContext *ctx)
Parses type and function information out of DWARF entries and stores them to the sdb for further use.
static const char * get_dwarf_reg_name(RZ_NONNULL char *arch, int reg_num, VariableLocationKind *kind, int bits)
struct dwarf_var_location_t VariableLocation
static void get_spec_die_type(Context *ctx, RzBinDwarfDie *die, RzStrBuf *ret_type)
bool filter_sdb_function_names(void *user, const char *k, const char *v)
static RzBinDwarfAttrValue * find_attr(const RzBinDwarfDie *die, st32 attr_name)
Definition: dwarf_process.c:75
RZ_API void rz_analysis_dwarf_integrate_functions(RzAnalysis *analysis, RzFlag *flags, Sdb *dwarf_sdb)
Use parsed DWARF function info from Sdb in the function analysis XXX right now we only save parsed na...
static const char * map_dwarf_reg_to_ppc64_reg(ut64 reg_num, VariableLocationKind *kind)
static void parse_function(Context *ctx, ut64 idx)
Parse function,it's arguments, variables and save the information into the Sdb.
static const char * get_specification_die_name(const RzBinDwarfDie *die)
static void parse_atomic_type(Context *ctx, ut64 idx)
static ut64 get_die_size(const RzBinDwarfDie *die)
Get the DIE size in bits.
static void parse_type_entry(Context *ctx, ut64 idx)
Delegates DIE to it's proper parsing method.
static st32 parse_type(Context *ctx, const ut64 offset, RzStrBuf *strbuf, ut64 *size, RZ_NONNULL SetU *visited)
Recursively parses type entry of a certain offset into strbuf saves type size into *size.
static RzTypeEnumCase * parse_enumerator(Context *ctx, ut64 idx, RzTypeEnumCase *result)
Parses enum entry into *result RzTypeEnumCase http://www.dwarfstd.org/doc/DWARF4.pdf#page=110&zoom=10...
void cleanup(void)
Definition: enough.c:244
RZ_API RzFlagItem * rz_flag_set_next(RzFlag *f, const char *name, ut64 off, ut32 size)
Definition: flag.c:494
RZ_API bool rz_flag_unset_off(RzFlag *f, ut64 off)
Definition: flag.c:608
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
uint8_t ut8
Definition: lh5801.h:11
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
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 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
void * malloc(size_t size)
Definition: malloc.c:123
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 void ls_free(SdbList *list)
Definition: ls.c:191
#define ls_foreach(list, it, pos)
Definition: ls.h:31
RZ_API bool rz_meta_set_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, const char *s)
Definition: meta.c:141
int args
Definition: mipsasm.c:18
int type
Definition: mipsasm.c:17
int idx
Definition: setup.py:197
RZ_API Sdb * sdb_ns(Sdb *s, const char *name, int create)
Definition: ns.c:186
RZ_API ut64 sdb_num_get(Sdb *s, const char *key, ut32 *cas)
Definition: num.c:13
const char * name
Definition: op.c:541
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
static RzSocket * s
Definition: rtr.c:28
@ RZ_META_TYPE_COMMENT
Definition: rz_analysis.h:295
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_warn_if_fail(expr)
Definition: rz_assert.h:35
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define DW_AT_high_pc
Definition: rz_bin_dwarf.h:142
#define DW_OP_reg31
Definition: rz_bin_dwarf.h:428
#define DW_AT_trampoline
Definition: rz_bin_dwarf.h:200
#define DW_OP_breg11
Definition: rz_bin_dwarf.h:440
#define DW_TAG_variable
Definition: rz_bin_dwarf.h:107
#define DW_AT_specification
Definition: rz_bin_dwarf.h:185
#define DW_LANG_Rust
Definition: rz_bin_dwarf.h:549
#define DW_OP_reg7
Definition: rz_bin_dwarf.h:404
#define DW_OP_reg1
Definition: rz_bin_dwarf.h:398
#define DW_LANG_C89
Definition: rz_bin_dwarf.h:529
#define DW_OP_reg6
Definition: rz_bin_dwarf.h:403
#define DW_AT_count
Definition: rz_bin_dwarf.h:169
#define DW_OP_reg27
Definition: rz_bin_dwarf.h:424
#define DW_TAG_subrange_type
Definition: rz_bin_dwarf.h:81
#define DW_OP_reg26
Definition: rz_bin_dwarf.h:423
#define DW_OP_reg16
Definition: rz_bin_dwarf.h:413
#define DW_LANG_Swift
Definition: rz_bin_dwarf.h:551
#define DW_LANG_Julia
Definition: rz_bin_dwarf.h:552
#define DW_OP_reg11
Definition: rz_bin_dwarf.h:408
#define DW_TAG_subprogram
Definition: rz_bin_dwarf.h:97
#define DW_OP_breg25
Definition: rz_bin_dwarf.h:454
#define DW_OP_reg28
Definition: rz_bin_dwarf.h:425
#define DW_AT_encoding
Definition: rz_bin_dwarf.h:176
#define DW_OP_breg30
Definition: rz_bin_dwarf.h:459
#define DW_TAG_volatile_type
Definition: rz_bin_dwarf.h:108
#define DW_AT_data_member_location
Definition: rz_bin_dwarf.h:170
#define DW_LANG_ObjC
Definition: rz_bin_dwarf.h:544
#define DW_AT_language
Definition: rz_bin_dwarf.h:143
#define DW_OP_reg5
Definition: rz_bin_dwarf.h:402
#define DW_OP_reg30
Definition: rz_bin_dwarf.h:427
#define DW_OP_breg6
Definition: rz_bin_dwarf.h:435
#define DW_OP_breg7
Definition: rz_bin_dwarf.h:436
#define DW_OP_breg23
Definition: rz_bin_dwarf.h:452
#define DW_OP_reg0
Definition: rz_bin_dwarf.h:397
#define DW_AT_virtuality
Definition: rz_bin_dwarf.h:190
#define DW_TAG_formal_parameter
Definition: rz_bin_dwarf.h:59
#define DW_LANG_Java
Definition: rz_bin_dwarf.h:539
@ DW_AT_KIND_STRING
Definition: rz_bin_dwarf.h:698
@ DW_AT_KIND_REFERENCE
Definition: rz_bin_dwarf.h:697
@ DW_AT_KIND_BLOCK
Definition: rz_bin_dwarf.h:689
@ DW_AT_KIND_CONSTANT
Definition: rz_bin_dwarf.h:690
@ DW_AT_KIND_ADDRESS
Definition: rz_bin_dwarf.h:688
@ DW_AT_KIND_LOCLISTPTR
Definition: rz_bin_dwarf.h:694
#define DW_TAG_class_type
Definition: rz_bin_dwarf.h:56
#define DW_OP_reg29
Definition: rz_bin_dwarf.h:426
#define DW_LANG_Dylan
Definition: rz_bin_dwarf.h:553
#define DW_OP_breg5
Definition: rz_bin_dwarf.h:434
#define DW_OP_reg13
Definition: rz_bin_dwarf.h:410
#define DW_AT_name
Definition: rz_bin_dwarf.h:135
#define DW_LANG_Modula2
Definition: rz_bin_dwarf.h:538
#define DW_OP_reg4
Definition: rz_bin_dwarf.h:401
#define DW_OP_addr
Definition: rz_bin_dwarf.h:323
#define DW_TAG_typedef
Definition: rz_bin_dwarf.h:70
#define DW_OP_reg23
Definition: rz_bin_dwarf.h:420
#define DW_OP_reg20
Definition: rz_bin_dwarf.h:417
#define DW_OP_breg14
Definition: rz_bin_dwarf.h:443
#define DW_OP_reg18
Definition: rz_bin_dwarf.h:415
#define DW_LANG_PLI
Definition: rz_bin_dwarf.h:543
#define DW_TAG_structure_type
Definition: rz_bin_dwarf.h:68
static const char * rz_bin_dwarf_attr_value_get_string_content(const RzBinDwarfAttrValue *val)
Safely get the string content from an RzBinDwarfAttrValue if it has one.
Definition: rz_bin_dwarf.h:725
#define DW_LANG_Python
Definition: rz_bin_dwarf.h:548
#define DW_LANG_C_plus_plus
Definition: rz_bin_dwarf.h:532
#define DW_OP_fbreg
Definition: rz_bin_dwarf.h:462
#define DW_OP_breg9
Definition: rz_bin_dwarf.h:438
#define DW_LANG_Cobol85
Definition: rz_bin_dwarf.h:534
#define DW_AT_location
Definition: rz_bin_dwarf.h:134
#define DW_AT_upper_bound
Definition: rz_bin_dwarf.h:162
#define DW_TAG_array_type
Definition: rz_bin_dwarf.h:55
#define DW_OP_breg1
Definition: rz_bin_dwarf.h:430
#define DW_AT_accessibility
Definition: rz_bin_dwarf.h:164
#define DW_OP_breg0
Definition: rz_bin_dwarf.h:429
#define DW_AT_data_bit_offset
Definition: rz_bin_dwarf.h:221
#define DW_LANG_C
Definition: rz_bin_dwarf.h:530
#define DW_OP_breg16
Definition: rz_bin_dwarf.h:445
#define DW_TAG_pointer_type
Definition: rz_bin_dwarf.h:64
#define DW_OP_breg22
Definition: rz_bin_dwarf.h:451
#define DW_AT_mutable
Definition: rz_bin_dwarf.h:211
#define DW_OP_breg17
Definition: rz_bin_dwarf.h:446
#define DW_OP_reg22
Definition: rz_bin_dwarf.h:419
#define DW_AT_vtable_elem_location
Definition: rz_bin_dwarf.h:191
#define DW_OP_breg20
Definition: rz_bin_dwarf.h:449
#define DW_AT_MIPS_linkage_name
Definition: rz_bin_dwarf.h:260
#define DW_LANG_Fortran03
Definition: rz_bin_dwarf.h:555
#define DW_OP_reg8
Definition: rz_bin_dwarf.h:405
#define DW_AT_abstract_origin
Definition: rz_bin_dwarf.h:163
#define DW_OP_breg3
Definition: rz_bin_dwarf.h:432
#define DW_AT_containing_type
Definition: rz_bin_dwarf.h:152
#define DW_OP_breg8
Definition: rz_bin_dwarf.h:437
#define DW_AT_bit_size
Definition: rz_bin_dwarf.h:139
#define DW_TAG_subroutine_type
Definition: rz_bin_dwarf.h:69
#define DW_OP_reg2
Definition: rz_bin_dwarf.h:399
#define DW_TAG_const_type
Definition: rz_bin_dwarf.h:86
#define DW_OP_reg3
Definition: rz_bin_dwarf.h:400
#define DW_LANG_C_plus_plus_14
Definition: rz_bin_dwarf.h:554
#define DW_AT_declaration
Definition: rz_bin_dwarf.h:174
#define DW_TAG_compile_unit
Definition: rz_bin_dwarf.h:66
#define DW_AT_entry_pc
Definition: rz_bin_dwarf.h:196
#define DW_OP_reg14
Definition: rz_bin_dwarf.h:411
#define DW_LANG_C99
Definition: rz_bin_dwarf.h:540
#define DW_OP_reg9
Definition: rz_bin_dwarf.h:406
#define DW_OP_reg15
Definition: rz_bin_dwarf.h:412
#define DW_LANG_Fortran08
Definition: rz_bin_dwarf.h:556
#define DW_OP_breg13
Definition: rz_bin_dwarf.h:442
#define DW_AT_byte_size
Definition: rz_bin_dwarf.h:137
#define DW_TAG_unspecified_parameters
Definition: rz_bin_dwarf.h:72
#define DW_LANG_ObjC_plus_plus
Definition: rz_bin_dwarf.h:545
#define DW_OP_breg15
Definition: rz_bin_dwarf.h:444
#define DW_LANG_Pascal83
Definition: rz_bin_dwarf.h:537
#define DW_AT_external
Definition: rz_bin_dwarf.h:177
#define DW_OP_breg4
Definition: rz_bin_dwarf.h:433
#define DW_OP_reg19
Definition: rz_bin_dwarf.h:416
#define DW_OP_reg21
Definition: rz_bin_dwarf.h:418
#define DW_TAG_base_type
Definition: rz_bin_dwarf.h:84
#define DW_TAG_member
Definition: rz_bin_dwarf.h:63
#define DW_TAG_restrict_type
Definition: rz_bin_dwarf.h:110
#define DW_LANG_Fortran77
Definition: rz_bin_dwarf.h:535
#define DW_OP_breg28
Definition: rz_bin_dwarf.h:457
#define DW_OP_call_frame_cfa
Definition: rz_bin_dwarf.h:473
#define DW_OP_breg29
Definition: rz_bin_dwarf.h:458
#define DW_LANG_Ada95
Definition: rz_bin_dwarf.h:541
#define DW_AT_frame_base
Definition: rz_bin_dwarf.h:178
#define DW_OP_breg19
Definition: rz_bin_dwarf.h:448
#define DW_AT_ranges
Definition: rz_bin_dwarf.h:199
#define DW_OP_reg17
Definition: rz_bin_dwarf.h:414
#define DW_LANG_D
Definition: rz_bin_dwarf.h:547
#define DW_AT_const_value
Definition: rz_bin_dwarf.h:151
#define DW_OP_reg10
Definition: rz_bin_dwarf.h:407
#define DW_TAG_enumeration_type
Definition: rz_bin_dwarf.h:58
#define DW_TAG_rvalue_reference_type
Definition: rz_bin_dwarf.h:122
#define DW_OP_breg31
Definition: rz_bin_dwarf.h:460
#define DW_OP_reg24
Definition: rz_bin_dwarf.h:421
#define DW_TAG_enumerator
Definition: rz_bin_dwarf.h:88
#define DW_AT_object_pointer
Definition: rz_bin_dwarf.h:214
#define DW_TAG_reference_type
Definition: rz_bin_dwarf.h:65
#define DW_LANG_Cobol74
Definition: rz_bin_dwarf.h:533
#define DW_TAG_union_type
Definition: rz_bin_dwarf.h:71
#define DW_LANG_Fortran95
Definition: rz_bin_dwarf.h:542
#define DW_LANG_Ada83
Definition: rz_bin_dwarf.h:531
#define DW_OP_breg27
Definition: rz_bin_dwarf.h:456
#define DW_OP_breg21
Definition: rz_bin_dwarf.h:450
#define DW_AT_linkage_name
Definition: rz_bin_dwarf.h:224
#define DW_OP_breg12
Definition: rz_bin_dwarf.h:441
#define DW_AT_low_pc
Definition: rz_bin_dwarf.h:141
#define DW_LANG_C11
Definition: rz_bin_dwarf.h:550
#define DW_AT_type
Definition: rz_bin_dwarf.h:187
#define DW_OP_breg10
Definition: rz_bin_dwarf.h:439
#define DW_OP_reg12
Definition: rz_bin_dwarf.h:409
#define DW_OP_reg25
Definition: rz_bin_dwarf.h:422
#define DW_OP_breg2
Definition: rz_bin_dwarf.h:431
#define DW_LANG_Fortran90
Definition: rz_bin_dwarf.h:536
#define DW_OP_breg26
Definition: rz_bin_dwarf.h:455
#define DW_LANG_UPC
Definition: rz_bin_dwarf.h:546
#define DW_OP_breg18
Definition: rz_bin_dwarf.h:447
#define DW_OP_bregx
Definition: rz_bin_dwarf.h:463
#define DW_OP_breg24
Definition: rz_bin_dwarf.h:453
static ut64 rz_read_ble64(const void *src, bool big_endian)
Definition: rz_endian.h:501
static ut8 rz_read_ble8(const void *src)
Definition: rz_endian.h:12
static ut32 rz_read_ble32(const void *src, bool big_endian)
Definition: rz_endian.h:497
static ut16 rz_read_ble16(const void *src, bool big_endian)
Definition: rz_endian.h:493
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_sanitize_sdb_key(const char *s)
Definition: str.c:1405
#define RZ_STR_DUP(x)
Definition: rz_str.h:69
RZ_API RZ_OWN char * rz_strbuf_drain_nofree(RzStrBuf *sb)
Definition: strbuf.c:349
RZ_API const char * rz_strbuf_set(RzStrBuf *sb, const char *s)
Definition: strbuf.c:153
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
RZ_API bool rz_strbuf_slice(RZ_NONNULL RzStrBuf *sb, size_t from, size_t len)
Cuts the current string into a substring.
Definition: strbuf.c:122
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
Definition: strbuf.c:365
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
RzBaseTypeKind
Definition: rz_type.h:72
@ RZ_BASE_TYPE_KIND_TYPEDEF
Definition: rz_type.h:76
@ RZ_BASE_TYPE_KIND_ATOMIC
Definition: rz_type.h:77
@ RZ_BASE_TYPE_KIND_UNION
Definition: rz_type.h:74
@ RZ_BASE_TYPE_KIND_STRUCT
Definition: rz_type.h:73
@ RZ_BASE_TYPE_KIND_ENUM
Definition: rz_type.h:75
#define PFMT64d
Definition: rz_types.h:394
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
#define PFMT64u
Definition: rz_types.h:395
#define PFMT64x
Definition: rz_types.h:393
#define st64
Definition: rz_types_base.h:10
#define st32
Definition: rz_types_base.h:12
RZ_API const ut8 * rz_uleb128(const ut8 *data, int datalen, RZ_NULLABLE ut64 *v, const char **error)
Definition: uleb128.c:9
RZ_API st64 rz_sleb128(const ut8 **data, const ut8 *end)
Definition: uleb128.c:145
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
RZ_API char * sdb_get(Sdb *s, const char *key, ut32 *cas)
Definition: sdb.c:290
RZ_API SdbList * sdb_foreach_list_filter(Sdb *s, SdbForeachCallback filter, bool sorted)
Definition: sdb.c:685
RZ_API char * sdb_anext(char *str, char **next)
Definition: util.c:192
#define sdb_aforeach_next(x)
Definition: sdb.h:348
#define sdb_aforeach(x, y)
Definition: sdb.h:342
RZ_API SetU * set_u_new(void)
Definition: set.c:30
RZ_API void set_u_free(SetU *s)
Definition: set.c:46
RZ_API void set_u_delete(SetU *s, ut64 u)
Definition: set.c:42
RZ_API void set_u_add(SetU *s, ut64 u)
Definition: set.c:34
RZ_API bool set_u_contains(SetU *s, ut64 u)
Definition: set.c:38
HtUP SetU
Definition: set.h:22
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
static int
Definition: sfsocketcall.h:114
#define c(i)
Definition: sha256.c:43
RzBinDwarfDie * dies
Definition: rz_bin_dwarf.h:764
RzBinDwarfAttrValue * attr_values
Definition: rz_bin_dwarf.h:756
size_t len
Definition: rz_strbuf.h:12
Definition: buffer.h:15
RzBinDwarfBlock block
Definition: rz_bin_dwarf.h:710
RzBinDwarfAttrKind kind
Definition: rz_bin_dwarf.h:704
const char * name
Definition: dwarf_process.c:23
const char * signature
Definition: dwarf_process.c:24
const RzBinDwarfDie * all_dies
Definition: dwarf_process.c:13
const RzAnalysis * analysis
Definition: dwarf_process.c:12
const char * reg_name
Definition: dwarf_process.c:46
VariableLocationKind kind
Definition: dwarf_process.c:42
VariableLocation * location
Definition: dwarf_process.c:50
Definition: ls.h:17
Definition: ls.h:22
Definition: z80asm.h:102
RzTypeDB * typedb
Definition: rz_analysis.h:602
RzVector cases
Definition: rz_type.h:108
RzBaseTypeStruct struct_data
Definition: rz_type.h:118
char * name
Definition: rz_type.h:112
RzType * type
Definition: rz_type.h:113
RzBaseTypeEnum enum_data
Definition: rz_type.h:119
Definition: rz_bin_dwarf.h:912
RzTypeParser * parser
Definition: rz_type.h:37
Definition: sdbht.h:14
HtPPKv base
Definition: sdbht.h:16
Definition: sdb.h:63
RZ_API void rz_type_free(RZ_NULLABLE RzType *type)
Frees the RzType.
Definition: type.c:1273
RZ_API RZ_BORROW RzAnalysisVar * rz_analysis_function_set_var(RzAnalysisFunction *fcn, int delta, char kind, RZ_BORROW RZ_NULLABLE const RzType *type, int size, bool isarg, RZ_NONNULL const char *name)
Definition: var.c:111
ut64(WINAPI *w32_GetEnabledXStateFeatures)()