Rizin
unix-like reverse engineering framework and cli tools
type_pdb.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2020 HoundThe <cgkajm@gmail.com>
2 // SPDX-FileCopyrightText: 2021 Basstorm <basstorm@nyist.edu.cn>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_bin.h>
6 #include <rz_core.h>
7 #include <rz_type.h>
8 #include <rz_pdb.h>
9 #include <rz_analysis.h>
10 #include "../bin/pdb/pdb.h"
11 
12 static RzType *parse_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name);
18 static void parse_type_arglist(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *arglist, RzPVector *vec);
19 static RzType *parse_type_mfunction(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name);
20 static RzType *parse_type_onemethod(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info);
21 static RzType *parse_type_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name);
22 static RzType *parse_type_nest(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info);
29 
30 static bool is_parsable_type(const TpiLeafType type) {
32  return (type == LF_STRUCTURE ||
33  type == LF_UNION ||
34  type == LF_ENUM ||
35  type == LF_CLASS ||
36  type == LF_CLASS_19 ||
38 }
39 
47  int offset_length = snprintf(NULL, 0, "type_0x%" PFMT64x, offset);
48  char *str = malloc(offset_length + 1);
49  snprintf(str, offset_length + 1, "type_0x%" PFMT64x, offset);
50  return str;
51 }
52 
54  rz_return_val_if_fail(type && stream && typedb, NULL);
55  Tpi_LF_Array *lf_array = type->type_data;
57  if (!element) {
58  return NULL;
59  }
60  RzType *element_type = parse_type(typedb, stream, element, NULL);
61  if (!element_type) {
62  return NULL;
63  }
64  RzType *typ = RZ_NEW0(RzType);
65  if (!typ) {
66  return NULL;
67  }
68  typ->kind = RZ_TYPE_KIND_ARRAY;
69  typ->array.type = element_type;
70  typ->array.count = rz_bin_pdb_get_type_val(type);
71  return typ;
72 }
73 
75  rz_return_val_if_fail(type && stream && typedb, NULL);
76  switch (type->leaf_type) {
77  case LF_CLASS:
78  case LF_CLASS_19:
79  // TODO: https://github.com/rizinorg/rizin/issues/1205
80  RZ_LOG_INFO("%s : LF_CLASS is not handled for now.\n", __FUNCTION__);
81  break;
82  case LF_STRUCTURE:
83  case LF_STRUCTURE_19:
84  return parse_structure(typedb, stream, type);
85  case LF_MODIFIER:
86  return parse_type_modifier(typedb, stream, type);
87  case LF_ARRAY:
88  return parse_type_array(typedb, stream, type);
89  case LF_BITFIELD:
90  // TODO: we don't have BITFIELD type for now https://github.com/rizinorg/rizin/issues/1240
91  RZ_LOG_INFO("%s : LF_BITFIELD is not handled for now.\n", __FUNCTION__);
92  break;
93  case LF_POINTER:
94  return parse_type_pointer(typedb, stream, type, name);
95  case LF_PROCEDURE:
96  return parse_type_procedure(typedb, stream, type, name);
97  case LF_UNION:
98  return parse_union(typedb, stream, type);
99  case LF_ENUM:
100  return parse_enum(typedb, stream, type);
101  default:
102  RZ_LOG_INFO("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type->leaf_type);
103  break;
104  }
105  return NULL;
106 }
107 
109  rz_return_val_if_fail(type && stream && typedb, NULL);
110  Tpi_LF_Modifier *lf_modifier = type->type_data;
112  if (m_utype) {
113  RzType *typ = parse_type(typedb, stream, m_utype, NULL);
114  if (typ && lf_modifier->umodifier.bits.const_) {
115  switch (typ->kind) {
117  typ->identifier.is_const = true;
118  break;
120  typ->pointer.is_const = true;
121  break;
122  default:
123  break;
124  }
125  }
126  return typ;
127  }
128  return NULL;
129 }
130 
132  rz_return_val_if_fail(type && typedb, NULL);
133  Tpi_LF_Pointer *lf_pointer = type->type_data;
134  RzType *typ = RZ_NEW0(RzType);
135  if (!typ) {
136  goto error;
137  }
138  typ->kind = RZ_TYPE_KIND_POINTER;
139  RzPdbTpiType *p_utype = rz_bin_pdb_get_type_by_index(stream, lf_pointer->utype);
140  if (p_utype) {
141  RzType *tmp = parse_type(typedb, stream, p_utype, name);
142  if (!tmp) {
143  goto error;
144  }
145  typ->pointer.type = tmp;
146  return typ;
147  }
148 error:
149  rz_type_free(typ);
150  return NULL;
151 }
152 
154  rz_return_val_if_fail(type && typedb, NULL);
155  RzType *typ;
156  if (type->leaf_type == LF_SIMPLE_TYPE) {
157  Tpi_LF_SimpleType *simple_type = type->type_data;
158  char *error_msg = NULL;
159  typ = rz_type_parse_string_single(typedb->parser, simple_type->type, &error_msg);
160  if (error_msg) {
161  RZ_LOG_ERROR("%s : Error parsing complex type member \"%s\" type:\n%s\n", __FUNCTION__, simple_type->type, error_msg);
162  RZ_FREE(error_msg);
163  }
164  return typ;
165  } else {
166  if (type->leaf_type == LF_POINTER) {
167  return parse_type_pointer(typedb, stream, type, name);
168  } else {
169  return parse_regular_type(typedb, stream, type, name);
170  }
171  }
172 }
173 
174 static void parse_type_arglist(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *arglist, RzPVector *vec) {
175  rz_return_if_fail(arglist && typedb && vec);
176  Tpi_LF_Arglist *lf_arglist = arglist->type_data;
177  if (!vec) {
178  return;
179  }
180  ut32 *ptr_types = lf_arglist->arg_type;
181  for (int i = 0; i < lf_arglist->count; i++) {
182  RzPdbTpiType *stype = rz_bin_pdb_get_type_by_index(stream, *ptr_types++);
183  if (!stype) {
184  continue;
185  }
186  RzType *type = parse_type(typedb, stream, stype, NULL);
187  if (!type) {
188  continue;
189  }
191  arg->name = rz_str_newf("arg%d", i);
192  arg->type = type;
193  rz_pvector_push(vec, arg);
194  }
195 }
196 
198  rz_return_val_if_fail(type && stream && typedb, NULL);
199  Tpi_LF_Procedure *lf_procedure = type->type_data;
200  RzType *typ = RZ_NEW0(RzType);
201  RzCallable *callable = RZ_NEW0(RzCallable);
202  if (!typ || !callable) {
203  free(typ);
204  free(callable);
205  return NULL;
206  }
208  typ->callable = callable;
209  if (!name) {
210  typ->callable->name = create_type_name_from_offset(type->type_index);
211  } else {
212  typ->callable->name = strdup(name);
213  }
214 
216  // parse return type
217  RzPdbTpiType *ret_type = rz_bin_pdb_get_type_by_index(stream, lf_procedure->return_type);
218  if (ret_type) {
219  typ->callable->ret = parse_type(typedb, stream, ret_type, name);
220  if (!typ->callable->ret) {
221  typ->callable->noret = true;
222  }
223  }
224  // parse parameter list
226  if (!typ->callable->args) {
227  rz_type_free(typ);
228  return NULL;
229  }
230  RzPdbTpiType *arglist = rz_bin_pdb_get_type_by_index(stream, lf_procedure->arg_list);
231  if (arglist) {
232  parse_type_arglist(typedb, stream, arglist, typ->callable->args);
233  }
234  rz_type_func_save((RzTypeDB *)typedb, callable);
235  return typ;
236 }
237 
238 static RzType *parse_type_mfunction(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
239  rz_return_val_if_fail(type_info && stream && typedb, NULL);
240  Tpi_LF_MFcuntion *lf_mfunction = type_info->type_data;
242  RzCallable *callable = RZ_NEW0(RzCallable);
243  if (!type || !callable) {
244  free(type);
245  free(callable);
246  return NULL;
247  }
248  type->kind = RZ_TYPE_KIND_CALLABLE;
249  type->callable = callable;
250  type->callable->name = strdup(name);
251  type->callable->cc = rz_bin_pdb_calling_convention_as_string(lf_mfunction->call_conv);
252  // parse return type
253  RzPdbTpiType *ret_type = rz_bin_pdb_get_type_by_index(stream, lf_mfunction->return_type);
254  if (ret_type) {
255  type->callable->ret = parse_type(typedb, stream, ret_type, name);
256  if (!type->callable->ret) {
257  type->callable->noret = true;
258  }
259  }
260  // parse parameter list
262  if (!type->callable->args) {
264  return NULL;
265  }
266  RzPdbTpiType *arglist = rz_bin_pdb_get_type_by_index(stream, lf_mfunction->arglist);
267  if (arglist) {
268  parse_type_arglist(typedb, stream, arglist, type->callable->args);
269  }
270  rz_type_func_save((RzTypeDB *)typedb, callable);
271  return type;
272 }
273 
275  rz_return_val_if_fail(type_info && typedb, NULL);
276  Tpi_LF_OneMethod *lf_onemethod = type_info->type_data;
277  char *name = rz_bin_pdb_get_type_name(type_info);
278  RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_onemethod->index);
279  if (!utype) {
280  return NULL;
281  }
282  if (utype->leaf_type == LF_MFUNCTION) {
283  return parse_type_mfunction(typedb, stream, utype, name);
284  }
285  return NULL;
286 }
287 
288 static RzType *parse_type_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
289  rz_return_val_if_fail(type_info && typedb, NULL);
290  Tpi_LF_Member *lf_member = type_info->type_data;
291 
293  if (!utype) {
294  return NULL;
295  }
296  return parse_type(typedb, stream, utype, name);
297 }
298 
299 static RzType *parse_type_static_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
300  rz_return_val_if_fail(type_info && typedb, NULL);
301  Tpi_LF_StaticMember *lf_stmember = type_info->type_data;
302  RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_stmember->index);
303  if (!utype) {
304  return NULL;
305  }
306  return parse_type(typedb, stream, utype, name);
307 }
308 
309 static RzType *parse_type_nest(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) {
310  rz_return_val_if_fail(type_info && stream && typedb, NULL);
311  Tpi_LF_NestType *lf_nest = type_info->type_data;
313  if (!utype) {
314  return NULL;
315  }
316  char *name = rz_bin_pdb_get_type_name(utype);
317  if (name) {
318  RzBaseType *b_type = rz_type_db_get_base_type(typedb, name);
319  if (b_type && b_type->type) {
320  if (b_type->type->kind == RZ_TYPE_KIND_IDENTIFIER) {
321  return rz_type_clone(b_type->type);
322  }
323  }
324  return NULL;
325  }
326 
327  RzType *n_type = parse_type(typedb, stream, utype, NULL);
328  if (!n_type) {
329  return NULL;
330  }
332  if (!btype) {
333  return NULL;
334  }
335  btype->name = name ? strdup(name) : create_type_name_from_offset(lf_nest->index);
336  btype->type = n_type;
337  rz_type_db_save_base_type(typedb, btype);
338  if (n_type->kind == RZ_TYPE_KIND_IDENTIFIER) {
339  return rz_type_clone(n_type);
340  }
341  return NULL;
342 }
343 
353  rz_return_val_if_fail(type_info, NULL);
354  char *name = NULL;
355  ut64 offset = 0;
356  RzType *type = NULL;
357  switch (type_info->leaf_type) {
358  case LF_ONEMETHOD: {
359  name = rz_bin_pdb_get_type_name(type_info);
360  type = parse_type_onemethod(typedb, stream, type_info);
361  break;
362  }
363  case LF_MEMBER: {
364  offset = rz_bin_pdb_get_type_val(type_info);
365  name = rz_bin_pdb_get_type_name(type_info);
366  type = parse_type_member(typedb, stream, type_info, name);
367  break;
368  }
369  case LF_STMEMBER: {
370  name = rz_bin_pdb_get_type_name(type_info);
371  type = parse_type_static_member(typedb, stream, type_info, name);
372  break;
373  }
374  case LF_NESTTYPE: {
375  name = rz_bin_pdb_get_type_name(type_info);
376  type = parse_type_nest(typedb, stream, type_info);
377  break;
378  }
379  case LF_BCLASS:
380  // For structure, we don't need base class for now
381  goto cleanup;
382  case LF_METHOD:
383  // TODO: need to handle overloaded methods here
384  goto cleanup;
385  case LF_VFUNCTAB:
386  // For structure, we don't need vtable for now
387  goto cleanup;
388  default:
389  RZ_LOG_ERROR("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type_info->leaf_type);
390  goto cleanup;
391  }
392  if (!type) {
393  RZ_LOG_INFO("%s : couldn't parse structure member type!\n", __FUNCTION__);
394  return NULL;
395  }
396 
398  if (!member) {
399  goto cleanup;
400  }
401  member->name = strdup(name);
402  member->type = type;
403  member->offset = offset;
404  return member;
405 cleanup:
407  return NULL;
408 }
409 
410 static inline bool is_tpitype_unnamed(const char *name) {
411  return !name || !strcmp(name, "<unnamed-tag>") || !strcmp(name, "<anonymous-tag>");
412 }
413 
414 static inline RzBaseType *get_tpitype_basetype(const RzTypeDB *typedb, RzPdbTpiType *type, const char *name) {
415  RzBaseType *base_type;
416  if (is_tpitype_unnamed(name)) {
417  char *tmp_name = create_type_name_from_offset(type->type_index);
418  base_type = rz_type_db_get_base_type(typedb, tmp_name);
419  free(tmp_name);
420  } else {
421  base_type = rz_type_db_get_base_type(typedb, name);
422  }
423  return base_type;
424 }
425 
427  RzType *t = RZ_NEW0(RzType);
428  if (!t) {
429  return NULL;
430  }
432  t->identifier.kind = kind;
434  return t;
435 }
436 
445  rz_return_val_if_fail(typedb && stream && type, NULL);
446 
447  RzBaseType *base_type = NULL;
449  if (name) {
450  base_type = get_tpitype_basetype(typedb, type, name);
451  if (base_type) {
452  if (base_type->kind != RZ_BASE_TYPE_KIND_STRUCT) {
453  RZ_LOG_WARN("PDB: Type of %s (struct) conflicts with already defined type (%s), redefining it.\n",
455  rz_type_db_delete_base_type((RzTypeDB *)typedb, base_type);
456  base_type = NULL;
457  } else if (type->parsed || rz_bin_pdb_type_is_fwdref(type)) {
458  return base_type->type ? rz_type_clone(base_type->type) : create_rztype(type, RZ_TYPE_IDENTIFIER_KIND_STRUCT, name);
459  } else if (base_type->attrs != RZ_TYPE_TYPECLASS_INVALID) {
460  RZ_LOG_INFO("%s : Redefining type %s.\n", __FUNCTION__, name);
461  }
462  }
463  }
464 
465  if (!base_type) {
467  if (!base_type) {
468  return NULL;
469  }
470 
472  if (!typ) {
473  rz_type_base_type_free(base_type);
474  return NULL;
475  }
476  base_type->type = typ;
477  base_type->name = strdup(typ->identifier.name);
478  base_type->attrs = RZ_TYPE_TYPECLASS_INVALID;
479  rz_type_db_save_base_type(typedb, base_type);
480 
482  return rz_type_clone(base_type->type);
483  }
484  }
485  rz_vector_clear(&base_type->struct_data.members);
487  RzListIter *it;
488  RzPdbTpiType *member_info;
489  rz_list_foreach (members, it, member_info) {
490  if (member_info->leaf_type == LF_INDEX) {
493  it = rz_list_head(members);
494  if (!it) {
495  break;
496  }
497  member_info = rz_list_first(members);
498  }
499  RzTypeStructMember *struct_member = parse_struct_member(typedb, stream, member_info);
500  if (!struct_member) {
501  continue; // skip the failure
502  }
503  void *element = rz_vector_push(&base_type->struct_data.members, struct_member);
504  if (!element) {
505  rz_type_base_struct_member_free(struct_member, NULL);
506  return NULL;
507  }
508  free(struct_member);
509  }
510  base_type->size = rz_bin_pdb_get_type_val(type);
511  if (base_type->attrs == RZ_TYPE_TYPECLASS_INVALID) {
512  base_type->attrs = RZ_TYPE_TYPECLASS_NONE;
513  rz_list_append(stream->print_type, base_type);
514  }
515  type->parsed = true;
516  return base_type->type ? rz_type_clone(base_type->type) : NULL;
517 }
518 
528  rz_return_val_if_fail(type_info && stream && typedb, NULL);
529  char *name = NULL;
530  ut64 offset = 0;
531  RzType *type = NULL;
532  switch (type_info->leaf_type) {
533  case LF_ONEMETHOD: {
534  name = rz_bin_pdb_get_type_name(type_info);
535  type = parse_type_onemethod(typedb, stream, type_info);
536  break;
537  }
538  case LF_MEMBER: {
539  offset = rz_bin_pdb_get_type_val(type_info);
540  name = rz_bin_pdb_get_type_name(type_info);
541  type = parse_type_member(typedb, stream, type_info, name);
542  break;
543  }
544  case LF_NESTTYPE: {
545  name = rz_bin_pdb_get_type_name(type_info);
546  type = parse_type_nest(typedb, stream, type_info);
547  break;
548  }
549  default:
550  RZ_LOG_ERROR("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type_info->leaf_type);
551  goto cleanup;
552  }
553  if (!type) {
554  RZ_LOG_INFO("%s : couldn't parse union member type!\n", __FUNCTION__);
555  return NULL;
556  }
557 
559  if (!member) {
560  goto cleanup;
561  }
562  member->name = strdup(name);
563  member->type = type;
564  member->offset = offset;
565  return member;
566 cleanup:
568  return NULL;
569 }
570 
578  rz_return_val_if_fail(typedb && stream && type, NULL);
579 
580  RzBaseType *base_type = NULL;
582  if (name) {
583  base_type = get_tpitype_basetype(typedb, type, name);
584  if (base_type) {
585  if (base_type->kind != RZ_BASE_TYPE_KIND_UNION) {
586  RZ_LOG_WARN("PDB: Type of %s (union) conflicts with already defined type (%s), redefining it.\n",
588  rz_type_db_delete_base_type((RzTypeDB *)typedb, base_type);
589  base_type = NULL;
590  } else if (type->parsed || rz_bin_pdb_type_is_fwdref(type)) {
591  return base_type->type ? rz_type_clone(base_type->type) : create_rztype(type, RZ_TYPE_IDENTIFIER_KIND_UNION, name);
592  } else if (base_type->attrs != RZ_TYPE_TYPECLASS_INVALID) {
593  RZ_LOG_INFO("%s : Redefining type %s.\n", __FUNCTION__, name);
594  }
595  }
596  }
597 
598  if (!base_type) {
600  if (!base_type) {
601  return NULL;
602  }
603 
605  if (!typ) {
606  rz_type_base_type_free(base_type);
607  return NULL;
608  }
609  base_type->type = typ;
610  base_type->name = strdup(typ->identifier.name);
611  base_type->attrs = RZ_TYPE_TYPECLASS_INVALID;
612  rz_type_db_save_base_type(typedb, base_type);
613 
615  return rz_type_clone(base_type->type);
616  }
617  }
618  rz_vector_clear(&base_type->union_data.members);
620  RzListIter *it;
621  RzPdbTpiType *member_info;
622  rz_list_foreach (members, it, member_info) {
623  if (member_info->leaf_type == LF_INDEX) {
626  it = rz_list_head(members);
627  if (!it) {
628  break;
629  }
630  member_info = rz_list_first(members);
631  }
632  RzTypeUnionMember *union_member = parse_union_member(typedb, stream, member_info);
633  if (!union_member) {
634  continue; // skip the failure
635  }
636  void *element = rz_vector_push(&base_type->union_data.members, union_member);
637  if (!element) {
638  rz_type_base_union_member_free(union_member, NULL);
639  return NULL;
640  }
641  free(union_member);
642  }
643  base_type->size = rz_bin_pdb_get_type_val(type);
644  if (base_type->attrs == RZ_TYPE_TYPECLASS_INVALID) {
645  base_type->attrs = RZ_TYPE_TYPECLASS_NONE;
646  rz_list_append(stream->print_type, base_type);
647  }
648  type->parsed = true;
649  return base_type->type ? rz_type_clone(base_type->type) : NULL;
650 }
651 
658  rz_return_val_if_fail(type && type->leaf_type == LF_ENUMERATE, NULL);
659 
660  char *name = NULL;
661  ut64 value = 0;
662  // sometimes, the type doesn't have get_val for some reason
666  if (!cas) {
667  goto cleanup;
668  }
669  cas->name = strdup(name);
670  cas->val = value;
671  return cas;
672 cleanup:
673  return NULL;
674 }
675 
684  rz_return_val_if_fail(typedb && type, NULL);
685  Tpi_LF_Enum *lf_enum = type->type_data;
686  // assert all member functions we need info from
687  RzBaseType *base_type = NULL;
689  if (name) {
690  base_type = get_tpitype_basetype(typedb, type, name);
691  if (base_type) {
692  if (base_type->kind != RZ_BASE_TYPE_KIND_ENUM) {
693  RZ_LOG_WARN("PDB: Type of %s (enum) conflicts with already defined type (%s), redefining it.\n",
695  rz_type_db_delete_base_type((RzTypeDB *)typedb, base_type);
696  base_type = NULL;
697  } else if (type->parsed || rz_bin_pdb_type_is_fwdref(type)) {
698  return base_type->type ? rz_type_clone(base_type->type) : NULL;
699  } else if (base_type->attrs != RZ_TYPE_TYPECLASS_INVALID) {
700  RZ_LOG_INFO("%s : Redefining type %s.\n", __FUNCTION__, name);
701  }
702  }
703  }
704 
705  if (!base_type) {
707  if (!base_type) {
708  return NULL;
709  }
710 
712  if (!utype) {
713  rz_type_base_type_free(base_type);
714  return NULL;
715  }
716  RzType *btype = parse_type(typedb, stream, utype, NULL);
717  if (!btype) {
718  rz_type_base_type_free(base_type);
719  return NULL;
720  }
721  base_type->name = is_tpitype_unnamed(name) ? create_type_name_from_offset(type->type_index) : strdup(name);
722  base_type->size = rz_type_db_get_bitsize(typedb, btype);
723  base_type->type = btype;
724  base_type->attrs = RZ_TYPE_TYPECLASS_INVALID;
725  rz_type_db_save_base_type(typedb, base_type);
726 
728  return rz_type_clone(base_type->type);
729  }
730  }
731  rz_vector_clear(&base_type->enum_data.cases);
733  RzListIter *it;
734  RzPdbTpiType *member_info;
735  rz_list_foreach (members, it, member_info) {
736  if (member_info->leaf_type == LF_INDEX) {
739  it = rz_list_head(members);
740  if (!it) {
741  break;
742  }
743  member_info = rz_list_first(members);
744  }
745  RzTypeEnumCase *enum_case = parse_enumerate(member_info);
746  if (!enum_case) {
747  continue; // skip it, move forward
748  }
749  void *element = rz_vector_push(&base_type->enum_data.cases, enum_case);
750  if (!element) {
751  rz_type_base_enum_case_free(enum_case, NULL);
752  return NULL;
753  }
754  free(enum_case);
755  }
756  if (base_type->attrs == RZ_TYPE_TYPECLASS_INVALID) {
757  base_type->attrs = RZ_TYPE_TYPECLASS_NONE;
758  rz_list_append(stream->print_type, base_type);
759  }
760  type->parsed = true;
761  return base_type->type ? rz_type_clone(base_type->type) : NULL;
762 }
763 
771 static void parse_types(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
772  rz_return_if_fail(typedb && type);
773 
774  switch (type->leaf_type) {
775  case LF_CLASS:
776  case LF_CLASS_19:
777  break;
778  case LF_STRUCTURE:
779  case LF_STRUCTURE_19:
780  parse_structure(typedb, stream, type);
781  break;
782  case LF_UNION:
783  parse_union(typedb, stream, type);
784  break;
785  case LF_ENUM:
786  parse_enum(typedb, stream, type);
787  break;
788  default:
789  // shouldn't happen, happens when someone modifies leafs that get here
790  // but not how they should be parsed
791  RZ_LOG_ERROR("Unknown type record");
792  break;
793  }
794 }
795 
802 RZ_API void rz_parse_pdb_types(const RzTypeDB *typedb, const RzPdb *pdb) {
803  rz_return_if_fail(typedb && pdb);
804  RzPdbTpiStream *stream = pdb->s_tpi;
805  if (!stream) { // no TPI stream found
806  return;
807  }
808 
810  if (!stream->print_type) {
811  return;
812  }
813 
814  RBIter it;
816  rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) {
817  if (type && is_parsable_type(type->leaf_type)) {
818  parse_types(typedb, stream, type);
819  }
820  }
821 }
lzma_index ** i
Definition: index.h:629
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 void rz_type_base_struct_member_free(void *e, void *user)
Definition: base.c:14
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
RZ_API RZ_BORROW const char * rz_type_base_type_kind_as_string(RzBaseTypeKind kind)
Returns string representing the kind of base type.
Definition: base.c:33
RZ_API void rz_type_base_union_member_free(void *e, void *user)
Definition: base.c:21
RZ_API RZ_BORROW RzBaseType * rz_type_db_get_base_type(const RzTypeDB *typedb, RZ_NONNULL const char *name)
Searches for the RzBaseType in the types database given the name.
Definition: base.c:57
RZ_API bool rz_type_db_delete_base_type(RzTypeDB *typedb, RZ_NONNULL RzBaseType *type)
Removes RzBaseType from the Types DB.
Definition: base.c:74
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
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
void cleanup(void)
Definition: enough.c:244
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf stream
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
snprintf
Definition: kernel.h:364
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 void * rz_list_first(RZ_NONNULL const RzList *list)
Returns the first element of the list.
Definition: list.c:77
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
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")
int type
Definition: mipsasm.c:17
#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 RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_WARN(fmtstr,...)
Definition: rz_log.h:56
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define rz_rbtree_foreach(root, it, data, struc, rb)
Definition: rz_rbtree.h:101
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
@ RZ_BASE_TYPE_KIND_TYPEDEF
Definition: rz_type.h:76
@ 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
RzTypeIdentifierKind
Definition: rz_type.h:134
@ RZ_TYPE_IDENTIFIER_KIND_STRUCT
Definition: rz_type.h:136
@ RZ_TYPE_IDENTIFIER_KIND_UNION
Definition: rz_type.h:137
@ RZ_TYPE_TYPECLASS_NONE
Definition: rz_type.h:62
@ RZ_TYPE_TYPECLASS_INVALID
Definition: rz_type.h:69
@ RZ_TYPE_KIND_ARRAY
Definition: rz_type.h:130
@ RZ_TYPE_KIND_CALLABLE
Definition: rz_type.h:131
@ RZ_TYPE_KIND_IDENTIFIER
Definition: rz_type.h:128
@ RZ_TYPE_KIND_POINTER
Definition: rz_type.h:129
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
RZ_API void * rz_vector_push(RzVector *vec, void *x)
Definition: vector.c:197
RZ_API RzPVector * rz_pvector_new(RzPVectorFree free)
Definition: vector.c:302
void(* RzPVectorFree)(void *e)
Definition: rz_vector.h:43
static void ** rz_pvector_push(RzPVector *vec, void *x)
Definition: rz_vector.h:300
RZ_API void rz_vector_clear(RzVector *vec)
Definition: vector.c:68
ut32 * arg_type
Definition: tpi.h:332
ut32 count
Definition: tpi.h:331
ut32 element_type
Definition: tpi.h:435
ut32 utype
Definition: tpi.h:493
ut32 return_type
Definition: tpi.h:319
RzPdbTpiCallingConvention call_conv
Definition: tpi.h:322
ut32 arglist
Definition: tpi.h:325
ut32 index
Definition: tpi.h:538
ut32 modified_type
Definition: tpi.h:346
TpiCVModifier umodifier
Definition: tpi.h:347
ut32 index
Definition: tpi.h:509
ut32 index
Definition: tpi.h:559
ut32 utype
Definition: tpi.h:409
ut32 arg_list
Definition: tpi.h:314
RzPdbTpiCallingConvention call_conv
Definition: tpi.h:311
ut32 return_type
Definition: tpi.h:310
char * type
Definition: tpi.h:586
const char * name
Definition: sparc-opc.c:1838
Definition: z80asm.h:102
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
RzBaseTypeUnion union_data
Definition: rz_type.h:120
RzBaseTypeKind kind
Definition: rz_type.h:115
RzTypeAttribute attrs
Definition: rz_type.h:116
RzVector members
Definition: rz_type.h:104
RzPVector * args
optional for the time being
Definition: rz_type.h:149
RZ_NULLABLE const char * cc
Definition: rz_type.h:150
RZ_NULLABLE char * name
Definition: rz_type.h:147
RZ_NULLABLE RzType * ret
Definition: rz_type.h:148
RzPdbTpiStream * s_tpi
Definition: rz_pdb.h:247
RzTypeParser * parser
Definition: rz_type.h:37
RzTypeKind kind
Definition: rz_type.h:155
struct rz_type_t::@292::@295 pointer
struct rz_type_t::@292::@294 identifier
RzCallable * callable
Definition: rz_type.h:170
struct rz_type_t::@292::@296 array
RzList * print_type
Definition: rz_pdb.h:157
ut16 leaf_type
Definition: rz_pdb.h:147
void * type_data
Definition: rz_pdb.h:149
RZ_API ut64 rz_bin_pdb_get_type_val(RZ_NONNULL RzPdbTpiType *type)
Get the numeric value inside the type.
Definition: tpi.c:507
RZ_API RZ_BORROW RzList * rz_bin_pdb_get_type_members(RZ_NONNULL RzPdbTpiStream *stream, RzPdbTpiType *t)
Get the RzPdbTpiType member list.
Definition: tpi.c:406
RZ_API RZ_BORROW RzPdbTpiType * rz_bin_pdb_get_type_by_index(RZ_NONNULL RzPdbTpiStream *stream, ut32 index)
Get RzPdbTpiType that matches tpi stream index.
Definition: tpi.c:1844
RZ_API RZ_OWN char * rz_bin_pdb_calling_convention_as_string(RZ_NONNULL RzPdbTpiCallingConvention idx)
Parses calling convention type as string.
Definition: tpi.c:35
RZ_API RZ_BORROW char * rz_bin_pdb_get_type_name(RZ_NONNULL RzPdbTpiType *type)
Get the name of the type.
Definition: tpi.c:447
RZ_API bool rz_bin_pdb_type_is_fwdref(RZ_NONNULL RzPdbTpiType *t)
Return true if type is forward definition.
Definition: tpi.c:372
TpiLeafType
Definition: tpi.h:75
@ LF_NESTTYPE
Definition: tpi.h:186
@ LF_MEMBER
Definition: tpi.h:183
@ LF_METHOD
Definition: tpi.h:185
@ LF_STRUCTURE_19
Definition: tpi.h:200
@ LF_ONEMETHOD
Definition: tpi.h:187
@ LF_BCLASS
Definition: tpi.h:154
@ LF_SIMPLE_TYPE
Definition: tpi.h:246
@ LF_PROCEDURE
Definition: tpi.h:133
@ LF_POINTER
Definition: tpi.h:127
@ LF_CLASS
Definition: tpi.h:174
@ LF_MODIFIER
Definition: tpi.h:126
@ LF_ENUMERATE
Definition: tpi.h:172
@ LF_STMEMBER
Definition: tpi.h:184
@ LF_MFUNCTION
Definition: tpi.h:134
@ LF_UNION
Definition: tpi.h:176
@ LF_STRUCTURE
Definition: tpi.h:175
@ LF_INDEX
Definition: tpi.h:158
@ LF_ARRAY
Definition: tpi.h:173
@ LF_CLASS_19
Definition: tpi.h:199
@ LF_BITFIELD
Definition: tpi.h:148
@ LF_ENUM
Definition: tpi.h:177
@ LF_VFUNCTAB
Definition: tpi.h:163
RZ_API bool rz_type_func_save(RzTypeDB *typedb, RZ_NONNULL RzCallable *callable)
Stores RzCallable type in the types database.
Definition: function.c:147
RZ_API void rz_type_callable_arg_free(RzCallableArg *arg)
Frees the RzCallableArg.
Definition: function.c:101
RZ_API ut64 rz_type_db_get_bitsize(const RzTypeDB *typedb, RZ_NONNULL RzType *type)
Returns the type size in bits (target dependent)
Definition: type.c:779
RZ_API void rz_type_free(RZ_NULLABLE RzType *type)
Frees the RzType.
Definition: type.c:1273
RZ_API RZ_OWN RzType * rz_type_clone(RZ_BORROW RZ_NONNULL const RzType *type)
Creates an exact clone of the RzType.
Definition: type.c:1181
static RzTypeUnionMember * parse_union_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info)
Parses union member.
Definition: type_pdb.c:527
static bool is_parsable_type(const TpiLeafType type)
Definition: type_pdb.c:30
static RzType * create_rztype(RzPdbTpiType *type, RzTypeIdentifierKind kind, const char *name)
Definition: type_pdb.c:426
static RzType * parse_type_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name)
Definition: type_pdb.c:288
static RzType * parse_structure(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type)
Parses structures into BaseType and saves them into hashtable.
Definition: type_pdb.c:444
static RzType * parse_type_mfunction(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name)
Definition: type_pdb.c:238
static RzType * parse_regular_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name)
Definition: type_pdb.c:74
static RzBaseType * get_tpitype_basetype(const RzTypeDB *typedb, RzPdbTpiType *type, const char *name)
Definition: type_pdb.c:414
static RzType * parse_type_nest(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info)
Definition: type_pdb.c:309
static RzType * parse_type_static_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name)
Definition: type_pdb.c:299
static RzType * parse_type_procedure(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name)
Definition: type_pdb.c:197
static RzType * parse_type_onemethod(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info)
Definition: type_pdb.c:274
static RzTypeEnumCase * parse_enumerate(RzPdbTpiType *type)
Parse enum case.
Definition: type_pdb.c:657
static char * create_type_name_from_offset(ut64 offset)
Create a type name from offset.
Definition: type_pdb.c:46
static RzTypeStructMember * parse_struct_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info)
Parses struct member.
Definition: type_pdb.c:352
static RzType * parse_type_modifier(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type)
Definition: type_pdb.c:108
static RzType * parse_type_pointer(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name)
Definition: type_pdb.c:131
static RzType * parse_union(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type)
Parses union into BaseType and saves it into hashtable.
Definition: type_pdb.c:577
RZ_API void rz_parse_pdb_types(const RzTypeDB *typedb, const RzPdb *pdb)
Saves PDB types from TPI stream into the type database.
Definition: type_pdb.c:802
static void parse_types(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type)
Delegate the type parsing to appropriate function.
Definition: type_pdb.c:771
static RzType * parse_enum(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type)
Parses enum into BaseType and saves it into SDB.
Definition: type_pdb.c:683
static bool is_tpitype_unnamed(const char *name)
Definition: type_pdb.c:410
static RzType * parse_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name)
Definition: type_pdb.c:153
static RzType * parse_type_array(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type)
Definition: type_pdb.c:53
static void parse_type_arglist(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *arglist, RzPVector *vec)
Definition: type_pdb.c:174
ut16 const_
Definition: tpi.h:338
struct TpiCVModifier::@210 bits
void error(const char *msg)
Definition: untgz.c:593
ut64(WINAPI *w32_GetEnabledXStateFeatures)()