Skip to content

Commit

Permalink
Create global variables from PDB (#4021)
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow committed Dec 6, 2023
1 parent 036a712 commit bfe19a7
Show file tree
Hide file tree
Showing 24 changed files with 1,909 additions and 1,174 deletions.
2 changes: 1 addition & 1 deletion librz/analysis/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ rz_analysis_sources = [
'serialize_analysis.c',
'similarity.c',
'switch.c',
'type_pdb.c',
'pdb_process.c',
'types.c',
'value.c',
'var.c',
Expand Down
176 changes: 93 additions & 83 deletions librz/analysis/type_pdb.c → librz/analysis/pdb_process.c

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions librz/bin/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ rz_bin_sources = [
'pdb/pdb_downloader.c',
'pdb/stream_pe.c',
'pdb/tpi.c',
'pdb/symbol.c',

'dwarf/abbrev.c',
'dwarf/addr.c',
Expand Down
79 changes: 21 additions & 58 deletions librz/bin/pdb/gdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,12 @@

#include "pdb.h"

static bool parse_gdata_global(GDataGlobal *global, RzBuffer *buf, ut32 initial_seek) {
if (!rz_buf_read_le32(buf, &global->symtype) ||
!rz_buf_read_le32(buf, &global->offset)) {
return false;
}
if (!rz_buf_read_le16(buf, &global->segment)) {
return false;
}
if (global->leaf_type == 0x110E) {
global->name = rz_buf_get_string(buf, rz_buf_tell(buf));
ut16 len = strlen(global->name) + 1;
global->name_len = len;
rz_buf_seek(buf, len, RZ_BUF_CUR);
} else {
if (!rz_buf_read8(buf, &global->name_len)) {
return false;
}
}
ut32 read_len = rz_buf_tell(buf) - initial_seek;
if (read_len % 4) {
ut16 remain = 4 - (read_len % 4);
rz_buf_seek(buf, remain, RZ_BUF_CUR);
}
return true;
}

RZ_IPI bool parse_gdata_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
rz_return_val_if_fail(pdb && stream, false);
PDBSymbolTable *syms = pdb_global_symbols(pdb);
if (!syms) {
return false;
}
if (!pdb->s_gdata) {
pdb->s_gdata = RZ_NEW0(RzPdbGDataStream);
}
Expand All @@ -40,53 +18,38 @@ RZ_IPI bool parse_gdata_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
RZ_LOG_ERROR("Error allocating memory.\n");
return false;
}
RzBuffer *buf = stream->stream_data;
s->global_list = rz_list_new();
if (!s->global_list) {
s->global_symbols = rz_pvector_new(free);
if (!s->global_symbols) {
return false;
}
ut16 len;

PDBSymbolIter iter = { 0 };
PDBSymbolTable_iter(syms, &iter);
while (true) {
ut32 initial_seek = rz_buf_tell(buf);
if (!rz_buf_read_le16(buf, &len)) {
break;
PDBSymbol *symbol = RZ_NEW0(PDBSymbol);
if (!symbol) {
goto err;
}
if (len == 0 || len == UT16_MAX) {
if (!PDBSymbolIter_next(&iter, symbol)) {
free(symbol);
break;
}
ut16 leaf_type;
if (!rz_buf_read_le16(buf, &leaf_type)) {
return false;
}
if (leaf_type == 0x110E || leaf_type == 0x1009) {
GDataGlobal *global = RZ_NEW0(GDataGlobal);
if (!global) {
goto skip;
}
global->leaf_type = leaf_type;
if (!parse_gdata_global(global, buf, initial_seek)) {
RZ_FREE(global);
return false;
}
rz_list_append(s->global_list, global);
if (!symbol->data) {
free(symbol);
continue;
}
skip:
rz_buf_seek(buf, len - sizeof(ut16), RZ_BUF_CUR);
rz_pvector_push(s->global_symbols, symbol);
}

return true;
err:
return false;
}

RZ_IPI void free_gdata_stream(RzPdbGDataStream *stream) {
if (!stream) {
return;
}
GDataGlobal *global;
RzListIter *it;
rz_list_foreach (stream->global_list, it, global) {
RZ_FREE(global->name);
RZ_FREE(global);
}
rz_list_free(stream->global_list);
rz_pvector_free(stream->global_symbols);
free(stream);
}
18 changes: 0 additions & 18 deletions librz/bin/pdb/gdata.h

This file was deleted.

73 changes: 35 additions & 38 deletions librz/bin/pdb/omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,33 +52,16 @@ RZ_IPI void free_omap_stream(RzPdbOmapStream *stream) {
free(stream);
}

// inclusive indices
// 0 <= imin when using truncate toward zero divide
// imid = (imin+imax)/2;
// imin unrestricted when using truncate toward minus infinity divide
// imid = (imin+imax)>>1; or
// imid = (int)floor((imin+imax)/2.0);
static int binary_search(unsigned int *A, int key, int imin, int imax) {
int imid;

// continually narrow search until just one element remains
while (imin < imax) {
imid = (imin + imax) / 2;
if (A[imid] < key) {
imin = imid + 1;
} else {
imax = imid;
}
static int cmp_ut64(const void *pa, const void *pb) {
ut64 a = *(ut64 *)pb;
ut64 b = *(ut64 *)pa;
if (a < b) {
return -1;
}
// At exit of while:
// if A[] is empty, then imax < imin
// otherwise imax == imin

// deferred test for equality
if ((imax == imin) && (A[imin] == key)) {
return imin;
if (a > b) {
return 1;
}
return -1;
return 0;
}

/**
Expand All @@ -88,21 +71,19 @@ static int binary_search(unsigned int *A, int key, int imin, int imax) {
* \param address Where to remap
* \return int
*/
RZ_API int rz_bin_pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, int address) {
static ut64 pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, ut64 address) {
OmapEntry *omap_entry = 0;
RzListIter *it = 0;
int i = 0;
int pos = 0;
int len = 0;

if (!omap_stream) {
return address;
}

len = rz_list_length(omap_stream->entries);
ut32 len = rz_list_length(omap_stream->entries);

if (omap_stream->froms == 0) {
omap_stream->froms = (unsigned int *)malloc(4 * len);
omap_stream->froms = (ut64 *)malloc(sizeof(ut64) * len);
if (!omap_stream->froms) {
return -1;
}
Expand All @@ -114,17 +95,12 @@ RZ_API int rz_bin_pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, int ad
}
}

// mb (len -1) ???
pos = binary_search(omap_stream->froms, address, 0, (len));

if (pos == -1) {
const ut64 *p = bsearch(&address, omap_stream->froms, len, sizeof(ut64), cmp_ut64);
if (!p) {
return -1;
}

if (omap_stream->froms[pos] != address) {
pos -= 1;
}
omap_entry = (OmapEntry *)rz_list_get_n(omap_stream->entries, pos);
omap_entry = (OmapEntry *)rz_list_get_n(omap_stream->entries, *p);
if (!omap_entry) {
return -1;
}
Expand All @@ -133,3 +109,24 @@ RZ_API int rz_bin_pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, int ad
}
return omap_entry->to + (address - omap_entry->from);
}

/**
* \brief Convert the section offset to relative virtual address
*
* \param pdb The PDB reference
* \param section_offset The section offset
* \return The relative virtual address
*/
RZ_API ut64 rz_bin_pdb_to_rva(RZ_NONNULL const RzPdb *pdb, const PDBSectionOffset *section_offset) {
static const ut64 DEFAULT = UT64_MAX;
rz_return_val_if_fail(pdb && pdb->s_pe, DEFAULT);
PeImageSectionHeader *section_hdr = pdb_section_hdr_by_index(pdb->s_pe, section_offset->section_index);
if (!section_hdr) {
return DEFAULT;
}
ut64 internal_rva = section_offset->offset + section_hdr->virtual_address;
if (pdb->s_omap) {
return pdb_omap_remap(pdb->s_omap, internal_rva);
}
return internal_rva;
}
42 changes: 36 additions & 6 deletions librz/bin/pdb/pdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,19 @@ static bool parse_streams(RzPdb *pdb) {
break;
case PDB_STREAM_PDB:
if (!parse_pdb_stream(pdb, ms)) {
RZ_LOG_ERROR("Parse pdb stream failed.");
RZ_LOG_ERROR("Parse pdb stream failed.\n");
return false;
}
break;
case PDB_STREAM_TPI:
if (!parse_tpi_stream(pdb, ms)) {
RZ_LOG_ERROR("Parse tpi stream failed.");
RZ_LOG_ERROR("Parse tpi stream failed.\n");
return false;
}
break;
case PDB_STREAM_DBI:
if (!parse_dbi_stream(pdb, ms)) {
RZ_LOG_ERROR("Parse dbi stream failed.");
RZ_LOG_ERROR("Parse dbi stream failed.\n");
return false;
}
break;
Expand All @@ -66,19 +66,19 @@ static bool parse_streams(RzPdb *pdb) {
}
if (ms->stream_idx == pdb->s_dbi->hdr.sym_record_stream) {
if (!parse_gdata_stream(pdb, ms)) {
RZ_LOG_ERROR("Parse gdata stream failed.");
RZ_LOG_ERROR("Parse gdata stream failed.\n");
return false;
}
} else if (ms->stream_idx == pdb->s_dbi->dbg_hdr.sn_section_hdr ||
ms->stream_idx == pdb->s_dbi->dbg_hdr.sn_section_hdr_orig) {
if (!parse_pe_stream(pdb, ms)) {
RZ_LOG_ERROR("Parse pe stream failed.");
RZ_LOG_ERROR("Parse pe stream failed.\n");
return false;
}
} else if (ms->stream_idx == pdb->s_dbi->dbg_hdr.sn_omap_to_src ||
ms->stream_idx == pdb->s_dbi->dbg_hdr.sn_omap_from_src) {
if (!parse_omap_stream(pdb, ms)) {
RZ_LOG_ERROR("Parse omap stream failed.");
RZ_LOG_ERROR("Parse omap stream failed.\n");
return false;
}
}
Expand All @@ -89,6 +89,36 @@ static bool parse_streams(RzPdb *pdb) {
return true;
}

RZ_IPI RzPdbMsfStream *pdb_raw_steam(RzPdb *pdb, ut16 index) {
if (!(pdb && pdb->streams)) {
return NULL;
}
RzListIter *it;
RzPdbMsfStream *ms;
rz_list_foreach (pdb->streams, it, ms) {
if (ms->stream_idx == index) {
return ms;
}
}
return NULL;
}

RZ_IPI PDBSymbolTable *pdb_global_symbols(RzPdb *pdb) {
if (!(pdb && pdb->s_dbi)) {
return NULL;
}
RzPdbMsfStream *steam = pdb_raw_steam(pdb, pdb->s_dbi->hdr.sym_record_stream);
if (!steam) {
return NULL;
}
PDBSymbolTable *symbols = RZ_NEW0(PDBSymbolTable);
if (!symbols) {
return NULL;
}
symbols->b = steam->stream_data;
return symbols;
}

static void msf_stream_free(void *data) {
RzPdbMsfStream *msfstream = data;
rz_buf_free(msfstream->stream_data);
Expand Down
10 changes: 7 additions & 3 deletions librz/bin/pdb/pdb.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
// SPDX-FileCopyrightText: 2021 Basstorm <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only

#ifndef PDB_PRIVATE_INCLUDE_H_
#define PDB_PRIVATE_INCLUDE_H_

#include <rz_pdb.h>
#include "dbi.h"
#include "gdata.h"
#include "omap.h"
#include "stream_pe.h"
#include "tpi.h"
#include "symbol.h"

RZ_IPI RzPdbMsfStream *pdb_raw_steam(RzPdb *pdb, ut16 index);
RZ_IPI PDBSymbolTable *pdb_global_symbols(RzPdb *pdb);

#ifndef PDB_PRIVATE_INCLUDE_H_
#define PDB_PRIVATE_INCLUDE_H_
// OMAP
RZ_IPI bool parse_omap_stream(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI void free_omap_stream(RzPdbOmapStream *stream);
Expand Down
4 changes: 4 additions & 0 deletions librz/bin/pdb/stream_pe.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ typedef struct {
ut32 charactestics;
} PeImageSectionHeader;

static inline PeImageSectionHeader *pdb_section_hdr_by_index(RZ_NONNULL const RzPdbPeStream *s, ut64 index) {
return rz_list_get_n(s->sections_hdrs, index - 1);
}

#endif
Loading

0 comments on commit bfe19a7

Please sign in to comment.