Rizin
unix-like reverse engineering framework and cli tools
pe_debug.c File Reference
#include "pe.h"

Go to the source code of this file.

Classes

struct  SCV_NB10_HEADER
 
struct  SGUID
 
struct  SCV_RSDS_HEADER
 

Macros

#define SIZEOF_FILE_NAME   255
 

Functions

static void free_rsdr_hdr (SCV_RSDS_HEADER *rsds_hdr)
 
static void init_rsdr_hdr (SCV_RSDS_HEADER *rsds_hdr)
 
static void free_cv_nb10_header (SCV_NB10_HEADER *cv_nb10_header)
 
static void init_cv_nb10_header (SCV_NB10_HEADER *cv_nb10_header)
 
static bool get_rsds (ut8 *dbg_data, int dbg_data_len, SCV_RSDS_HEADER *res)
 
static void get_nb10 (ut8 *dbg_data, int dbg_data_len, SCV_NB10_HEADER *res)
 
static int get_debug_info (RzBinPEObj *bin, PE_(image_debug_directory_entry) *dbg_dir_entry, ut8 *dbg_data, int dbg_data_len, SDebugInfo *res)
 
static int read_image_debug_directory_entry (RzBuffer *b, ut64 addr, PE_(image_debug_directory_entry) *entry)
 
int PE_() rz_bin_pe_get_debug_data (RzBinPEObj *bin, SDebugInfo *res)
 

Macro Definition Documentation

◆ SIZEOF_FILE_NAME

#define SIZEOF_FILE_NAME   255

Function Documentation

◆ free_cv_nb10_header()

static void free_cv_nb10_header ( SCV_NB10_HEADER cv_nb10_header)
static

Definition at line 43 of file pe_debug.c.

43  {
44  RZ_FREE(cv_nb10_header->file_name);
45 }
#define RZ_FREE(x)
Definition: rz_types.h:369
ut8 * file_name
Definition: pe_debug.c:14

References SCV_NB10_HEADER::file_name, and RZ_FREE.

Referenced by init_cv_nb10_header().

◆ free_rsdr_hdr()

static void free_rsdr_hdr ( SCV_RSDS_HEADER rsds_hdr)
static

Definition at line 34 of file pe_debug.c.

34  {
35  RZ_FREE(rsds_hdr->file_name);
36 }
ut8 * file_name
Definition: pe_debug.c:30

References SCV_RSDS_HEADER::file_name, and RZ_FREE.

Referenced by init_rsdr_hdr().

◆ get_debug_info()

static int get_debug_info ( RzBinPEObj bin,
PE_(image_debug_directory_entry) *  dbg_dir_entry,
ut8 dbg_data,
int  dbg_data_len,
SDebugInfo res 
)
static

Definition at line 71 of file pe_debug.c.

71  {
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 }
lzma_index ** i
Definition: index.h:629
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
#define GUIDSTR_LEN
Definition: pe.h:116
static void get_nb10(ut8 *dbg_data, int dbg_data_len, SCV_NB10_HEADER *res)
Definition: pe_debug.c:62
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
#define IMAGE_DEBUG_TYPE_CODEVIEW
Definition: pe_specs.h:129
#define RZ_LOG_INFO(fmtstr,...)
Definition: rz_log.h:54
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
#define toupper(c)
Definition: safe-ctype.h:147
ut32 timestamp
Definition: pe_debug.c:12
void(* free)(struct SCV_NB10_HEADER *cv_nb10_header)
Definition: pe_debug.c:15
void(* free)(struct SCV_RSDS_HEADER *rsds_hdr)
Definition: pe_debug.c:31
char file_name[DBG_FILE_NAME_LEN]
Definition: pe.h:121
char guidstr[GUIDSTR_LEN]
Definition: pe.h:120
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

References SCV_NB10_HEADER::age, SCV_RSDS_HEADER::age, SGUID::data1, SGUID::data2, SGUID::data3, SGUID::data4, SDebugInfo::file_name, SCV_NB10_HEADER::file_name, SCV_RSDS_HEADER::file_name, SCV_NB10_HEADER::free, SCV_RSDS_HEADER::free, get_nb10(), get_rsds(), SCV_RSDS_HEADER::guid, SDebugInfo::guidstr, GUIDSTR_LEN, i, IMAGE_DEBUG_TYPE_CODEVIEW, init_cv_nb10_header(), init_rsdr_hdr(), RZ_LOG_ERROR, RZ_LOG_INFO, snprintf, SCV_NB10_HEADER::timestamp, and toupper.

Referenced by rz_bin_pe_get_debug_data().

◆ get_nb10()

static void get_nb10 ( ut8 dbg_data,
int  dbg_data_len,
SCV_NB10_HEADER res 
)
static

Definition at line 62 of file pe_debug.c.

62  {
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 }
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
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")

References SCV_NB10_HEADER::file_name, memcpy(), and strdup().

Referenced by get_debug_info().

◆ get_rsds()

static bool get_rsds ( ut8 dbg_data,
int  dbg_data_len,
SCV_RSDS_HEADER res 
)
static

Definition at line 52 of file pe_debug.c.

52  {
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 }
Definition: pe_debug.c:18

References SCV_RSDS_HEADER::file_name, memcpy(), and strdup().

Referenced by get_debug_info().

◆ init_cv_nb10_header()

static void init_cv_nb10_header ( SCV_NB10_HEADER cv_nb10_header)
static

Definition at line 47 of file pe_debug.c.

47  {
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 }
return memset(p, 0, total)
static void free_cv_nb10_header(SCV_NB10_HEADER *cv_nb10_header)
Definition: pe_debug.c:43

References SCV_NB10_HEADER::free, free_cv_nb10_header(), and memset().

Referenced by get_debug_info().

◆ init_rsdr_hdr()

static void init_rsdr_hdr ( SCV_RSDS_HEADER rsds_hdr)
static

Definition at line 38 of file pe_debug.c.

38  {
39  memset(rsds_hdr, 0, sizeof(SCV_RSDS_HEADER));
40  rsds_hdr->free = (void (*)(struct SCV_RSDS_HEADER *))free_rsdr_hdr;
41 }
static void free_rsdr_hdr(SCV_RSDS_HEADER *rsds_hdr)
Definition: pe_debug.c:34

References SCV_RSDS_HEADER::free, free_rsdr_hdr(), and memset().

Referenced by get_debug_info().

◆ read_image_debug_directory_entry()

static int read_image_debug_directory_entry ( RzBuffer b,
ut64  addr,
PE_(image_debug_directory_entry) *  entry 
)
static

Definition at line 139 of file pe_debug.c.

139  {
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 }
voidpf void * buf
Definition: ioapi.h:138
#define PE_READ_STRUCT_FIELD(var, struct_type, field, size)
Definition: pe.h:177
#define PE_(name)
Definition: pe_specs.h:23
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
#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)
#define st64
Definition: rz_types_base.h:10
#define b(i)
Definition: sha256.c:42
Definition: swift.c:7
Definition: zipcmp.c:77
static int addr
Definition: z80asm.c:58

References addr, b, PE_, PE_READ_STRUCT_FIELD, RZ_BUF_CUR, rz_buf_read(), rz_buf_seek(), RZ_BUF_SET, and st64.

Referenced by rz_bin_pe_get_debug_data().

◆ rz_bin_pe_get_debug_data()

int PE_() rz_bin_pe_get_debug_data ( RzBinPEObj bin,
SDebugInfo res 
)

Definition at line 158 of file pe_debug.c.

158  {
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 }
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
PE_DWord PE_() bin_pe_rva_to_paddr(RzBinPEObj *bin, PE_DWord rva)
Definition: pe.c:15
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 int read_image_debug_directory_entry(RzBuffer *b, ut64 addr, PE_(image_debug_directory_entry) *entry)
Definition: pe_debug.c:139
#define PE_DWord
Definition: pe_specs.h:27
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
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
#define RZ_MIN(x, y)
Definition: malloc.c:26

References bin_pe_rva_to_paddr(), calloc(), get_debug_info(), NULL, PE_, PE_DWord, read_image_debug_directory_entry(), rz_buf_read_at(), rz_buf_size(), RZ_FREE, and RZ_MIN.