Rizin
unix-like reverse engineering framework and cli tools
pe_debug.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008-2019 nibble <nibble.ds@gmail.com>
2 // SPDX-FileCopyrightText: 2008-2019 pancake <pancake@nopcode.org>
3 // SPDX-FileCopyrightText: 2008-2019 inisider <inisider@gmail.com>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include "pe.h"
7 
8 struct SCV_NB10_HEADER;
9 typedef struct {
15  void (*free)(struct SCV_NB10_HEADER *cv_nb10_header);
17 
18 typedef struct {
22  ut8 data4[8];
23 } SGUID;
24 
25 struct SCV_RSDS_HEADER;
26 typedef struct {
31  void (*free)(struct SCV_RSDS_HEADER *rsds_hdr);
33 
34 static void free_rsdr_hdr(SCV_RSDS_HEADER *rsds_hdr) {
35  RZ_FREE(rsds_hdr->file_name);
36 }
37 
38 static void init_rsdr_hdr(SCV_RSDS_HEADER *rsds_hdr) {
39  memset(rsds_hdr, 0, sizeof(SCV_RSDS_HEADER));
40  rsds_hdr->free = (void (*)(struct SCV_RSDS_HEADER *))free_rsdr_hdr;
41 }
42 
43 static void free_cv_nb10_header(SCV_NB10_HEADER *cv_nb10_header) {
44  RZ_FREE(cv_nb10_header->file_name);
45 }
46 
47 static void init_cv_nb10_header(SCV_NB10_HEADER *cv_nb10_header) {
48  memset(cv_nb10_header, 0, sizeof(SCV_NB10_HEADER));
49  cv_nb10_header->free = (void (*)(struct SCV_NB10_HEADER *))free_cv_nb10_header;
50 }
51 
52 static bool get_rsds(ut8 *dbg_data, int dbg_data_len, SCV_RSDS_HEADER *res) {
53  const int rsds_sz = 4 + sizeof(SGUID) + 4;
54  if (dbg_data_len < rsds_sz) {
55  return false;
56  }
57  memcpy(res, dbg_data, rsds_sz);
58  res->file_name = (ut8 *)strdup((const char *)dbg_data + rsds_sz);
59  return true;
60 }
61 
62 static void get_nb10(ut8 *dbg_data, int dbg_data_len, SCV_NB10_HEADER *res) {
63  const int nb10sz = 16;
64  if (dbg_data_len < nb10sz) {
65  return;
66  }
67  memcpy(res, dbg_data, nb10sz);
68  res->file_name = (ut8 *)strdup((const char *)dbg_data + nb10sz);
69 }
70 
71 static int get_debug_info(RzBinPEObj *bin, PE_(image_debug_directory_entry) * dbg_dir_entry, ut8 *dbg_data, int dbg_data_len, SDebugInfo *res) {
72 #define SIZEOF_FILE_NAME 255
73  int i = 0;
74  const char *dbgname;
75  if (!dbg_data) {
76  return 0;
77  }
78  switch (dbg_dir_entry->Type) {
80  if (!strncmp((char *)dbg_data, "RSDS", 4)) {
81  SCV_RSDS_HEADER rsds_hdr;
82  init_rsdr_hdr(&rsds_hdr);
83  if (!get_rsds(dbg_data, dbg_data_len, &rsds_hdr)) {
84  RZ_LOG_INFO("Cannot read PE debug info\n");
85  return 0;
86  }
88  "%08x%04x%04x%02x%02x%02x%02x%02x%02x%02x%02x%x",
89  rsds_hdr.guid.data1,
90  rsds_hdr.guid.data2,
91  rsds_hdr.guid.data3,
92  rsds_hdr.guid.data4[0],
93  rsds_hdr.guid.data4[1],
94  rsds_hdr.guid.data4[2],
95  rsds_hdr.guid.data4[3],
96  rsds_hdr.guid.data4[4],
97  rsds_hdr.guid.data4[5],
98  rsds_hdr.guid.data4[6],
99  rsds_hdr.guid.data4[7],
100  rsds_hdr.age);
101  dbgname = (char *)rsds_hdr.file_name;
102  strncpy(res->file_name, (const char *)dbgname, sizeof(res->file_name));
103  res->file_name[sizeof(res->file_name) - 1] = 0;
104  rsds_hdr.free((struct SCV_RSDS_HEADER *)&rsds_hdr);
105  } else if (strncmp((const char *)dbg_data, "NB10", 4) == 0) {
106  if (dbg_data_len < 20) {
107  RZ_LOG_ERROR("Truncated NB10 entry, not enough data to parse\n");
108  return 0;
109  }
110  SCV_NB10_HEADER nb10_hdr = { { 0 } };
111  init_cv_nb10_header(&nb10_hdr);
112  get_nb10(dbg_data, dbg_data_len, &nb10_hdr);
113  snprintf(res->guidstr, sizeof(res->guidstr),
114  "%x%x", nb10_hdr.timestamp, nb10_hdr.age);
115  res->file_name[0] = 0;
116  if (nb10_hdr.file_name) {
117  strncpy(res->file_name, (const char *)nb10_hdr.file_name, sizeof(res->file_name) - 1);
118  }
119  res->file_name[sizeof(res->file_name) - 1] = 0;
120  nb10_hdr.free((struct SCV_NB10_HEADER *)&nb10_hdr);
121  } else {
122  RZ_LOG_INFO("CodeView section not NB10 or RSDS\n");
123  return 0;
124  }
125  break;
126  default:
127  // RZ_LOG_INFO("get_debug_info(): not supported type\n");
128  return 0;
129  }
130 
131  while (i < 33) {
132  res->guidstr[i] = toupper((ut8)res->guidstr[i]);
133  i++;
134  }
135 
136  return 1;
137 }
138 
139 static int read_image_debug_directory_entry(RzBuffer *b, ut64 addr, PE_(image_debug_directory_entry) * entry) {
140  st64 o_addr = rz_buf_seek(b, 0, RZ_BUF_CUR);
141  if (rz_buf_seek(b, addr, RZ_BUF_SET) < 0) {
142  return -1;
143  }
144  ut8 buf[sizeof(PE_(image_debug_directory_entry))];
145  rz_buf_read(b, buf, sizeof(buf));
146  PE_READ_STRUCT_FIELD(entry, PE_(image_debug_directory_entry), Characteristics, 32);
147  PE_READ_STRUCT_FIELD(entry, PE_(image_debug_directory_entry), TimeDateStamp, 32);
148  PE_READ_STRUCT_FIELD(entry, PE_(image_debug_directory_entry), MajorVersion, 16);
149  PE_READ_STRUCT_FIELD(entry, PE_(image_debug_directory_entry), MinorVersion, 16);
150  PE_READ_STRUCT_FIELD(entry, PE_(image_debug_directory_entry), Type, 32);
151  PE_READ_STRUCT_FIELD(entry, PE_(image_debug_directory_entry), SizeOfData, 32);
152  PE_READ_STRUCT_FIELD(entry, PE_(image_debug_directory_entry), AddressOfRawData, 32);
153  PE_READ_STRUCT_FIELD(entry, PE_(image_debug_directory_entry), PointerToRawData, 32);
154  rz_buf_seek(b, o_addr, RZ_BUF_SET);
155  return sizeof(PE_(image_debug_directory_entry));
156 }
157 
159  PE_(image_debug_directory_entry)
160  img_dbg_dir_entry = { 0 };
161  PE_(image_data_directory) *dbg_dir = NULL;
162  PE_DWord dbg_dir_offset;
163  ut8 *dbg_data = 0;
164  int result = 0;
165  if (!bin) {
166  return 0;
167  }
168  dbg_dir = &bin->nt_headers->optional_header.DataDirectory[6 /*IMAGE_DIRECTORY_ENTRY_DEBUG*/];
169  dbg_dir_offset = PE_(bin_pe_rva_to_paddr)(bin, dbg_dir->VirtualAddress);
170  if ((int)dbg_dir_offset < 0 || dbg_dir_offset >= bin->size) {
171  return false;
172  }
173  if (dbg_dir_offset >= rz_buf_size(bin->b)) {
174  return false;
175  }
176  read_image_debug_directory_entry(bin->b, dbg_dir_offset, &img_dbg_dir_entry);
177  if ((rz_buf_size(bin->b) - dbg_dir_offset) < sizeof(PE_(image_debug_directory_entry))) {
178  return false;
179  }
180  ut32 dbg_data_poff = RZ_MIN(img_dbg_dir_entry.PointerToRawData, rz_buf_size(bin->b));
181  int dbg_data_len = RZ_MIN(img_dbg_dir_entry.SizeOfData, rz_buf_size(bin->b) - dbg_data_poff);
182  if (dbg_data_len < 1) {
183  return false;
184  }
185  dbg_data = (ut8 *)calloc(1, dbg_data_len + 1);
186  if (dbg_data) {
187  rz_buf_read_at(bin->b, dbg_data_poff, dbg_data, dbg_data_len);
188  result = get_debug_info(bin, &img_dbg_dir_entry, dbg_data, dbg_data_len, res);
189  RZ_FREE(dbg_data);
190  }
191  return result;
192 }
lzma_index ** i
Definition: index.h:629
#define NULL
Definition: cris-opc.c:27
uint16_t ut16
uint32_t ut32
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
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")
PE_DWord PE_() bin_pe_rva_to_paddr(RzBinPEObj *bin, PE_DWord rva)
Definition: pe.c:15
#define RzBinPEObj
Definition: pe.h:126
#define PE_READ_STRUCT_FIELD(var, struct_type, field, size)
Definition: pe.h:177
#define GUIDSTR_LEN
Definition: pe.h:116
int PE_() rz_bin_pe_get_debug_data(RzBinPEObj *bin, SDebugInfo *res)
Definition: pe_debug.c:158
static void free_rsdr_hdr(SCV_RSDS_HEADER *rsds_hdr)
Definition: pe_debug.c:34
static void free_cv_nb10_header(SCV_NB10_HEADER *cv_nb10_header)
Definition: pe_debug.c:43
static void get_nb10(ut8 *dbg_data, int dbg_data_len, SCV_NB10_HEADER *res)
Definition: pe_debug.c:62
static int get_debug_info(RzBinPEObj *bin, PE_(image_debug_directory_entry) *dbg_dir_entry, ut8 *dbg_data, int dbg_data_len, SDebugInfo *res)
Definition: pe_debug.c:71
static bool get_rsds(ut8 *dbg_data, int dbg_data_len, SCV_RSDS_HEADER *res)
Definition: pe_debug.c:52
static void init_rsdr_hdr(SCV_RSDS_HEADER *rsds_hdr)
Definition: pe_debug.c:38
static void init_cv_nb10_header(SCV_NB10_HEADER *cv_nb10_header)
Definition: pe_debug.c:47
static int read_image_debug_directory_entry(RzBuffer *b, ut64 addr, PE_(image_debug_directory_entry) *entry)
Definition: pe_debug.c:139
#define PE_(name)
Definition: pe_specs.h:23
#define PE_DWord
Definition: pe_specs.h:27
#define IMAGE_DEBUG_TYPE_CODEVIEW
Definition: pe_specs.h:129
RZ_API st64 rz_buf_seek(RZ_NONNULL RzBuffer *b, st64 addr, int whence)
Modify the current cursor position in the buffer.
Definition: buf.c:1166
#define RZ_BUF_CUR
Definition: rz_buf.h:15
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
#define RZ_BUF_SET
Definition: rz_buf.h:14
RZ_API st64 rz_buf_read(RZ_NONNULL RzBuffer *b, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define toupper(c)
Definition: safe-ctype.h:147
#define b(i)
Definition: sha256.c:42
ut8 * file_name
Definition: pe_debug.c:14
ut8 signature[4]
Definition: pe_debug.c:10
ut32 timestamp
Definition: pe_debug.c:12
void(* free)(struct SCV_NB10_HEADER *cv_nb10_header)
Definition: pe_debug.c:15
ut8 signature[4]
Definition: pe_debug.c:27
ut8 * file_name
Definition: pe_debug.c:30
void(* free)(struct SCV_RSDS_HEADER *rsds_hdr)
Definition: pe_debug.c:31
Definition: pe.h:119
char file_name[DBG_FILE_NAME_LEN]
Definition: pe.h:121
char guidstr[GUIDSTR_LEN]
Definition: pe.h:120
Definition: pe_debug.c:18
ut16 data2
Definition: pe_debug.c:20
ut16 data3
Definition: pe_debug.c:21
ut32 data1
Definition: pe_debug.c:19
ut8 data4[8]
Definition: pe_debug.c:22
Definition: swift.c:7
Definition: malloc.c:26
Definition: zipcmp.c:77
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58