Rizin
unix-like reverse engineering framework and cli tools
cpdb.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Basstorm <basstorm@nyist.edu.cn>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_core.h>
5 #include <rz_pdb.h>
6 #include "../bin/pdb/pdb.h"
7 
8 static void pdb_types_print_standard(const RzTypeDB *db, const RzPdb *pdb, const RzList *types) {
9  rz_return_if_fail(pdb && db && types);
10  if (!types) {
11  eprintf("there is nothing to print!\n");
12  }
13  RzListIter *it;
16  rz_list_foreach (types, it, type) {
18  }
19  rz_cons_print(rz_strbuf_get(buf));
21  return;
22 }
23 
24 static void pdb_types_print_json(const RzTypeDB *db, const RzPdb *pdb, const RzList *types, PJ *pj) {
25  rz_return_if_fail(db && pdb && types && pj);
26  RzListIter *it;
28  pj_o(pj);
29  pj_ka(pj, "types");
30  rz_list_foreach (types, it, type) {
31  switch (type->kind) {
33  pj_o(pj);
34  pj_ks(pj, "type", "structure");
35  pj_ks(pj, "name", type->name);
36  pj_kn(pj, "size", type->size);
37  pj_ka(pj, "members");
38  RzTypeStructMember *memb;
39  rz_vector_foreach(&type->struct_data.members, memb) {
40  pj_o(pj);
41  char *typ = rz_type_as_string(db, memb->type);
42  pj_ks(pj, "member_type", typ);
43  RZ_FREE(typ);
44  pj_ks(pj, "member_name", memb->name);
45  pj_kN(pj, "offset", memb->offset);
46  pj_end(pj);
47  }
48  pj_end(pj);
49  pj_end(pj);
50  break;
51  }
53  pj_o(pj);
54  pj_ks(pj, "type", "union");
55  pj_ks(pj, "name", type->name);
56  pj_kn(pj, "size", type->size);
57  pj_ka(pj, "members");
58  RzTypeUnionMember *memb;
59  rz_vector_foreach(&type->union_data.members, memb) {
60  pj_o(pj);
61  char *typ = rz_type_as_string(db, memb->type);
62  pj_ks(pj, "member_type", typ);
63  RZ_FREE(typ);
64  pj_ks(pj, "member_name", memb->name);
65  pj_kN(pj, "offset", memb->offset);
66  pj_end(pj);
67  }
68  pj_end(pj);
69  pj_end(pj);
70  break;
71  }
73  pj_o(pj);
74  pj_ks(pj, "type", "enum");
75  pj_ks(pj, "name", type->name);
76  char *typ = rz_type_as_string(db, type->type);
77  pj_ks(pj, "base_type", typ);
78  RZ_FREE(typ);
79  pj_ka(pj, "cases");
80  RzTypeEnumCase *cas;
81  rz_vector_foreach(&type->enum_data.cases, cas) {
82  pj_o(pj);
83  pj_ks(pj, "enum_name", cas->name);
84  pj_kn(pj, "enum_val", cas->val);
85  pj_end(pj);
86  }
87  pj_end(pj);
88  pj_end(pj);
89  break;
90  }
91  default:
92  break;
93  }
94  }
95  pj_end(pj);
96  pj_end(pj);
97  return;
98 }
99 
100 static void rz_core_bin_pdb_types_print(const RzTypeDB *db, const RzPdb *pdb, const RzCmdStateOutput *state) {
101  rz_return_if_fail(db && pdb && state);
102  RzPdbTpiStream *stream = pdb->s_tpi;
103  if (!stream) {
104  eprintf("There is no tpi stream in current pdb\n");
105  return;
106  }
107  switch (state->mode) {
109  pdb_types_print_standard(db, pdb, stream->print_type);
110  break;
111  case RZ_OUTPUT_MODE_JSON:
112  pdb_types_print_json(db, pdb, stream->print_type, state->d.pj);
113  break;
114  default:
115  return;
116  }
117 }
118 
128 RZ_API char *rz_core_bin_pdb_gvars_as_string(RZ_NONNULL const RzPdb *pdb, const ut64 img_base, PJ *pj, const RzOutputMode mode) {
130  PeImageSectionHeader *sctn_header = 0;
131  RzPdbGDataStream *gsym_data_stream = 0;
132  RzPdbPeStream *pe_stream = 0;
133  RzPdbOmapStream *omap_stream;
134  GDataGlobal *gdata = 0;
135  RzListIter *it = 0;
136  char *name;
138  if (!buf) {
139  return NULL;
140  }
141  if (mode == RZ_OUTPUT_MODE_JSON) {
142  pj_o(pj);
143  pj_ka(pj, "gvars");
144  }
145  gsym_data_stream = pdb->s_gdata;
146  pe_stream = pdb->s_pe;
147  omap_stream = pdb->s_omap;
148  if (!pe_stream) {
150  return NULL;
151  }
152  rz_list_foreach (gsym_data_stream->global_list, it, gdata) {
153  sctn_header = rz_list_get_n(pe_stream->sections_hdrs, (gdata->segment - 1));
154  if (sctn_header) {
155  name = rz_demangler_msvc(gdata->name);
156  name = (name) ? name : strdup(gdata->name);
157  switch (mode) {
158  case RZ_OUTPUT_MODE_JSON: // JSON
159  pj_o(pj);
160  pj_kN(pj, "address", (img_base + rz_bin_pdb_omap_remap(omap_stream, gdata->offset + sctn_header->virtual_address)));
161  pj_kN(pj, "symtype", gdata->symtype);
162  pj_ks(pj, "section_name", sctn_header->name);
163  pj_ks(pj, "gdata_name", name);
164  pj_end(pj);
165  break;
167  rz_strbuf_appendf(buf, "0x%08" PFMT64x " %d %.*s %s\n",
168  (ut64)(img_base + rz_bin_pdb_omap_remap(omap_stream, gdata->offset + sctn_header->virtual_address)),
169  gdata->symtype, PDB_SIZEOF_SECTION_NAME, sctn_header->name, name);
170  break;
171  default:
172  break;
173  }
174  free(name);
175  }
176  }
177  if (mode == RZ_OUTPUT_MODE_JSON) {
178  pj_end(pj);
179  pj_end(pj);
180  // We will need this for Windows Heap.
182  }
183  char *str = strdup(rz_strbuf_get(buf));
185  return str;
186 }
187 
188 static void rz_core_bin_pdb_gvars_print(const RzPdb *pdb, const ut64 img_base, const RzCmdStateOutput *state) {
189  rz_return_if_fail(pdb && state);
190  char *str = rz_core_bin_pdb_gvars_as_string(pdb, img_base, state->d.pj, state->mode);
191  // We don't need to print the output of JSON because the RzCmdStateOutput will handle it.
192  if (state->mode == RZ_OUTPUT_MODE_STANDARD) {
193  rz_cons_print(str);
194  }
195  free(str);
196  return;
197 }
198 
199 static void pdb_set_symbols(const RzCore *core, const RzPdb *pdb, const ut64 img_base, const char *pdbfile) {
200  rz_return_if_fail(core && pdb);
201  PeImageSectionHeader *sctn_header = 0;
202  RzPdbGDataStream *gsym_data_stream = 0;
203  RzPdbPeStream *pe_stream = 0;
204  RzPdbOmapStream *omap_stream;
205  GDataGlobal *gdata = 0;
206  RzListIter *it = 0;
207  char *name;
208  char *filtered_name;
209  gsym_data_stream = pdb->s_gdata;
210  pe_stream = pdb->s_pe;
211  omap_stream = pdb->s_omap;
212  if (!pe_stream) {
213  return;
214  }
215  char *file = rz_str_replace(strdup(pdbfile), ".pdb", "", 0);
216  rz_flag_space_push(core->flags, RZ_FLAGS_FS_SYMBOLS);
217  rz_list_foreach (gsym_data_stream->global_list, it, gdata) {
218  sctn_header = rz_list_get_n(pe_stream->sections_hdrs, (gdata->segment - 1));
219  if (sctn_header) {
220  name = rz_demangler_msvc(gdata->name);
221  name = (name) ? name : strdup(gdata->name);
222  filtered_name = rz_name_filter2(name, true);
223  char *fname = rz_str_newf("pdb.%s.%s", file, filtered_name);
224  ut64 addr = (ut64)(img_base + rz_bin_pdb_omap_remap(omap_stream, gdata->offset + sctn_header->virtual_address));
225  RzFlagItem *item = rz_flag_set(core->flags, fname, addr, 0);
226  if (item) {
228  }
229  free(filtered_name);
230  free(name);
231  }
232  }
233  rz_flag_space_pop(core->flags);
234  free(file);
235  return;
236 }
237 
246  rz_return_val_if_fail(core && file, NULL);
247 
248  ut64 baddr = rz_bin_get_baddr(core->bin);
249  if (!baddr || baddr == UT64_MAX) {
250  baddr = rz_config_get_i(core->config, "bin.baddr");
251  eprintf("Warning: Cannot find base address, flags will probably be misplaced\n");
252  }
253 
255  if (!pdb) {
256  return NULL;
257  }
258 
259  // Save compound types into types database
260  rz_parse_pdb_types(core->analysis->typedb, pdb);
262  return pdb;
263 }
264 
274  rz_return_if_fail(db && pdb && state);
275 
276  ut64 baddr = rz_config_get_i(core->config, "bin.baddr");
277  if (core->bin->cur && core->bin->cur->o && core->bin->cur->o->opts.baseaddr) {
278  baddr = core->bin->cur->o->opts.baseaddr;
279  } else {
280  eprintf("Warning: Cannot find base address, flags will probably be misplaced\n");
281  }
282 
284  rz_core_bin_pdb_types_print(core->analysis->typedb, pdb, state);
287  return;
288 }
RZ_API RZ_OWN char * rz_type_db_base_type_as_pretty_string(RZ_NONNULL const RzTypeDB *typedb, RZ_NONNULL const RzBaseType *btype, unsigned int opts, int unfold_level)
Returns C representation as string of RzBaseType.
Definition: base.c:219
RZ_API ut64 rz_bin_get_baddr(RzBin *bin)
Definition: bin.c:536
static ut64 baddr(RzBinFile *bf)
Definition: bin_any.c:58
RZ_API void rz_cmd_state_output_array_start(RzCmdStateOutput *state)
Mark the start of an array of elements in the output.
Definition: cmd_api.c:2558
RZ_API void rz_cmd_state_output_array_end(RzCmdStateOutput *state)
Mark the end of an array of elements in the output.
Definition: cmd_api.c:2572
RZ_API ut64 rz_config_get_i(RzConfig *cfg, RZ_NONNULL const char *name)
Definition: config.c:119
#define RZ_API
static void rz_core_bin_pdb_gvars_print(const RzPdb *pdb, const ut64 img_base, const RzCmdStateOutput *state)
Definition: cpdb.c:188
static void pdb_set_symbols(const RzCore *core, const RzPdb *pdb, const ut64 img_base, const char *pdbfile)
Definition: cpdb.c:199
RZ_API void rz_core_pdb_info_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzTypeDB *db, RZ_NONNULL RzPdb *pdb, RZ_NONNULL RzCmdStateOutput *state)
Print parsed PDB file info.
Definition: cpdb.c:273
RZ_API char * rz_core_bin_pdb_gvars_as_string(RZ_NONNULL const RzPdb *pdb, const ut64 img_base, PJ *pj, const RzOutputMode mode)
Return the PDB global vars string.
Definition: cpdb.c:128
static void rz_core_bin_pdb_types_print(const RzTypeDB *db, const RzPdb *pdb, const RzCmdStateOutput *state)
Definition: cpdb.c:100
static void pdb_types_print_json(const RzTypeDB *db, const RzPdb *pdb, const RzList *types, PJ *pj)
Definition: cpdb.c:24
RZ_API RzPdb * rz_core_pdb_load_info(RZ_NONNULL RzCore *core, RZ_NONNULL const char *file)
Parse PDB file info and integrate with typedb.
Definition: cpdb.c:245
static void pdb_types_print_standard(const RzTypeDB *db, const RzPdb *pdb, const RzList *types)
Definition: cpdb.c:8
#define NULL
Definition: cris-opc.c:27
RZ_API RzFlagItem * rz_flag_set(RzFlag *f, const char *name, ut64 off, ut32 size)
Definition: flag.c:521
RZ_API void rz_flag_item_set_realname(RzFlagItem *item, const char *realname)
Definition: flag.c:571
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf stream
Definition: ioapi.h:138
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
RZ_API RZ_OWN char * rz_demangler_msvc(RZ_NONNULL const char *symbol)
Demangles microsft vc symbols.
Definition: demangler.c:74
RZ_API RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int type
Definition: mipsasm.c:17
RZ_API int rz_bin_pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, int address)
return remapped symbol address
Definition: omap.c:89
const char * name
Definition: op.c:541
insn_type_descr_t types[]
Definition: or1k_disas.c:7
RZ_API RZ_OWN RzPdb * rz_bin_pdb_parse_from_file(RZ_NONNULL const char *filename)
Parse PDB file given the path.
Definition: pdb.c:292
#define eprintf(x, y...)
Definition: rlcc.c:7
#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_FLAGS_FS_SYMBOLS
Definition: rz_core.h:67
RZ_API const char * rz_file_basename(const char *path)
Definition: file.c:83
RZ_API char * rz_name_filter2(const char *name, bool strict)
Definition: name.c:92
RZ_API PJ * pj_ka(PJ *j, const char *k)
Definition: pj.c:163
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API const char * pj_string(PJ *pj)
Definition: pj.c:57
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121
RZ_API PJ * pj_kN(PJ *j, const char *k, st64 n)
Definition: pj.c:128
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
@ RZ_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
@ RZ_TYPE_PRINT_END_NEWLINE
Definition: rz_type.h:222
@ RZ_TYPE_PRINT_MULTILINE
Definition: rz_type.h:216
#define RZ_NONNULL
Definition: rz_types.h:64
RzOutputMode
Enum to describe the way data are printed.
Definition: rz_types.h:38
@ RZ_OUTPUT_MODE_JSON
Definition: rz_types.h:40
@ RZ_OUTPUT_MODE_STANDARD
Definition: rz_types.h:39
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define UT64_MAX
Definition: rz_types_base.h:86
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
#define PDB_SIZEOF_SECTION_NAME
Definition: stream_pe.h:14
ut32 offset
Definition: gdata.h:12
ut16 segment
Definition: gdata.h:13
char * name
Definition: gdata.h:14
ut32 symtype
Definition: gdata.h:11
RzList * global_list
Definition: rz_pdb.h:68
RzList * sections_hdrs
Definition: rz_pdb.h:80
Definition: gzappend.c:170
Definition: z80asm.h:102
Definition: rz_pj.h:12
Represent the output state of a command handler.
Definition: rz_cmd.h:91
RzFlag * flags
Definition: rz_core.h:330
RzPdbGDataStream * s_gdata
Definition: rz_pdb.h:248
RzPdbTpiStream * s_tpi
Definition: rz_pdb.h:247
RzPdbPeStream * s_pe
Definition: rz_pdb.h:250
RzPdbOmapStream * s_omap
Definition: rz_pdb.h:249
Definition: dis.h:43
RZ_API RZ_OWN char * rz_type_as_string(const RzTypeDB *typedb, RZ_NONNULL const RzType *type)
Returns the type C representation.
Definition: type.c:817
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
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58