Initial implementation of the PDB parser

* Contains 78 rebased commits

- add R_PDB struct
- add implementation of init_pdb_parser()
- add stub for init_pdb7_root_stream()
- add init_pdb_stream() function
- add functions for working with stream_file
- do fixes for stream_file_read
- add getting of sizes
- save streams to rlist
- add light implementation of read_root function
- add stubs for parsed_pdb_stream_init
- add parsing of pdb info stream
- start of parsing tpi header
- add stub for tpi stream
- fix stream file read. +stubs for eFIELD_LIST
- add parsing of lf_enumerate
- add parsing of lf_nesttype()
- add parsing of LF_METHOD
- add parsing of lf_member
- add some additional parsing of types
- fix some memory leaks
- add support of LF_METHOD and LF_MEMBER
- add support of LF_NESTTYPE
- add support of LF_ENUM
- add parsing of lf_structure
- add parsing of lf_pointer
- start of lf_array implementation
- back implementation of lf_array
- add implementation of LF_MODIFIER
- add implementaion of lf_arglist
- add implementaion of lf_mfunction
- add useful macros
- add implementation of lf_procedure
- add implementation of lf_union
- add free of sval and printf name of sval
- add implementation of LF_BITFIELD
- add implementation of LF_CLASS
- add implementation of LF_VTSHPAE
- start of refactoring
- finish refactor of the code
- fix memory leak issues
- some refactor of memory managment
- fix memory managment
- add supprot of ushort type
- add function for printing type name and value
- add API for getting leaf types members
- refactor of SType and STypeInfO
- add implementation of get_name/val/... for new types
- fix cast in some function of getting name, val, etc
- add stubs for resolving type
- add pointers to function for getting types
- add connections for types function pointers
- add stub for printing structures
- update memory manadgement and fix some problems in API for working with types
- add process of result from init_pdb function
- print more info about structure
- refactor of printing structure info
- Revert of 9fa8e7083c

refactor structure info printing

more pretty print

refactor code

add parsing of dbi header

add structure stabs for dbi stream

add parsing of dbi_ex_headers

add free for dbi stream

finish parsing of dbg stream

add stubs for streams from dbg stream

add fpo parsing

add free for fpo stream and do some refactor

add parsing of gdata stream

add parsing of pe stream

add parsing of fpo new stream

add fpo new stream

add omap stream parsing

add implementation of printing gvars

add setting parameters for pdb_parser

delete unused comments

delete unused comments
This commit is contained in:
inisider 2014-07-23 16:28:06 -04:00 committed by pancake
parent 7b65bb16b2
commit d547b037c9
21 changed files with 5009 additions and 1 deletions

View File

@ -10,7 +10,7 @@ PFX=$(call rmdblslash,${DESTDIR}/${PREFIX})
BFX=$(call rmdblslash,${DESTDIR}/${BINDIR})
LFX=$(call rmdblslash,${DESTDIR}/${LIBDIR})
BINS=rax2 rasm2 rabin2 rahash2 radiff2 radare2 rafind2 rarun2 ragg2 r2agent
BINS=pdb-parser rax2 rasm2 rabin2 rahash2 radiff2 radare2 rafind2 rarun2 ragg2 r2agent
all: preload
@for a in ${BINS} ; do (cd $$a && ${MAKE} all) || exit 1; done

View File

@ -0,0 +1,64 @@
#include <stdio.h>
#include <r_pdb.h>
#include <string.h>
#include <getopt.h>
///////////////////////////////////////////////////////////////////////////////
static void print_usage()
{
printf("pdb_parser -f pdb_file [option]\n");
printf("\t -f, --pdb_file : set pdb file to parse\n");
printf("[option]:\n");
printf("\t -t, --print_types : print all types parsed in pdb file\n");
printf("\t -g, --print_globals : print all globals functions/variables parsed in pdb file\n");
}
///////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
R_PDB pdb;
static struct option long_options[] =
{
{"pdb_file", required_argument, 0, 'f'},
{"print_types", no_argument, 0, 't'},
{"print_globals", required_argument, 0, 'g'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
int option_index = 0;
int c = 0;
char *pdb_file = 0;
while(1) {
c = getopt_long (argc, argv, ":f:tg:h",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'f':
pdb_file = optarg;
strcpy(&pdb.file_name, optarg);
if (!init_pdb_parser(&pdb)) {
printf("initialization error of pdb parser\n");
return 0;
}
pdb.pdb_parse(&pdb);
break;
case 't':
pdb.print_types(&pdb);
break;
case 'g':
pdb.print_gvars(&pdb, *(int *)optarg);
break;
default:
print_usage();
return 0;
}
}
return 0;
}

View File

@ -45,6 +45,9 @@ EXTRA +=
<include>format
;
# PDB
OBJS += pdb/omap.c pdb/pe.c pdb/gdata.c pdb/fpo.c pdb/dbi.c pdb/tpi.c pdb/stream_file.c pdb/pdb.c
# Java
OBJS += p/bin_java.c ;
EXTRA +=

View File

@ -18,6 +18,7 @@ STATIC_OBJS=$(addprefix $(LTOP)/bin/p/, $(STATIC_OBJ))
OBJS=bin.o dbginfo.o bin_write.o demangle.o dwarf.o
OBJS+=mangling/cxx/cp-demangle.o ${STATIC_OBJS}
OBJS+=mangling/objc.o mangling/cxx.o
OBJS+=pdb/omap.o pdb/pe.o pdb/gdata.o pdb/fpo.o pdb/dbi.o pdb/tpi.o pdb/stream_file.o pdb/pdb.o
LINK+=$(SHLR)/java/libr_java.a
include $(TOP)/libr/rules.mk

172
libr/bin/pdb/dbi.c Normal file
View File

@ -0,0 +1,172 @@
#include "dbi.h"
#include "stream_file.h"
#include "tpi.h"
#define _ALIGN 4
///////////////////////////////////////////////////////////////////////////////
static void free_dbi_stream(void *stream)
{
SDbiStream *t = (SDbiStream *) stream;
RListIter *it = 0;
SDBIExHeader *dbi_ex_header = 0;
it = r_list_iterator(t->dbiexhdrs);
while (r_list_iter_next(it)) {
dbi_ex_header = (SDBIExHeader *) r_list_iter_get(it);
free(dbi_ex_header->modName.name);
free(dbi_ex_header->objName.name);
free(dbi_ex_header);
}
r_list_free(t->dbiexhdrs);
}
///////////////////////////////////////////////////////////////////////////////
static void parse_dbi_header(SDBIHeader *dbi_header, R_STREAM_FILE *stream_file)
{
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->magic);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->version);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->age);
stream_file_read(stream_file, sizeof(short), (char *)&dbi_header->gssymStream);
stream_file_read(stream_file, sizeof(unsigned short), (char *)&dbi_header->vers);
stream_file_read(stream_file, sizeof(short), (char *)&dbi_header->pssymStream);
stream_file_read(stream_file, sizeof(unsigned short), (char *)&dbi_header->pdbver);
stream_file_read(stream_file, sizeof(short), (char *)&dbi_header->symrecStream);
stream_file_read(stream_file, sizeof(unsigned short), (char *)&dbi_header->pdbver2);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->module_size);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->seccon_size);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->secmap_size);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->filinf_size);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->tsmap_size);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->mfc_index);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->dbghdr_size);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->ecinfo_size);
stream_file_read(stream_file, sizeof(unsigned short), (char *)&dbi_header->flags);
stream_file_read(stream_file, 2, (char *)&dbi_header->machine);
stream_file_read(stream_file, sizeof(unsigned int), (char *)&dbi_header->resvd);
}
///////////////////////////////////////////////////////////////////////////////
static int parse_ssymbol_range(char *data, int max_len, SSymbolRange *symbol_range)
{
int read_bytes = 0;
READ(read_bytes, 2, max_len, symbol_range->section, data, short);
READ(read_bytes, 2, max_len, symbol_range->padding1, data, short);
READ(read_bytes, 4, max_len, symbol_range->offset, data, int);
READ(read_bytes, 4, max_len, symbol_range->size, data, int);
READ(read_bytes, 4, max_len, symbol_range->flags, data, unsigned int);
READ(read_bytes, 4, max_len, symbol_range->module, data, int);
// TODO: why not need to read this padding?
// READ(read_bytes, 2, max_len, symbol_range->padding2, data, short);
READ(read_bytes, 4, max_len, symbol_range->data_crc, data, unsigned int);
READ(read_bytes, 4, max_len, symbol_range->reloc_crc, data, unsigned int);
return read_bytes;
}
///////////////////////////////////////////////////////////////////////////////
static int parse_dbi_ex_header(char *data, int max_len, SDBIExHeader *dbi_ex_header)
{
unsigned int read_bytes = 0, before_read_bytes = 0;
READ(read_bytes, 4, max_len, dbi_ex_header->opened, data, unsigned int);
before_read_bytes = read_bytes;
read_bytes += parse_ssymbol_range(data, max_len, &dbi_ex_header->range);
data += (read_bytes - before_read_bytes);
READ(read_bytes, 2, max_len, dbi_ex_header->flags, data, unsigned short);
READ(read_bytes, 2, max_len, dbi_ex_header->stream, data, short);
READ(read_bytes, 4, max_len, dbi_ex_header->symSize, data, unsigned int);
READ(read_bytes, 4, max_len, dbi_ex_header->oldLineSize, data, unsigned int);
READ(read_bytes, 4, max_len, dbi_ex_header->lineSize, data, unsigned int);
READ(read_bytes, 2, max_len, dbi_ex_header->nSrcFiles, data, short);
READ(read_bytes, 2, max_len, dbi_ex_header->padding1, data, short);
READ(read_bytes, 4, max_len, dbi_ex_header->offsets, data, unsigned int);
READ(read_bytes, 4, max_len, dbi_ex_header->niSource, data, unsigned int);
READ(read_bytes, 4, max_len, dbi_ex_header->niCompiler, data, unsigned int);
before_read_bytes = read_bytes;
parse_sctring(&dbi_ex_header->modName, data, &read_bytes, max_len);
data += (read_bytes - before_read_bytes);
before_read_bytes = read_bytes;
parse_sctring(&dbi_ex_header->objName, data, &read_bytes, max_len);
data += (read_bytes - before_read_bytes);
return read_bytes;
}
///////////////////////////////////////////////////////////////////////////////
static void parse_dbg_header(SDbiDbgHeader *dbg_header, R_STREAM_FILE *stream_file)
{
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_fpo);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_exception);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_fixup);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_omap_to_src);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_omap_from_src);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_section_hdr);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_token_rid_map);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_xdata);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_pdata);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_new_fpo);
stream_file_read(stream_file, sizeof(short), (char *)&dbg_header->sn_section_hdr_orig);
}
///////////////////////////////////////////////////////////////////////////////
void init_dbi_stream(SDbiStream *dbi_stream)
{
dbi_stream->free_ = free_dbi_stream;
}
///////////////////////////////////////////////////////////////////////////////
void parse_dbi_stream(void *parsed_pdb_stream, R_STREAM_FILE *stream_file)
{
SDbiStream *dbi_stream = (SDbiStream *) parsed_pdb_stream;
SDBIExHeader *dbi_ex_header = 0;
int pos = 0;
char *dbiexhdr_data = 0, *p_tmp = 0;
int size = 0, sz = 0;
int i = 0;
parse_dbi_header(&dbi_stream->dbi_header, stream_file);
pos += sizeof(SDBIHeader) - 2; // 2 because enum in C equal to 4, but
// to read just 2;
stream_file_seek(stream_file, pos, 0);
size = dbi_stream->dbi_header.module_size;
dbiexhdr_data = (char *) malloc(size);
stream_file_read(stream_file, size, dbiexhdr_data);
dbi_stream->dbiexhdrs = r_list_new();
p_tmp = dbiexhdr_data;
while (i < size) {
dbi_ex_header = (SDBIExHeader *) malloc(sizeof(SDBIExHeader));
// TODO: rewrite for signature where can to do chech CAN_READ true?
sz = parse_dbi_ex_header(p_tmp, size, dbi_ex_header);
if ((sz % _ALIGN)) {
sz = sz + (_ALIGN - (sz % _ALIGN));
}
i += sz;
p_tmp += sz;
r_list_append(dbi_stream->dbiexhdrs, dbi_ex_header);
}
free(dbiexhdr_data);
// "Section Contribution"
stream_file_seek(stream_file, dbi_stream->dbi_header.seccon_size, 1);
// "Section Map"
stream_file_seek(stream_file, dbi_stream->dbi_header.secmap_size, 1);
// "File Info"
stream_file_seek(stream_file, dbi_stream->dbi_header.filinf_size, 1);
// "TSM"
stream_file_seek(stream_file, dbi_stream->dbi_header.tsmap_size, 1);
// "EC"
stream_file_seek(stream_file, dbi_stream->dbi_header.ecinfo_size, 1);
parse_dbg_header(&dbi_stream->dbg_header, stream_file);
}

9
libr/bin/pdb/dbi.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef DBI_H
#define DBI_H
#include "types.h"
void init_dbi_stream(SDbiStream *dbi_stream);
void parse_dbi_stream(void *parsed_pdb_stream, R_STREAM_FILE *stream_file);
#endif // DBI_H

126
libr/bin/pdb/fpo.c Normal file
View File

@ -0,0 +1,126 @@
#include "fpo.h"
#include "stream_file.h"
///////////////////////////////////////////////////////////////////////////////
static int parse_fpo_data(char *data, int data_size, int *read_bytes, SFPO_DATA *fpo_data)
{
int curr_read_bytes = *read_bytes;
READ(*read_bytes, 4, data_size, fpo_data->ul_off_start, data, unsigned int);
READ(*read_bytes, 4, data_size, fpo_data->cb_proc_size, data, unsigned int);
READ(*read_bytes, 4, data_size, fpo_data->cdw_locals, data, unsigned int);
READ(*read_bytes, 2, data_size, fpo_data->cdw_params, data, unsigned short);
READ(*read_bytes, 2, data_size, fpo_data->bit_values.bit_values, data, unsigned short);
fpo_data->bit_values.bit_values = SWAP_UINT16(fpo_data->bit_values.bit_values);
return (*read_bytes - curr_read_bytes);
}
///////////////////////////////////////////////////////////////////////////////
static int parse_fpo_data_v2(char *data, int data_size, int *read_bytes, SFPO_DATA_V2 *fpo_data)
{
int curr_read_bytes = *read_bytes;
memcpy(fpo_data, data, sizeof(SFPO_DATA_V2));
*read_bytes += sizeof(SFPO_DATA_V2);
return (*read_bytes - curr_read_bytes);
}
///////////////////////////////////////////////////////////////////////////////
void parse_fpo_stream(void *stream, R_STREAM_FILE *stream_file)
{
int data_size;
char *data = 0, *ptmp = 0;
int curr_read_bytes = 0, read_bytes = 0;
SFPO_DATA *fpo_data = 0;
SFPOStream *fpo_stream = 0;
stream_file_get_size(stream_file, &data_size);
data = (char *) malloc(data_size);
stream_file_get_data(stream_file, data);
fpo_stream = (SFPOStream *) stream;
fpo_stream->fpo_data_list = r_list_new();
curr_read_bytes = 0;
ptmp = data;
while (read_bytes < data_size) {
fpo_data = (SFPO_DATA *) malloc(sizeof(SFPO_DATA));
curr_read_bytes = parse_fpo_data(ptmp, data_size, &read_bytes, fpo_data);
ptmp += curr_read_bytes;
if (!curr_read_bytes) {
free(fpo_data);
break;
}
r_list_append(fpo_stream->fpo_data_list, fpo_data);
}
free(data);
}
///////////////////////////////////////////////////////////////////////////////
void free_fpo_stream(void *stream)
{
SFPOStream *fpo_stream = (SFPOStream *) stream;
RListIter *it = 0;
SFPO_DATA *fpo_data = 0;
it = r_list_iterator(fpo_stream->fpo_data_list);
while (r_list_iter_next(it)) {
fpo_data = (SFPO_DATA *) r_list_iter_get(it);
free(fpo_data);
}
r_list_free(fpo_stream->fpo_data_list);
}
///////////////////////////////////////////////////////////////////////////////
void free_fpo_new_stream(void *stream)
{
SFPONewStream *fpo_stream = (SFPONewStream *) stream;
RListIter *it = 0;
SFPO_DATA_V2 *fpo_data = 0;
it = r_list_iterator(fpo_stream->fpo_data_list);
while (r_list_iter_next(it)) {
fpo_data = (SFPO_DATA_V2 *) r_list_iter_get(it);
free(fpo_data);
}
r_list_free(fpo_stream->fpo_data_list);
}
///////////////////////////////////////////////////////////////////////////////
void parse_fpo_new_stream(void *stream, R_STREAM_FILE *stream_file)
{
int data_size;
char *data = 0, *ptmp = 0;
int curr_read_bytes = 0, read_bytes = 0;
SFPO_DATA_V2 *fpo_data = 0;
SFPONewStream *fpo_stream = 0;
stream_file_get_size(stream_file, &data_size);
data = (char *) malloc(data_size);
stream_file_get_data(stream_file, data);
fpo_stream = (SFPONewStream *) stream;
fpo_stream->fpo_data_list = r_list_new();
curr_read_bytes = 0;
ptmp = data;
while (read_bytes < data_size) {
fpo_data = (SFPO_DATA_V2 *) malloc(sizeof(SFPO_DATA_V2));
curr_read_bytes = parse_fpo_data_v2(ptmp, data_size, &read_bytes, fpo_data);
ptmp += curr_read_bytes;
if (!curr_read_bytes) {
free(fpo_data);
break;
}
r_list_append(fpo_stream->fpo_data_list, fpo_data);
}
free(data);
}

12
libr/bin/pdb/fpo.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef FPO_H
#define FPO_H
#include "types.h"
void free_fpo_stream(void *stream);
void parse_fpo_stream(void *stream, R_STREAM_FILE *stream_file);
void free_fpo_new_stream(void *stream);
void parse_fpo_new_stream(void *stream, R_STREAM_FILE *stream_file);
#endif // FPO_H

76
libr/bin/pdb/gdata.c Normal file
View File

@ -0,0 +1,76 @@
#include "gdata.h"
#include "stream_file.h"
#include "tpi.h"
///////////////////////////////////////////////////////////////////////////////
static void parse_global(char *data, int data_size, SGlobal *global)
{
unsigned int read_bytes = 2;
READ(read_bytes, 4, data_size, global->symtype, data, unsigned int);
READ(read_bytes, 4, data_size, global->offset, data, unsigned int);
READ(read_bytes, 2, data_size, global->segment, data, unsigned short);
if (global->leaf_type == 0x110E) {
parse_sctring(&global->name, (unsigned char *)data, &read_bytes, data_size);
} else {
READ(read_bytes, 1, data_size, global->name.size, data, unsigned char);
init_scstring(&global->name, global->name.size, data);
}
}
///////////////////////////////////////////////////////////////////////////////
void parse_gdata_stream(void *stream, R_STREAM_FILE *stream_file)
{
unsigned short len = 0;
unsigned short leaf_type = 0;
char *data = 0;
SGDATAStream *data_stream = (SGDATAStream *) stream;
SGlobal *global = 0;
data_stream->globals_list = r_list_new();
while (1) {
stream_file_read(stream_file, 2, (char *)&len);
if (len == 0)
break;
data = (char *) malloc(len);
stream_file_read(stream_file, len, data);
leaf_type = *(unsigned short *) (data);
if ((leaf_type == 0x110E) || (leaf_type == 0x1009)) {
global = (SGlobal *) malloc(sizeof(SGlobal));
global->leaf_type = leaf_type;
parse_global(data + 2, len, global);
r_list_append(data_stream->globals_list, global);
}
free(data);
}
// TODO: for more fast access
// for g in self.globals:
// if not hasattr(g, 'symtype'): continue
// if g.symtype == 0:
// if g.name.startswith("_"):
// self.vars[g.name[1:]] = g
// else:
// self.vars[g.name] = g
// elif g.symtype == 2:
// self.funcs[g.name] = g
}
///////////////////////////////////////////////////////////////////////////////
void free_gdata_stream(void *stream)
{
SGDATAStream *data_stream = (SGDATAStream *) stream;
SGlobal *global = 0;
RListIter *it = 0;
it = r_list_iterator(data_stream->globals_list);
while (r_list_iter_next(it)) {
global = (SGlobal *) r_list_iter_get(it);
if (global->name.name)
free(global->name.name);
free(global);
}
r_list_free(data_stream->globals_list);
}

9
libr/bin/pdb/gdata.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef GDATA_H
#define GDATA_H
#include "types.h"
void parse_gdata_stream(void *stream, R_STREAM_FILE *stream_file);
void free_gdata_stream(void *stream);
#endif // GDATA_H

135
libr/bin/pdb/omap.c Normal file
View File

@ -0,0 +1,135 @@
#include "omap.h"
#include "types.h"
///////////////////////////////////////////////////////////////////////////////
static int parse_omap_entry(char *data, int data_size, int *read_bytes, SOmapEntry *omap_entry)
{
int curr_read_bytes = *read_bytes;
memcpy(omap_entry, data, sizeof(SOmapEntry));
*read_bytes += sizeof(SOmapEntry);
return (*read_bytes - curr_read_bytes);
}
///////////////////////////////////////////////////////////////////////////////
void parse_omap_stream(void *stream, R_STREAM_FILE *stream_file)
{
int data_size;
char *data = 0, *ptmp = 0;
int curr_read_bytes = 0, read_bytes = 0;
SOmapEntry *omap_entry = 0;
SOmapStream *omap_stream = 0;
stream_file_get_size(stream_file, &data_size);
data = (char *) malloc(data_size);
stream_file_get_data(stream_file, data);
omap_stream = (SOmapStream *) stream;
omap_stream->froms = 0;
omap_stream->omap_entries = r_list_new();
curr_read_bytes = 0;
ptmp = data;
while (read_bytes < data_size) {
omap_entry = (SOmapEntry *) malloc(sizeof(SOmapEntry));
curr_read_bytes = parse_omap_entry(ptmp, data_size, &read_bytes, omap_entry);
ptmp += curr_read_bytes;
if (!curr_read_bytes) {
free(omap_entry);
break;
}
r_list_append(omap_stream->omap_entries, omap_entry);
}
free(data);
}
///////////////////////////////////////////////////////////////////////////////
void free_omap_stream(void *stream)
{
SOmapStream *omap_stream = (SOmapStream *) stream;
RListIter *it = 0;
SOmapEntry *omap_entry = 0;
it = r_list_iterator(omap_stream->omap_entries);
while (r_list_iter_next(it)) {
omap_entry = (SOmapEntry *) r_list_iter_get(it);
free(omap_entry);
}
r_list_free(omap_stream->omap_entries);
}
// 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;
}
// 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;
else
return -1;
}
///////////////////////////////////////////////////////////////////////////////
int omap_remap(void *stream, int address)
{
SOmapStream *omap_stream = (SOmapStream *) stream;
SOmapEntry *omap_entry = 0;
RListIter *it = 0;
int i = 0;
int pos = 0;
int len = 0;
if (!omap_stream) {
return address;
}
len = r_list_length(omap_stream->omap_entries);
if (omap_stream->froms == 0) {
omap_stream->froms = (unsigned int *) malloc(4 * len);
it = r_list_iterator(omap_stream->omap_entries);
while (r_list_iter_next(it)) {
omap_entry = (SOmapEntry *) r_list_iter_get(it);
omap_stream->froms[i] = omap_entry->from;
i++;
}
}
// mb (len -1) ???
pos = binary_search(omap_stream->froms, address, 0, (len));
if (omap_stream->froms[pos] != address) {
pos -= 1;
}
omap_entry = (SOmapEntry *) r_list_get_n(omap_stream->omap_entries, pos);
if (omap_entry->to == 0) {
return omap_entry->to;
} else {
return omap_entry->to + (address - omap_entry->from);
}
}

10
libr/bin/pdb/omap.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef OMAP_H
#define OMAP_H
#include "types.h"
void parse_omap_stream(void *stream, R_STREAM_FILE *stream_file);
void free_omap_stream(void *stream);
int omap_remap(void *stream, int address);
#endif // OMAP_H

742
libr/bin/pdb/pdb.c Normal file
View File

@ -0,0 +1,742 @@
#include <r_pdb.h>
#include <string.h>
#include "stream_file.h"
#include "types.h"
#include "tpi.h"
#include "dbi.h"
#include "fpo.h"
#include "gdata.h"
#include "pe.h"
#include "omap.h"
#define PDB2_SIGNATURE "Microsoft C/C++ program database 2.00\r\n\032JG\0\0"
#define PDB7_SIGNATURE "Microsoft C/C++ MSF 7.00\r\n\x1ADS\0\0\0"
#define PDB7_SIGNATURE_LEN 32
#define PDB2_SIGNATURE_LEN 51
typedef void (*parse_stream_)(void *stream, R_STREAM_FILE *stream_file);
typedef struct {
int indx;
parse_stream_ parse_stream;
void *stream;
EStream type;
free_func free;
} SStreamParseFunc;
///////////////////////////////////////////////////////////////////////////////
static void free_pdb_stream(void *stream)
{
R_PDB_STREAM *pdb_stream = (R_PDB_STREAM *) stream;
if (pdb_stream) {
if (pdb_stream->pages) {
// free(pdb_stream->pages);
pdb_stream->pages = 0;
}
}
}
//static void pdb_stream_get_data(R_PDB_STREAM *pdb_stream, char *data)
//{
// int pos = stream_file_tell(&pdb_stream->stream_file);
// stream_file_seek(&pdb_stream->stream_file, 0, 0);
// stream_file_read(&pdb_stream->stream_file, -1, data);
// stream_file_seek(&pdb_stream->stream_file, pos, 0);
//}
///////////////////////////////////////////////////////////////////////////////
/// size - default value = -1
/// page_size - default value = 0x1000
///////////////////////////////////////////////////////////////////////////////
static int init_r_pdb_stream(R_PDB_STREAM *pdb_stream, FILE *fp, int *pages,
int pages_amount, int index, int size, int page_size)
{
// printf("init_r_pdb_stream()\n");
pdb_stream->fp = fp;
pdb_stream->pages = pages;
pdb_stream->indx = index;
pdb_stream->page_size = page_size;
pdb_stream->pages_amount = pages_amount;
if (size == -1) {
pdb_stream->size = pages_amount * page_size;
} else {
pdb_stream->size = size;
}
init_r_stream_file(&(pdb_stream->stream_file), fp, pages, pages_amount, size, page_size);
pdb_stream->free_ = free_pdb_stream;
return 1;
}
///////////////////////////////////////////////////////////////////////////////
static int read_int_var(char *var_name, int *var, FILE *fp)
{
int bytes_read = fread(var, 4, 1, fp);
if (bytes_read != 1) {
printf("error while reading from file [%s]", var_name);
return 0;
}
return 1;
}
///////////////////////////////////////////////////////////////////////////////
static int count_pages(int length, int page_size)
{
int num_pages = 0;
num_pages = length / page_size;
if (length % page_size)
num_pages++;
return num_pages;
}
///////////////////////////////////////////////////////////////////////////////
static int init_pdb7_root_stream(R_PDB *pdb, int *root_page_list, int pages_amount,
EStream indx, int root_size, int page_size)
{
int num_streams = 0;
char *data = 0;
char *tmp_data = 0;
int *tmp_sizes = 0;
int num_pages = 0;
int i = 0;
int *sizes = 0;
int stream_size = 0;
int pos = 0;
int pn_start, off_start;
R_PDB_STREAM *pdb_stream = 0;
int data_size = 0;
char *tmp;
R_PDB7_ROOT_STREAM *root_stream7;
pdb->root_stream = (R_PDB7_ROOT_STREAM *) malloc(sizeof(R_PDB7_ROOT_STREAM));
init_r_pdb_stream(pdb->root_stream, pdb->fp, root_page_list, pages_amount,
indx, root_size, page_size);
root_stream7 = pdb->root_stream;
pdb_stream = &(root_stream7->pdb_stream);
stream_file_get_size(&pdb_stream->stream_file, &data_size);
data = (char *) malloc(data_size);
stream_file_get_data(&pdb_stream->stream_file, data);
num_streams = *(int *)data;
tmp_data = data;
tmp_data += 4;
root_stream7->num_streams = num_streams;
sizes = (int *) malloc(num_streams * 4);
for (i = 0; i < num_streams; i++) {
stream_size = *(int *)(tmp_data);
tmp_data += 4;
if (stream_size == 0xffffffff) {
stream_size = 0;
}
memcpy(sizes + i, &stream_size, 4);
}
// char *tmp_file_name = (char *) malloc(strlen("/root/test.pdb.000") + 1);
// short ii;
// FILE *tmp_file;
tmp_data = ((char *)data + num_streams * 4 + 4);
root_stream7->streams_list = r_list_new();
RList *pList = root_stream7->streams_list;
SPage *page = 0;
for (i = 0; i < num_streams; i++) {
num_pages = count_pages(sizes[i], page_size);
tmp = (char *) malloc(num_pages * 4);
memset(tmp, 0, num_pages * 4);
page = (SPage *) malloc(sizeof(SPage));
if (num_pages != 0) {
memcpy(tmp, tmp_data + pos, num_pages * 4);
pos += num_pages * 4;
// sprintf(tmp_file_name, "%s%d", "/root/test.pdb", i);
// tmp_file = fopen(tmp_file_name, "wb");
// fwrite(tmp, num_pages * 4, 1, tmp_file);
// fclose(tmp_file);
page->stream_size = sizes[i];
page->stream_pages = tmp;
page->num_pages = num_pages;
} else {
page->stream_size = 0;
page->stream_pages = 0;
page->num_pages = 0;
free(tmp);
}
r_list_append(pList, page);
}
free(sizes);
free(data);
printf("init_pdb7_root_stream()\n");
return 1;
}
///////////////////////////////////////////////////////////////////////////////
static void init_parsed_pdb_stream(SParsedPDBStream *pdb_stream, FILE *fp, int *pages,
int pages_amount, int index, int size,
int page_size, f_load pLoad)
{
pdb_stream->pdb_stream = (R_PDB_STREAM *) malloc(sizeof(R_PDB_STREAM));
init_r_pdb_stream(pdb_stream->pdb_stream, fp, pages, pages_amount, index, size, page_size);
pdb_stream->load = pLoad;
if (pLoad != NULL) {
pLoad(pdb_stream, &(pdb_stream->pdb_stream->stream_file));
}
}
///////////////////////////////////////////////////////////////////////////////
static void parse_pdb_info_stream(void *parsed_pdb_stream, R_STREAM_FILE *stream)
{
SPDBInfoStream *tmp = (SPDBInfoStream *)parsed_pdb_stream;
tmp->names = 0;
stream_file_read(stream, 4, (char *)&tmp->/*data.*/version);
stream_file_read(stream, 4, (char *)&tmp->/*data.*/time_date_stamp);
stream_file_read(stream, 4, (char *)&tmp->/*data.*/age);
stream_file_read(stream, 4, (char *)&tmp->/*data.*/guid.data1);
stream_file_read(stream, 2, (char *)&tmp->/*data.*/guid.data2);
stream_file_read(stream, 2, (char *)&tmp->/*data.*/guid.data3);
stream_file_read(stream, 8, (char *)&tmp->/*data.*/guid.data4);
stream_file_read(stream, 4, (char *)&tmp->/*data.*/cb_names);
tmp->/*data.*/names = (char *) malloc(tmp->/*data.*/cb_names);
stream_file_read(stream, tmp->/*data.*/cb_names, tmp->/*data.*/names);
}
///////////////////////////////////////////////////////////////////////////////
static void free_info_stream(void *stream)
{
SPDBInfoStream *info_stream = (SPDBInfoStream *)stream;
free(info_stream->names);
}
///////////////////////////////////////////////////////////////////////////////
#define ADD_INDX_TO_LIST(list, index, stream_size, stream_type, free_func, parse_func) { \
if (index != -1) { \
SStreamParseFunc *stream_parse_func = (SStreamParseFunc *) malloc(sizeof(SStreamParseFunc)); \
stream_parse_func->indx = (index); \
stream_parse_func->type = (stream_type); \
stream_parse_func->parse_stream = (parse_func); \
stream_parse_func->free = (free_func); \
if (stream_size) { \
stream_parse_func->stream = malloc(stream_size); \
} else { \
stream_parse_func->stream = 0; \
} \
r_list_append((list), stream_parse_func); \
} \
}
///////////////////////////////////////////////////////////////////////////////
static void fill_list_for_stream_parsing(RList *l, SDbiStream *dbi_stream)
{
ADD_INDX_TO_LIST(l, dbi_stream->dbi_header.symrecStream, sizeof(SGDATAStream),
ePDB_STREAM_GSYM, free_gdata_stream, parse_gdata_stream);
ADD_INDX_TO_LIST(l, dbi_stream->dbg_header.sn_section_hdr, sizeof(SPEStream),
ePDB_STREAM_SECT_HDR, free_pe_stream, parse_pe_stream);
ADD_INDX_TO_LIST(l, dbi_stream->dbg_header.sn_section_hdr_orig, sizeof(SPEStream),
ePDB_STREAM_SECT__HDR_ORIG, free_pe_stream, parse_pe_stream);
ADD_INDX_TO_LIST(l, dbi_stream->dbg_header.sn_omap_to_src, sizeof(SOmapStream),
ePDB_STREAM_OMAP_TO_SRC, free_omap_stream, parse_omap_stream);
ADD_INDX_TO_LIST(l, dbi_stream->dbg_header.sn_omap_from_src, sizeof(SOmapStream),
ePDB_STREAM_OMAP_FROM_SRC, free_omap_stream, parse_omap_stream);
ADD_INDX_TO_LIST(l, dbi_stream->dbg_header.sn_fpo, sizeof(SFPOStream),
ePDB_STREAM_FPO, free_fpo_stream, parse_fpo_stream);
ADD_INDX_TO_LIST(l, dbi_stream->dbg_header.sn_new_fpo, sizeof(SFPONewStream),
ePDB_STREAM_FPO_NEW, free_fpo_stream, parse_fpo_new_stream);
// unparsed, but know their names
ADD_INDX_TO_LIST(l, dbi_stream->dbg_header.sn_xdata, 0, ePDB_STREAM_XDATA, 0, 0);
ADD_INDX_TO_LIST(l, dbi_stream->dbg_header.sn_pdata, 0, ePDB_STREAM_PDATA, 0, 0);
ADD_INDX_TO_LIST(l, dbi_stream->dbg_header.sn_token_rid_map, 0, ePDB_STREAM_TOKEN_RID_MAP, 0, 0);
}
///////////////////////////////////////////////////////////////////////////////
static void find_indx_in_list(RList *l, int index, SStreamParseFunc **res)
{
SStreamParseFunc *stream_parse_func = 0;
RListIter *it = 0;
*res = 0;
it = r_list_iterator(l);
while (r_list_iter_next(it)) {
stream_parse_func = (SStreamParseFunc *) r_list_iter_get(it);
if (index == stream_parse_func->indx) {
*res = stream_parse_func;
return;
}
}
}
///////////////////////////////////////////////////////////////////////////////
static int pdb_read_root(R_PDB *pdb)
{
int i = 0;
RList *pList = pdb->pdb_streams;
R_PDB7_ROOT_STREAM *root_stream = pdb->root_stream;
R_PDB_STREAM *pdb_stream = 0;
SParsedPDBStream *parsed_pdb_stream = 0;
SPDBInfoStream *pdb_info_stream = 0;
STpiStream *tpi_stream = 0;
R_STREAM_FILE stream_file;
RListIter *it;
SPage *page = 0;
RList *tmp_list = 0;
SStreamParseFunc *stream_parse_func = 0;
it = r_list_iterator(root_stream->streams_list);
while (r_list_iter_next(it)) {
page = (SPage*) r_list_iter_get(it);
init_r_stream_file(&stream_file, pdb->fp, page->stream_pages,
page->num_pages/*root_stream->pdb_stream.pages_amount*/,
page->stream_size,
root_stream->pdb_stream.page_size);
switch (i) {
//TODO: rewrite for style like for streams from dbg stream
// look default
case ePDB_STREAM_PDB:
pdb_info_stream = (SPDBInfoStream *) malloc(sizeof(SPDBInfoStream));
pdb_info_stream->free_ = free_info_stream;
parse_pdb_info_stream(pdb_info_stream, &stream_file);
r_list_append(pList, pdb_info_stream);
break;
case ePDB_STREAM_TPI:
tpi_stream = (STpiStream *) malloc(sizeof(STpiStream));
init_tpi_stream(tpi_stream);
parse_tpi_stream(tpi_stream, &stream_file);
r_list_append(pList, tpi_stream);
break;
case ePDB_STREAM_DBI:
{
SDbiStream *dbi_stream = (SDbiStream *) malloc(sizeof(SDbiStream));
init_dbi_stream(dbi_stream);
parse_dbi_stream(dbi_stream, &stream_file);
r_list_append(pList, dbi_stream);
pdb->pdb_streams2 = r_list_new();
fill_list_for_stream_parsing(pdb->pdb_streams2, dbi_stream);
break;
}
default:
find_indx_in_list(pdb->pdb_streams2, i, &stream_parse_func);
if (stream_parse_func) {
if (stream_parse_func->parse_stream) {
stream_parse_func->parse_stream(stream_parse_func->stream,
&stream_file);
break;
}
}
pdb_stream = (R_PDB_STREAM *) malloc(sizeof(R_PDB_STREAM));
init_r_pdb_stream(pdb_stream, pdb->fp, page->stream_pages,
root_stream->pdb_stream.pages_amount, i,
page->stream_size,
root_stream->pdb_stream.page_size);
r_list_append(pList, pdb_stream);
break;
}
i++;
}
return 1;
}
///////////////////////////////////////////////////////////////////////////////
static int pdb7_parse(R_PDB *pdb)
{
printf("pdb7_parse()\n");
char signature[PDB7_SIGNATURE_LEN + 1];
int page_size = 0;
int alloc_tbl_ptr = 0;
int num_file_pages = 0;
int root_size = 0;
int reserved = 0;
int num_root_pages = 0;
int num_root_index_pages = 0;
int *root_index_pages = 0;
void *root_page_data = 0;
int *root_page_list = 0;
int i = 0;
void *p_tmp;
int bytes_read = 0;
bytes_read = fread(signature, 1, PDB7_SIGNATURE_LEN, pdb->fp);
if (bytes_read != PDB7_SIGNATURE_LEN) {
printf("error while reading PDB7_SIGNATURE\n");
goto error;
}
if (read_int_var("page_size", &page_size, pdb->fp) == 0) {
goto error;
}
if (read_int_var("alloc_tbl_ptr", &alloc_tbl_ptr, pdb->fp) == 0) {
goto error;
}
if (read_int_var("num_file_pages", &num_file_pages, pdb->fp) == 0) {
goto error;
}
if (read_int_var("root_size", &root_size, pdb->fp) == 0) {
goto error;
}
if (read_int_var("reserved", &reserved, pdb->fp) == 0) {
goto error;
}
// FIXME: why they is not equal ????
// if (memcmp(signature, PDB7_SIGNATURE, PDB7_SIGNATURE_LEN) != 0) {
// printf("Invalid signature for PDB7 format\n");
// //goto error;
// }
num_root_pages = count_pages(root_size, page_size);
num_root_index_pages = count_pages((num_root_pages * 4), page_size);
root_index_pages = (int *)malloc(sizeof(int) * num_root_index_pages);
if (!root_index_pages) {
printf("error memory allocation\n");
goto error;
}
bytes_read = fread(root_index_pages, 4, num_root_index_pages, pdb->fp);
if (bytes_read != num_root_index_pages) {
printf("error while reading root_index_pages\n");
goto error;
}
root_page_data = (int *)malloc(page_size * num_root_index_pages);
if (!root_page_data) {
printf("error memory allocation of root_page_data\n");
goto error;
}
p_tmp = root_page_data;
for (i = 0; i < num_root_index_pages; i++) {
fseek(pdb->fp, root_index_pages[i] * page_size, SEEK_SET);
fread(p_tmp, page_size, 1, pdb->fp);
p_tmp = (char *)p_tmp + page_size;
}
root_page_list = (int *)malloc(sizeof(int) * num_root_pages);
if (!root_page_list) {
printf("error: memory allocation of root page\n");
goto error;
}
p_tmp = root_page_data;
for (i = 0; i < num_root_pages; i++) {
root_page_list[i] = *((int *)p_tmp);
p_tmp = (int *)p_tmp + 1;
}
pdb->pdb_streams2 = 0;
init_pdb7_root_stream(pdb, root_page_list, num_root_pages, ePDB_STREAM_ROOT, root_size, page_size);
pdb_read_root(pdb);
if (root_page_list) {
free(root_page_list);
root_page_list = 0;
}
if (root_page_data) {
free(root_page_data);
root_page_data = 0;
}
if (root_index_pages) {
free(root_index_pages);
root_index_pages = 0;
}
return 1;
error:
if (root_page_list) {
free(root_page_list);
root_page_list = 0;
}
if (root_page_data) {
free(root_page_data);
root_page_data = 0;
}
if (root_index_pages) {
free(root_index_pages);
root_index_pages = 0;
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
static void finish_pdb_parse(R_PDB *pdb)
{
R_PDB7_ROOT_STREAM *p = pdb->root_stream;
RListIter *it;
SPage *page = 0;
it = r_list_iterator(p->streams_list);
while (r_list_iter_next(it)) {
page = (SPage *) r_list_iter_get(it);
free(page->stream_pages);
page->stream_pages = 0;
free(page);
page = 0;
}
r_list_free(p->streams_list);
p->streams_list = 0;
free(p);
p = 0;
// end of free of R_PDB7_ROOT_STREAM
// TODO: maybe create some kind of destructor?
// free of pdb->pdb_streams
// SParsedPDBStream *parsed_pdb_stream = 0;
SPDBInfoStream *pdb_info_stream = 0;
STpiStream *tpi_stream = 0;
SDbiStream *dbi_stream = 0;
SStreamParseFunc *stream_parse_func;
R_PDB_STREAM *pdb_stream = 0;
int i = 0;
it = r_list_iterator(pdb->pdb_streams);
while (r_list_iter_next(it)) {
switch (i) {
case 1:
pdb_info_stream = (SPDBInfoStream *) r_list_iter_get(it);
pdb_info_stream->free_(pdb_info_stream);
free(pdb_info_stream);
break;
case 2:
tpi_stream = (STpiStream *) r_list_iter_get(it);
tpi_stream->free_(tpi_stream);
free(tpi_stream);
break;
case 3:
dbi_stream = (SDbiStream *) r_list_iter_get(it);
dbi_stream->free_(dbi_stream);
free(dbi_stream);
break;
default:
find_indx_in_list(pdb->pdb_streams2, i, &stream_parse_func);
if (stream_parse_func) {
break;
}
pdb_stream = (R_PDB_STREAM *) r_list_iter_get(it);
pdb_stream->free_(pdb_stream);
free(pdb_stream);
break;
}
i++;
}
r_list_free(pdb->pdb_streams);
// enf of free of pdb->pdb_streams
// start of free pdb->pdb_streams2
it = r_list_iterator(pdb->pdb_streams2);
while (r_list_iter_next(it)) {
stream_parse_func = (SStreamParseFunc *) r_list_iter_get(it);
if (stream_parse_func->free) {
stream_parse_func->free(stream_parse_func->stream);
free(stream_parse_func->stream);
}
free(stream_parse_func);
}
r_list_free(pdb->pdb_streams2);
// end of free pdb->streams2
if (pdb->stream_map)
free(pdb->stream_map);
fclose(pdb->fp);
printf("finish_pdb_parse()\n");
}
///////////////////////////////////////////////////////////////////////////////
static void print_types(R_PDB *pdb)
{
printf("print_types()\n");
char *name;
int val = 0;
int offset = 0;
SType *t = 0;
STypeInfo *tf = 0;
RListIter *it = 0, *it2 = 0;
RList *plist = pdb->pdb_streams, *ptmp;
STpiStream *tpi_stream = r_list_get_n(plist, ePDB_STREAM_TPI);
it = r_list_iterator(tpi_stream->types);
while (r_list_iter_next(it)) {
t = (SType *) r_list_iter_get(it);
tf = &t->type_data;
if ((tf->leaf_type == eLF_STRUCTURE) || (tf->leaf_type == eLF_UNION)) {
tf->is_fwdref(tf, &val);
if (val == 1) {
continue;
}
tf->get_name(tf, &name);
// val for STRUCT or UNION mean size
tf->get_val(tf, &val);
printf("%s: size 0x%x\n", name, val);
tf->get_members(tf, &ptmp);
it2 = r_list_iterator(ptmp);
while (r_list_iter_next(it2)) {
tf = (STypeInfo *) r_list_iter_get(it2);
tf->get_name(tf, &name);
if (tf->get_val)
tf->get_val(tf, &offset);
else
offset = 0;
printf("\t0x%x: %s type:", offset, name);
tf->get_print_type(tf, &name);
printf("%s\n", name);
free(name);
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
static void print_gvars(R_PDB *pdb, int img_base)
{
RList *l = 0;
RListIter *it = 0, *it1 = 0;
SStreamParseFunc *omap = 0, *sctns = 0, *sctns_orig = 0 ,
*gsym = 0, *tmp = 0;
SGDATAStream *gsym_data_stream = 0;
SGlobal *gdata = 0;
SPEStream *pe_stream = 0;
SIMAGE_SECTION_HEADER *sctn_header = 0;
l = pdb->pdb_streams2;
it = r_list_iterator(l);
while (r_list_iter_next(it)) {
tmp = (SStreamParseFunc *) r_list_iter_get(it);
switch (tmp->type) {
case ePDB_STREAM_SECT__HDR_ORIG:
sctns_orig = tmp;
break;
case ePDB_STREAM_SECT_HDR:
sctns = tmp;
break;
case ePDB_STREAM_OMAP_FROM_SRC:
omap = tmp;
break;
case ePDB_STREAM_GSYM:
gsym = tmp;
break;
default:
break;
}
}
gsym_data_stream = (SGDATAStream *) gsym->stream;
if ((omap != 0) && (sctns_orig != 0)) {
pe_stream = (SPEStream *) sctns_orig->stream;
} else {
pe_stream = (SPEStream *) sctns->stream;
}
it = r_list_iterator(gsym_data_stream->globals_list);
while (r_list_iter_next(it)) {
gdata = (SGlobal *) r_list_iter_get(it);
sctn_header = r_list_get_n(pe_stream->sections_hdrs, (gdata->segment -1));
if (sctn_header) {
printf("%s, 0x%x, %d, %s\n",
gdata->name.name, img_base + omap_remap((omap) ? (omap->stream) : 0,
gdata->offset + sctn_header->virtual_address),
gdata->symtype, sctn_header->name);
} else {
printf("Skipping %s, segment %d does not exist\n",
gdata->name.name, (gdata->segment -1));
}
}
}
///////////////////////////////////////////////////////////////////////////////
int init_pdb_parser(R_PDB *pdb)
{
char *signature = 0;
int bytes_read = 0;
if (!pdb) {
printf("struct R_PDB is not correct\n");
goto error;
}
pdb->fp = fopen(pdb->file_name, "rb");
if (!pdb->fp) {
printf("file %s can not be open\n", pdb->file_name);
goto error;
}
signature = (char *)malloc(sizeof(char) * PDB7_SIGNATURE_LEN);
if (!signature) {
printf("memory allocation error\n");
goto error;
}
bytes_read = fread(signature, 1, PDB7_SIGNATURE_LEN, pdb->fp);
if (bytes_read != PDB7_SIGNATURE_LEN) {
printf("file reading error\n");
goto error;
}
fseek(pdb->fp, 0, SEEK_SET);
if (memcmp(signature, PDB7_SIGNATURE, PDB7_SIGNATURE_LEN)) {
pdb->pdb_parse =pdb7_parse;
} else {
printf("unsupported pdb format\n");
goto error;
}
if (signature) {
free(signature);
signature = 0;
}
pdb->pdb_streams = r_list_new();
pdb->stream_map = 0;
pdb->finish_pdb_parse = finish_pdb_parse;
pdb->print_types = print_types;
pdb->print_gvars = print_gvars;
printf("init_pdb_parser() finish with success\n");
return 1;
error:
if (signature) {
free(signature);
signature = 0;
}
return 0;
}

46
libr/bin/pdb/pe.c Normal file
View File

@ -0,0 +1,46 @@
#include "pe.h"
#include "stream_file.h"
///////////////////////////////////////////////////////////////////////////////
void parse_pe_stream(void *stream, R_STREAM_FILE *stream_file)
{
int data_size = 0;
char *data = 0, *ptmp = 0;
int read_bytes = 0;
SIMAGE_SECTION_HEADER *sctn_header = 0;
SPEStream *pe_stream = (SPEStream *) stream;
int sctn_header_size =0;
stream_file_get_size(stream_file, &data_size);
data = (char *) malloc(data_size);
stream_file_get_data(stream_file, data);
sctn_header_size = sizeof(SIMAGE_SECTION_HEADER);
ptmp = data;
pe_stream->sections_hdrs = r_list_new();
while (read_bytes < data_size) {
sctn_header = (SIMAGE_SECTION_HEADER *) malloc (sctn_header_size);
memcpy(sctn_header, ptmp, sctn_header_size);
ptmp += sctn_header_size;
r_list_append(pe_stream->sections_hdrs, sctn_header);
read_bytes += sctn_header_size;
}
free(data);
}
///////////////////////////////////////////////////////////////////////////////
void free_pe_stream(void *stream)
{
SPEStream *pe_stream = (SPEStream *) stream;
SIMAGE_SECTION_HEADER *sctn_header = 0;
RListIter *it = 0;
it = r_list_iterator(pe_stream->sections_hdrs);
while (r_list_iter_next(it)) {
sctn_header = (SIMAGE_SECTION_HEADER *) r_list_iter_get(it);
free(sctn_header);
}
r_list_free(pe_stream->sections_hdrs);
}

9
libr/bin/pdb/pe.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef PE_H
#define PE_H
#include "types.h"
void parse_pe_stream(void *stream, R_STREAM_FILE *stream_file);
void free_pe_stream(void *stream);
#endif // PE_H

120
libr/bin/pdb/stream_file.c Normal file
View File

@ -0,0 +1,120 @@
#include "stream_file.h"
///////////////////////////////////////////////////////////////////////////////
/// size = -1 (default value)
/// pages_size = 0x1000 (default value)
////////////////////////////////////////////////////////////////////////////////
int init_r_stream_file(R_STREAM_FILE *stream_file, FILE *fp, int *pages,
int pages_amount, int size, int page_size)
{
stream_file->fp = fp;
stream_file->pages = pages;
stream_file->pages_amount = pages_amount;
stream_file->page_size = page_size;
if (size == -1) {
stream_file->end = pages_amount * page_size;
} else {
stream_file->end = size;
}
stream_file->pos = 0;
return 1;
}
///////////////////////////////////////////////////////////////////////////////
static void stream_file_read_pages(R_STREAM_FILE *stream_file, int start_indx,
int end_indx, char *res)
{
int i;
int page_offset;
int curr_pos;
int tmp;
// char buffer[1024];
for (i = start_indx; i < end_indx; i++) {
tmp = stream_file->pages[i];
page_offset = stream_file->pages[i] * stream_file->page_size;
fseek(stream_file->fp, page_offset, SEEK_SET);
// curr_pos = ftell(stream_file->fp);
fread(res, stream_file->page_size, 1, stream_file->fp);
res += stream_file->page_size;
}
}
// size by default = -1
///////////////////////////////////////////////////////////////////////////////
void stream_file_read(R_STREAM_FILE *stream_file, int size, char *res)
{
int pn_start, off_start, pn_end, off_end;
int i = 0;
char *pdata = 0;
char *tmp;
int len = 0;
if (size == -1) {
pdata = (char *) malloc(stream_file->pages_amount * stream_file->page_size);
GET_PAGE(pn_start, off_start, stream_file->pos, stream_file->page_size);
tmp = pdata;
stream_file_read_pages(stream_file, 0, stream_file->pages_amount, tmp);
stream_file->pos = stream_file->end;
memcpy(res, pdata + off_start, stream_file->end - off_start);
free(pdata);
} else {
GET_PAGE(pn_start, off_start, stream_file->pos, stream_file->page_size);
GET_PAGE(pn_end, off_end, stream_file->pos + size, stream_file->page_size);
pdata = (char *) malloc(stream_file->page_size * (pn_end + 1 - pn_start));
tmp = pdata;
stream_file_read_pages(stream_file, pn_start, pn_end + 1, tmp);
stream_file->pos += size;
memcpy(res, pdata + off_start, size);
free(pdata);
}
}
///////////////////////////////////////////////////////////////////////////////
void stream_file_seek(R_STREAM_FILE *stream_file, int offset, int whence)
{
switch (whence) {
case 0:
stream_file->pos = offset;
break;
case 1:
stream_file->pos += offset;
break;
case 2:
stream_file->pos = stream_file->end + offset;
break;
default:
break;
}
if (stream_file->pos < 0) stream_file->pos = 0;
if (stream_file->pos > stream_file->end) stream_file->pos = stream_file->end;
}
///////////////////////////////////////////////////////////////////////////////
int stream_file_tell(R_STREAM_FILE *stream_file)
{
return stream_file->pos;
}
///////////////////////////////////////////////////////////////////////////////
void stream_file_get_data(R_STREAM_FILE *stream_file, char *data)
{
int pos = 0;
pos = stream_file_tell(stream_file);
stream_file_seek(stream_file, 0, 0);
stream_file_read(stream_file, -1, data);
stream_file_seek(stream_file, pos, 0);
}
///////////////////////////////////////////////////////////////////////////////
void stream_file_get_size(R_STREAM_FILE *stream_file, int *data_size)
{
int pn_start = 0, off_start = 0;
GET_PAGE(pn_start, off_start, stream_file->pos, stream_file->page_size);
*data_size = stream_file->end - off_start;
}

View File

@ -0,0 +1,30 @@
#ifndef STREAM_FILE_H
#define STREAM_FILE_H
#include <stdio.h>
#include "types.h"
///////////////////////////////////////////////////////////////////////////////
/// size = -1 (default value)
/// pages_size = 0x1000 (default value)
////////////////////////////////////////////////////////////////////////////////
int init_r_stream_file(R_STREAM_FILE *stream_file, FILE *fp, int *pages,
int pages_amount, int size, int page_size);
// size by default = -1
///////////////////////////////////////////////////////////////////////////////
void stream_file_read(R_STREAM_FILE *stream_file, int size, char *res);
///////////////////////////////////////////////////////////////////////////////
void stream_file_seek(R_STREAM_FILE *stream_file, int offset, int whence);
///////////////////////////////////////////////////////////////////////////////
int stream_file_tell(R_STREAM_FILE *stream_file);
///////////////////////////////////////////////////////////////////////////////
void stream_file_get_data(R_STREAM_FILE *stream_file, char *data);
///////////////////////////////////////////////////////////////////////////////
void stream_file_get_size(R_STREAM_FILE *stream_file, int *data_size);
#endif // STREAM_FILE_H

2189
libr/bin/pdb/tpi.c Normal file

File diff suppressed because it is too large Load Diff

17
libr/bin/pdb/tpi.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef TPI_H
#define TPI_H
#include "types.h"
///////////////////////////////////////////////////////////////////////////////
void init_tpi_stream(STpiStream *tpi_stream);
///////////////////////////////////////////////////////////////////////////////
void parse_tpi_stream(void *parsed_pdb_stream, R_STREAM_FILE *stream);
// TODO: Remove to separate file
void parse_sctring(SCString *sctr, unsigned char *leaf_data, unsigned int *read_bytes, unsigned int len);
///////////////////////////////////////////////////////////////////////////////
void init_scstring(SCString *cstr, unsigned int size, char *name);
#endif // TPI_H

1201
libr/bin/pdb/types.h Normal file

File diff suppressed because it is too large Load Diff

37
libr/include/r_pdb.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef R2_PDB_H
#define R2_PDB_H
#define _R_LIST_C
#include "r_util.h"
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#define FILE_NAME_LEN 256
struct R_PDB7_ROOT_STREAM;
typedef struct {
int (*pdb_parse)(struct R_PDB *pdb);
void (*finish_pdb_parse)(struct R_PDB *pdb);
void (*print_types)(struct R_PDB *pdb);
char file_name[FILE_NAME_LEN];
FILE *fp;
struct R_PDB7_ROOT_STREAM *root_stream;
void *stream_map;
RList *pdb_streams;
RList *pdb_streams2;
void (*print_gvars)(struct R_PDB *pdb, int img_base);
} R_PDB;
int init_pdb_parser(R_PDB *pdb);
#ifdef __cplusplus
}
#endif
#endif