Load symbols in modules from PDB (#4025)

* PDB: add module info parsing
* Refactor PDB component
* Refactor PDB/tpi
* Fix read_pascal_string
* Fix memory leaks
* Add test `Modules from PDB`
This commit is contained in:
billow
2023-12-10 14:14:14 +08:00
committed by GitHub
parent 81b6a3850f
commit d5d29fcb37
25 changed files with 2071 additions and 1898 deletions
+199 -217
View File
@@ -9,31 +9,29 @@
#include <rz_analysis.h>
#include "../bin/pdb/pdb.h"
static RzType *parse_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name);
static RzType *parse_regular_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name);
static RzType *parse_type_modifier(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static RzType *parse_type_pointer(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name);
static RzType *parse_type_procedure(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name);
static RzType *parse_type_array(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static void parse_type_arglist(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *arglist, RzPVector /*<RzCallableArg *>*/ *vec);
static RzType *parse_type_mfunction(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name);
static RzType *parse_type_onemethod(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info);
static RzType *parse_type_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name);
static RzType *parse_type_nest(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info);
static RzType *parse_union(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static RzTypeUnionMember *parse_union_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info);
static RzType *parse_structure(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static RzTypeStructMember *parse_struct_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info);
static RzType *parse_enum(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static RzTypeEnumCase *parse_enumerate(RzPdbTpiType *type);
static RzType *pdb_type_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name);
static RzType *modifier_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static RzType *pointer_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name);
static RzType *procedure_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name);
static RzType *array_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static void arglist_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *arglist, RzPVector /*<RzCallableArg *>*/ *vec);
static RzType *mfunction_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name);
static RzType *onemethod_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info);
static RzType *member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name);
static RzType *nest_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *t, char *name);
static RzType *union_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info);
static RzType *class_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static RzTypeStructMember *class_member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *t);
static RzType *enum_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type);
static RzTypeEnumCase *enumerate_parse(RzPdbTpiType *type);
static RzType *pdb_simple_type_parse(const RzTypeDB *typedb, const RzPdbTpiType *type);
static bool is_parsable_type(const TpiLeafType type) {
return (type == LF_STRUCTURE ||
type == LF_UNION ||
type == LF_ENUM ||
type == LF_CLASS ||
type == LF_CLASS_19 ||
type == LF_STRUCTURE_19);
static bool is_parsable_type(const RzPdbTpiType *t) {
const RzPDBTpiKind k = t->kind;
return k == TpiKind_CLASS ||
k == TpiKind_UNION ||
k == TpiKind_ENUM;
}
/**
@@ -49,14 +47,27 @@ static char *create_type_name_from_offset(ut64 offset) {
return str;
}
static RzType *parse_type_array(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
static RzType *pdb_simple_type_parse(const RzTypeDB *typedb, const RzPdbTpiType *type) {
rz_warn_if_fail(type->kind == TpiKind_SIMPLE_TYPE);
const Tpi_LF_SimpleType *simple_type = type->data;
char *error_msg = NULL;
RzType *typ = rz_type_parse_string_single(typedb->parser, simple_type->type, &error_msg);
if (error_msg) {
RZ_LOG_ERROR("%s : Error parsing complex type member \"%s\" type:\n%s\n",
__FUNCTION__, simple_type->type, error_msg);
RZ_FREE(error_msg);
}
return typ;
}
static RzType *array_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
rz_return_val_if_fail(type && stream && typedb, NULL);
Tpi_LF_Array *lf_array = type->data;
RzPdbTpiType *element = rz_bin_pdb_get_type_by_index(stream, lf_array->element_type);
if (!element) {
return NULL;
}
RzType *element_type = parse_type(typedb, stream, element, NULL);
RzType *element_type = pdb_type_parse(typedb, stream, element, NULL);
if (!element_type) {
return NULL;
}
@@ -70,46 +81,12 @@ static RzType *parse_type_array(const RzTypeDB *typedb, RzPdbTpiStream *stream,
return typ;
}
static RzType *parse_regular_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) {
rz_return_val_if_fail(type && stream && typedb, NULL);
switch (type->leaf) {
case LF_CLASS:
case LF_CLASS_19:
// TODO: https://github.com/rizinorg/rizin/issues/1205
RZ_LOG_INFO("%s : LF_CLASS is not handled for now.\n", __FUNCTION__);
break;
case LF_STRUCTURE:
case LF_STRUCTURE_19:
return parse_structure(typedb, stream, type);
case LF_MODIFIER:
return parse_type_modifier(typedb, stream, type);
case LF_ARRAY:
return parse_type_array(typedb, stream, type);
case LF_BITFIELD:
// TODO: we don't have BITFIELD type for now https://github.com/rizinorg/rizin/issues/1240
RZ_LOG_INFO("%s : LF_BITFIELD is not handled for now.\n", __FUNCTION__);
break;
case LF_POINTER:
return parse_type_pointer(typedb, stream, type, name);
case LF_PROCEDURE:
return parse_type_procedure(typedb, stream, type, name);
case LF_UNION:
return parse_union(typedb, stream, type);
case LF_ENUM:
return parse_enum(typedb, stream, type);
default:
RZ_LOG_INFO("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type->leaf);
break;
}
return NULL;
}
static RzType *parse_type_modifier(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
static RzType *modifier_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
rz_return_val_if_fail(type && stream && typedb, NULL);
Tpi_LF_Modifier *lf_modifier = type->data;
RzPdbTpiType *m_utype = rz_bin_pdb_get_type_by_index(stream, lf_modifier->modified_type);
if (m_utype) {
RzType *typ = parse_type(typedb, stream, m_utype, NULL);
RzType *typ = pdb_type_parse(typedb, stream, m_utype, NULL);
if (typ && lf_modifier->umodifier.const_) {
switch (typ->kind) {
case RZ_TYPE_KIND_IDENTIFIER:
@@ -127,7 +104,8 @@ static RzType *parse_type_modifier(const RzTypeDB *typedb, RzPdbTpiStream *strea
return NULL;
}
static RzType *parse_type_pointer(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) {
static RzType *pointer_parse(
const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) {
rz_return_val_if_fail(type && typedb, NULL);
Tpi_LF_Pointer *lf_pointer = type->data;
RzType *typ = RZ_NEW0(RzType);
@@ -137,7 +115,7 @@ static RzType *parse_type_pointer(const RzTypeDB *typedb, RzPdbTpiStream *stream
typ->kind = RZ_TYPE_KIND_POINTER;
RzPdbTpiType *p_utype = rz_bin_pdb_get_type_by_index(stream, lf_pointer->utype);
if (p_utype) {
RzType *tmp = parse_type(typedb, stream, p_utype, name);
RzType *tmp = pdb_type_parse(typedb, stream, p_utype, name);
if (!tmp) {
goto error;
}
@@ -149,40 +127,16 @@ error:
return NULL;
}
static RzType *parse_type(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) {
rz_return_val_if_fail(type && typedb, NULL);
RzType *typ;
if (type->leaf == LF_SIMPLE_TYPE) {
Tpi_LF_SimpleType *simple_type = type->data;
char *error_msg = NULL;
typ = rz_type_parse_string_single(typedb->parser, simple_type->type, &error_msg);
if (error_msg) {
RZ_LOG_ERROR("%s : Error parsing complex type member \"%s\" type:\n%s\n", __FUNCTION__, simple_type->type, error_msg);
RZ_FREE(error_msg);
}
return typ;
} else {
if (type->leaf == LF_POINTER) {
return parse_type_pointer(typedb, stream, type, name);
} else {
return parse_regular_type(typedb, stream, type, name);
}
}
}
static void parse_type_arglist(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *arglist, RzPVector /*<RzCallableArg *>*/ *vec) {
static void arglist_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *arglist, RzPVector /*<RzCallableArg *>*/ *vec) {
rz_return_if_fail(arglist && typedb && vec);
Tpi_LF_Arglist *lf_arglist = arglist->data;
if (!vec) {
return;
}
ut32 *ptr_types = lf_arglist->arg_type;
for (int i = 0; i < lf_arglist->count; i++) {
RzPdbTpiType *stype = rz_bin_pdb_get_type_by_index(stream, *ptr_types++);
if (!stype) {
continue;
}
RzType *type = parse_type(typedb, stream, stype, NULL);
RzType *type = pdb_type_parse(typedb, stream, stype, NULL);
if (!type) {
continue;
}
@@ -193,7 +147,8 @@ static void parse_type_arglist(const RzTypeDB *typedb, RzPdbTpiStream *stream, R
}
}
static RzType *parse_type_procedure(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) {
static RzType *procedure_parse(
const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) {
rz_return_val_if_fail(type && stream && typedb, NULL);
Tpi_LF_Procedure *lf_procedure = type->data;
RzType *typ = RZ_NEW0(RzType);
@@ -211,11 +166,11 @@ static RzType *parse_type_procedure(const RzTypeDB *typedb, RzPdbTpiStream *stre
typ->callable->name = strdup(name);
}
typ->callable->cc = rz_bin_pdb_calling_convention_as_string(lf_procedure->call_conv);
typ->callable->cc = rz_bin_pdb_calling_convention_as_string(lf_procedure->func_attr.calling_convention);
// parse return type
RzPdbTpiType *ret_type = rz_bin_pdb_get_type_by_index(stream, lf_procedure->return_type);
if (ret_type) {
typ->callable->ret = parse_type(typedb, stream, ret_type, name);
typ->callable->ret = pdb_type_parse(typedb, stream, ret_type, name);
if (!typ->callable->ret) {
typ->callable->noret = true;
}
@@ -228,13 +183,13 @@ static RzType *parse_type_procedure(const RzTypeDB *typedb, RzPdbTpiStream *stre
}
RzPdbTpiType *arglist = rz_bin_pdb_get_type_by_index(stream, lf_procedure->arg_list);
if (arglist) {
parse_type_arglist(typedb, stream, arglist, typ->callable->args);
arglist_parse(typedb, stream, arglist, typ->callable->args);
}
rz_type_func_save((RzTypeDB *)typedb, callable);
return typ;
}
static RzType *parse_type_mfunction(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
static RzType *mfunction_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
rz_return_val_if_fail(type_info && stream && typedb, NULL);
Tpi_LF_MFcuntion *lf_mfunction = type_info->data;
RzType *type = RZ_NEW0(RzType);
@@ -247,11 +202,11 @@ static RzType *parse_type_mfunction(const RzTypeDB *typedb, RzPdbTpiStream *stre
type->kind = RZ_TYPE_KIND_CALLABLE;
type->callable = callable;
type->callable->name = strdup(name);
type->callable->cc = rz_bin_pdb_calling_convention_as_string(lf_mfunction->call_conv);
type->callable->cc = rz_bin_pdb_calling_convention_as_string(lf_mfunction->func_attr.calling_convention);
// parse return type
RzPdbTpiType *ret_type = rz_bin_pdb_get_type_by_index(stream, lf_mfunction->return_type);
if (ret_type) {
type->callable->ret = parse_type(typedb, stream, ret_type, name);
type->callable->ret = pdb_type_parse(typedb, stream, ret_type, name);
if (!type->callable->ret) {
type->callable->noret = true;
}
@@ -264,13 +219,14 @@ static RzType *parse_type_mfunction(const RzTypeDB *typedb, RzPdbTpiStream *stre
}
RzPdbTpiType *arglist = rz_bin_pdb_get_type_by_index(stream, lf_mfunction->arglist);
if (arglist) {
parse_type_arglist(typedb, stream, arglist, type->callable->args);
arglist_parse(typedb, stream, arglist, type->callable->args);
}
rz_type_func_save((RzTypeDB *)typedb, callable);
return type;
}
static RzType *parse_type_onemethod(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) {
static RzType *onemethod_parse(
const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) {
rz_return_val_if_fail(type_info && typedb, NULL);
Tpi_LF_OneMethod *lf_onemethod = type_info->data;
char *name = rz_bin_pdb_get_type_name(type_info);
@@ -278,68 +234,78 @@ static RzType *parse_type_onemethod(const RzTypeDB *typedb, RzPdbTpiStream *stre
if (!utype) {
return NULL;
}
if (utype->leaf == LF_MFUNCTION) {
return parse_type_mfunction(typedb, stream, utype, name);
if (utype->kind == TpiKind_MFUNCTION) {
return mfunction_parse(typedb, stream, utype, name);
}
return NULL;
}
static RzType *parse_type_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
static RzType *member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
rz_return_val_if_fail(type_info && typedb, NULL);
Tpi_LF_Member *lf_member = type_info->data;
RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_member->index);
RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_member->field_type);
if (!utype) {
return NULL;
}
return parse_type(typedb, stream, utype, name);
return pdb_type_parse(typedb, stream, utype, name);
}
static RzType *parse_type_static_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
static RzType *static_member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
rz_return_val_if_fail(type_info && typedb, NULL);
Tpi_LF_StaticMember *lf_stmember = type_info->data;
RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_stmember->index);
RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_stmember->field_type);
if (!utype) {
return NULL;
}
return parse_type(typedb, stream, utype, name);
return pdb_type_parse(typedb, stream, utype, name);
}
static RzType *parse_type_nest(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) {
static RzType *type_new_identify(const char *name, RzTypeIdentifierKind k) {
if (RZ_STR_ISEMPTY(name)) {
return NULL;
}
RzType *t = RZ_NEW0(RzType);
if (!t) {
return NULL;
}
t->kind = RZ_TYPE_KIND_IDENTIFIER;
t->identifier.name = rz_str_new(name);
t->identifier.kind = k;
return t;
}
static RzTypeIdentifierKind iKind_from_bKind(RzBaseTypeKind k) {
switch (k) {
case RZ_BASE_TYPE_KIND_STRUCT: return RZ_TYPE_IDENTIFIER_KIND_STRUCT;
case RZ_BASE_TYPE_KIND_UNION: return RZ_TYPE_IDENTIFIER_KIND_UNION;
case RZ_BASE_TYPE_KIND_ENUM: return RZ_TYPE_IDENTIFIER_KIND_ENUM;
case RZ_BASE_TYPE_KIND_TYPEDEF:
case RZ_BASE_TYPE_KIND_ATOMIC: return RZ_TYPE_IDENTIFIER_KIND_UNSPECIFIED;
}
return RZ_TYPE_IDENTIFIER_KIND_UNSPECIFIED;
}
static RzType *nest_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info, char *name) {
rz_return_val_if_fail(type_info && stream && typedb, NULL);
Tpi_LF_NestType *lf_nest = type_info->data;
RzPdbTpiType *utype = rz_bin_pdb_get_type_by_index(stream, lf_nest->index);
RzPdbTpiType *utpi = rz_bin_pdb_get_type_by_index(stream, lf_nest->index);
if (!utpi) {
return NULL;
}
const char *uname = rz_bin_pdb_get_type_name(utpi);
if (uname) {
const RzBaseType *bt = rz_type_db_get_base_type(typedb, uname);
if (bt) {
return type_new_identify(bt->name, iKind_from_bKind(bt->kind));
}
}
RzType *utype = pdb_type_parse(typedb, stream, utpi, NULL);
if (!utype) {
return NULL;
}
const char *name = rz_bin_pdb_get_type_name(utype);
if (name) {
RzBaseType *b_type = rz_type_db_get_base_type(typedb, name);
if (b_type && b_type->type) {
if (b_type->type->kind == RZ_TYPE_KIND_IDENTIFIER) {
return rz_type_clone(b_type->type);
}
}
return NULL;
}
RzType *n_type = parse_type(typedb, stream, utype, NULL);
if (!n_type) {
return NULL;
}
RzBaseType *btype = rz_type_base_type_new(RZ_BASE_TYPE_KIND_TYPEDEF);
if (!btype) {
return NULL;
}
btype->name = name ? strdup(name) : create_type_name_from_offset(lf_nest->index);
btype->type = n_type;
if (!rz_type_db_save_base_type(typedb, btype)) {
return NULL;
}
if (n_type->kind == RZ_TYPE_KIND_IDENTIFIER) {
return rz_type_clone(n_type);
}
return NULL;
return rz_type_clone(utype);
}
/**
@@ -347,47 +313,50 @@ static RzType *parse_type_nest(const RzTypeDB *typedb, RzPdbTpiStream *stream, R
*
* \param typedb Types DB instance
* \param stream TPI Stream
* \param type_info Current RzPdbTpiType (member)
* \param t Current RzPdbTpiType (member)
* \return RzTypeStructMember* parsed member, NULL if fail
*/
static RzTypeStructMember *parse_struct_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) {
rz_return_val_if_fail(type_info, NULL);
static RzTypeStructMember *class_member_parse(
const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *t) {
rz_return_val_if_fail(t, NULL);
char *name = NULL;
ut64 offset = 0;
RzType *type = NULL;
switch (type_info->leaf) {
case LF_ONEMETHOD: {
name = rz_bin_pdb_get_type_name(type_info);
type = parse_type_onemethod(typedb, stream, type_info);
switch (t->kind) {
case TpiKind_ONEMETHOD: {
name = rz_bin_pdb_get_type_name(t);
type = onemethod_parse(typedb, stream, t);
break;
}
case LF_MEMBER: {
offset = rz_bin_pdb_get_type_val(type_info);
name = rz_bin_pdb_get_type_name(type_info);
type = parse_type_member(typedb, stream, type_info, name);
case TpiKind_MEMBER: {
offset = rz_bin_pdb_get_type_val(t);
name = rz_bin_pdb_get_type_name(t);
type = member_parse(typedb, stream, t, name);
break;
}
case LF_STMEMBER: {
name = rz_bin_pdb_get_type_name(type_info);
type = parse_type_static_member(typedb, stream, type_info, name);
case TpiKind_STMEMBER: {
name = rz_bin_pdb_get_type_name(t);
type = static_member_parse(typedb, stream, t, name);
break;
}
case LF_NESTTYPE: {
name = rz_bin_pdb_get_type_name(type_info);
type = parse_type_nest(typedb, stream, type_info);
case TpiKind_NESTTYPE: {
name = rz_bin_pdb_get_type_name(t);
type = nest_parse(typedb, stream, t, rz_str_new(name));
break;
}
case LF_BCLASS:
case TpiKind_VBCLASS:
case TpiKind_BCLASS:
// For structure, we don't need base class for now
goto cleanup;
case LF_METHOD:
case TpiKind_METHOD:
// TODO: need to handle overloaded methods here
goto cleanup;
case LF_VFUNCTAB:
case TpiKind_VFUNCTAB:
// For structure, we don't need vtable for now
goto cleanup;
default:
RZ_LOG_ERROR("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type_info->leaf);
rz_warn_if_reached();
RZ_LOG_ERROR("%s : unsupported leaf type 0x%x\n", __FUNCTION__, t->leaf);
goto cleanup;
}
if (!type) {
@@ -436,7 +405,7 @@ static RzType *create_rztype(RzPdbTpiType *type, RzTypeIdentifierKind kind, cons
}
#define PDB_PROCESS_LF_INDEX \
if (member_info->leaf == LF_INDEX) { \
if (member_info->kind == TpiKind_INDEX) { \
ut32 index = rz_bin_pdb_get_type_val(member_info); \
if (index == type->index) { \
break; \
@@ -460,7 +429,7 @@ static RzType *create_rztype(RzPdbTpiType *type, RzTypeIdentifierKind kind, cons
* \param stream TPI Stream
* \param type Current type
*/
static RzType *parse_structure(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
static RzType *class_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
rz_return_val_if_fail(typedb && stream && type, NULL);
RzBaseType *base_type = NULL;
@@ -510,12 +479,13 @@ foreach_members:
rz_pvector_foreach (members, it) {
RzPdbTpiType *member_info = *it;
PDB_PROCESS_LF_INDEX;
RzTypeStructMember *struct_member = parse_struct_member(typedb, stream, member_info);
RzTypeStructMember *struct_member = class_member_parse(typedb, stream, member_info);
if (!struct_member) {
continue; // skip the failure
}
void *element = rz_vector_push(&base_type->struct_data.members, struct_member);
if (!element) {
rz_warn_if_reached();
rz_type_base_struct_member_free(struct_member, NULL);
return NULL;
}
@@ -538,29 +508,30 @@ foreach_members:
* \param type_info Current RzPdbTpiType (member)
* \return RzTypeUnionMember* parsed member, NULL if fail
*/
static RzTypeUnionMember *parse_union_member(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) {
static RzTypeUnionMember *union_member_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type_info) {
rz_return_val_if_fail(type_info && stream && typedb, NULL);
char *name = NULL;
ut64 offset = 0;
RzType *type = NULL;
switch (type_info->leaf) {
case LF_ONEMETHOD: {
switch (type_info->kind) {
case TpiKind_ONEMETHOD: {
name = rz_bin_pdb_get_type_name(type_info);
type = parse_type_onemethod(typedb, stream, type_info);
type = onemethod_parse(typedb, stream, type_info);
break;
}
case LF_MEMBER: {
case TpiKind_MEMBER: {
offset = rz_bin_pdb_get_type_val(type_info);
name = rz_bin_pdb_get_type_name(type_info);
type = parse_type_member(typedb, stream, type_info, name);
type = member_parse(typedb, stream, type_info, name);
break;
}
case LF_NESTTYPE: {
case TpiKind_NESTTYPE: {
name = rz_bin_pdb_get_type_name(type_info);
type = parse_type_nest(typedb, stream, type_info);
type = nest_parse(typedb, stream, type_info, rz_str_new(name));
break;
}
default:
rz_warn_if_reached();
RZ_LOG_ERROR("%s : unsupported leaf type 0x%x\n", __FUNCTION__, type_info->leaf);
goto cleanup;
}
@@ -588,7 +559,7 @@ cleanup:
* \param stream TPI Stream
* \param type_info Current RzPdbTpiType (enum case)
*/
static RzType *parse_union(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
static RzType *union_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
rz_return_val_if_fail(typedb && stream && type, NULL);
RzBaseType *base_type = NULL;
@@ -638,7 +609,7 @@ foreach_members:
rz_pvector_foreach (members, it) {
RzPdbTpiType *member_info = *it;
PDB_PROCESS_LF_INDEX;
RzTypeUnionMember *union_member = parse_union_member(typedb, stream, member_info);
RzTypeUnionMember *union_member = union_member_parse(typedb, stream, member_info);
if (!union_member) {
continue; // skip the failure
}
@@ -660,17 +631,15 @@ foreach_members:
/**
* \brief Parse enum case
* \param type_info Current type info (enum case)
* \param type Current type info (enum case)
* \return RzTypeEnumCase* parsed enum case, NULL if fail
*/
static RzTypeEnumCase *parse_enumerate(RzPdbTpiType *type) {
rz_return_val_if_fail(type && type->leaf == LF_ENUMERATE, NULL);
static RzTypeEnumCase *enumerate_parse(RzPdbTpiType *type) {
rz_return_val_if_fail(type && type->kind == TpiKind_ENUMERATE, NULL);
char *name = NULL;
ut64 value = 0;
// sometimes, the type doesn't have get_val for some reason
value = rz_bin_pdb_get_type_val(type);
name = rz_bin_pdb_get_type_name(type);
ut64 value = rz_bin_pdb_get_type_val(type);
char *name = rz_bin_pdb_get_type_name(type);
RzTypeEnumCase *cas = RZ_NEW0(RzTypeEnumCase);
if (!cas) {
goto cleanup;
@@ -689,7 +658,7 @@ cleanup:
* \param stream TPI Stream
* \param type Current type
*/
static RzType *parse_enum(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
static RzType *enum_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
rz_return_val_if_fail(typedb && type, NULL);
Tpi_LF_Enum *lf_enum = type->data;
// assert all member functions we need info from
@@ -722,7 +691,7 @@ static RzType *parse_enum(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbT
rz_type_base_type_free(base_type);
return NULL;
}
RzType *btype = parse_type(typedb, stream, utype, NULL);
RzType *btype = pdb_type_parse(typedb, stream, utype, NULL);
if (!btype) {
rz_type_base_type_free(base_type);
return NULL;
@@ -746,7 +715,7 @@ foreach_members:
rz_pvector_foreach (members, it) {
RzPdbTpiType *member_info = *it;
PDB_PROCESS_LF_INDEX;
RzTypeEnumCase *enum_case = parse_enumerate(member_info);
RzTypeEnumCase *enum_case = enumerate_parse(member_info);
if (!enum_case) {
continue; // skip it, move forward
}
@@ -765,6 +734,53 @@ foreach_members:
return base_type->type ? rz_type_clone(base_type->type) : NULL;
}
static RzType *pdb_type_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type, char *name) {
switch (type->kind) {
case TpiKind_SIMPLE_TYPE:
return pdb_simple_type_parse(typedb, type);
case TpiKind_CLASS:
return class_parse(typedb, stream, type);
case TpiKind_UNION:
return union_parse(typedb, stream, type);
case TpiKind_ENUM:
return enum_parse(typedb, stream, type);
case TpiKind_MODIFIER:
return modifier_parse(typedb, stream, type);
case TpiKind_ARRAY:
return array_parse(typedb, stream, type);
case TpiKind_POINTER:
return pointer_parse(typedb, stream, type, name);
case TpiKind_PROCEDURE:
return procedure_parse(typedb, stream, type, name);
case TpiKind_MFUNCTION:
return mfunction_parse(typedb, stream, type, name);
case TpiKind_BITFIELD:
case TpiKind_BCLASS:
case TpiKind_FILEDLIST:
case TpiKind_ENUMERATE:
case TpiKind_ARGLIST:
case TpiKind_METHODLIST:
case TpiKind_VTSHAPE:
case TpiKind_VFTABLE:
case TpiKind_LABEL:
case TpiKind_NESTTYPE:
case TpiKind_MEMBER:
case TpiKind_METHOD:
case TpiKind_ONEMETHOD:
case TpiKind_VFUNCTAB:
case TpiKind_STMEMBER:
case TpiKind_VBCLASS:
case TpiKind_INDEX:
return NULL;
default:
rz_warn_if_reached();
RZ_LOG_DEBUG("Unknown type record: #0x%" PFMT32x ": leaf=0x%" PFMT32x "\n",
type->index, type->leaf);
break;
}
return NULL;
}
/**
* \brief Delegate the type parsing to appropriate function
*
@@ -774,41 +790,7 @@ foreach_members:
*/
RZ_API RzType *rz_type_db_pdb_parse(const RzTypeDB *typedb, RzPdbTpiStream *stream, RzPdbTpiType *type) {
rz_return_val_if_fail(typedb && type, NULL);
switch (type->leaf) {
case LF_SIMPLE_TYPE: {
Tpi_LF_SimpleType *simple_type = type->data;
char *error_msg = NULL;
RzType *typ = rz_type_parse_string_single(typedb->parser, simple_type->type, &error_msg);
if (error_msg) {
RZ_LOG_ERROR("%s : Error parsing complex type member \"%s\" type:\n%s\n", __FUNCTION__, simple_type->type, error_msg);
RZ_FREE(error_msg);
}
return typ;
}
case LF_CLASS:
case LF_CLASS_19:
case LF_STRUCTURE:
case LF_STRUCTURE_19:
return parse_structure(typedb, stream, type);
case LF_UNION:
return parse_union(typedb, stream, type);
case LF_ENUM:
return parse_enum(typedb, stream, type);
case LF_MODIFIER:
return parse_type_modifier(typedb, stream, type);
case LF_ARRAY:
return parse_type_array(typedb, stream, type);
case LF_POINTER:
return parse_type_pointer(typedb, stream, type, NULL);
case LF_PROCEDURE:
return parse_type_procedure(typedb, stream, type, NULL);
default:
RZ_LOG_DEBUG("Unknown type record: #0x%" PFMT32x ": leaf=0x%" PFMT32x "\n",
type->index, type->leaf);
break;
}
return NULL;
return pdb_type_parse(typedb, stream, type, NULL);
}
/**
@@ -832,7 +814,7 @@ RZ_API void rz_type_db_pdb_load(const RzTypeDB *typedb, const RzPdb *pdb) {
RBIter it;
RzPdbTpiType *type;
rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) {
if (type && is_parsable_type(type->leaf)) {
if (type && is_parsable_type(type)) {
rz_type_db_pdb_parse(typedb, stream, type);
}
}
+1 -1
View File
@@ -82,7 +82,7 @@ int PE_(bin_pe_init_security)(RzBinPEObj *bin) {
PE_DWord paddr = data_dir_security->VirtualAddress;
ut32 size = data_dir_security->Size;
if (size < 8 || paddr > bin->size || paddr + size > bin->size) {
RZ_LOG_INFO("Invalid certificate table");
RZ_LOG_INFO("Invalid certificate table\n");
return false;
}
+1
View File
@@ -260,6 +260,7 @@ rz_bin_sources = [
'pdb/stream_pe.c',
'pdb/tpi.c',
'pdb/symbol.c',
'pdb/modi.c',
'dwarf/abbrev.c',
'dwarf/addr.c',
+79 -112
View File
@@ -4,18 +4,18 @@
#include "pdb.h"
RZ_IPI void free_dbi_stream(RzPdbDbiStream *stream) {
RZ_IPI void dbi_stream_free(RzPdbDbiStream *stream) {
if (!stream) {
return;
}
RzPdbDbiStreamExHdr *ex_hdr;
RzListIter *it;
rz_list_foreach (stream->ex_hdrs, it, ex_hdr) {
RZ_FREE(ex_hdr->ModuleName);
RZ_FREE(ex_hdr->ObjFileName);
RZ_FREE(ex_hdr);
void **it;
rz_pvector_foreach (stream->modules, it) {
PDB_DBIModule *m = *it;
RZ_FREE(m->module_name);
RZ_FREE(m->object_file_name);
RZ_FREE(m);
}
rz_list_free(stream->ex_hdrs);
rz_pvector_free(stream->modules);
free(stream);
}
@@ -42,113 +42,77 @@ static bool parse_dbi_stream_header(RzPdbDbiStream *s, RzBuffer *buf) {
rz_buf_read_le32(buf, &s->hdr.padding);
}
static bool parse_dbi_stream_section_entry(RzPdbDbiStreamExHdr *hdr, RzBuffer *buf) {
return rz_buf_read_le16(buf, &hdr->sec_con.Section) &&
rz_buf_read_le16(buf, (ut16 *)&hdr->sec_con.Padding1) &&
rz_buf_read_le32(buf, (ut32 *)&hdr->sec_con.Offset) &&
rz_buf_read_le32(buf, (ut32 *)&hdr->sec_con.Size) &&
rz_buf_read_le32(buf, &hdr->sec_con.Characteristics) &&
rz_buf_read_le16(buf, &hdr->sec_con.ModuleIndex) &&
rz_buf_read_le16(buf, (ut16 *)&hdr->sec_con.Padding2) &&
rz_buf_read_le32(buf, &hdr->sec_con.DataCrc) &&
rz_buf_read_le32(buf, &hdr->sec_con.RelocCrc);
static bool PDB_DBISectionContrbution_parse(RzBuffer *buf, PDB_DBISectionContrbution *section) {
ut16 pad = 0;
return rz_buf_read_le16(buf, &section->offset.section_index) &&
rz_buf_read_le16(buf, &pad) &&
rz_buf_read_le32(buf, &section->offset.offset) &&
rz_buf_read_le32(buf, &section->size) &&
rz_buf_read_le32(buf, &section->characteristics) &&
rz_buf_read_le16(buf, &section->module) &&
rz_buf_read_le16(buf, &section->pad) &&
rz_buf_read_le32(buf, &section->data_crc) &&
rz_buf_read_le32(buf, &section->reloc_crc);
}
static bool parse_dbi_stream_ex_header(RzPdbDbiStream *s, RzBuffer *buf) {
s->ex_hdrs = rz_list_new();
if (!s->ex_hdrs) {
// free s-dbi
return false;
}
ut32 ex_size = s->hdr.mod_info_size;
ut32 read_len = 0;
bool result = true;
while (read_len < ex_size) {
ut32 initial_seek = rz_buf_tell(buf);
RzPdbDbiStreamExHdr *hdr = RZ_NEW0(RzPdbDbiStreamExHdr);
if (!hdr) {
result = false;
goto err;
}
if (!rz_buf_read_le32(buf, &hdr->unknown)) {
result = false;
goto err;
}
if (!parse_dbi_stream_section_entry(hdr, buf)) {
result = false;
goto err;
}
if (!rz_buf_read_le16(buf, &hdr->Flags) ||
!rz_buf_read_le16(buf, &hdr->ModuleSymStream)) {
result = false;
goto err;
}
if (!rz_buf_read_le32(buf, &hdr->SymByteSize) ||
!rz_buf_read_le32(buf, &hdr->C11ByteSize) ||
!rz_buf_read_le32(buf, &hdr->C13ByteSize)) {
result = false;
goto err;
}
if (!rz_buf_read_le16(buf, &hdr->SourceFileCount) ||
!rz_buf_read_le16(buf, (ut16 *)&hdr->Padding)) {
result = false;
goto err;
}
if (!rz_buf_read_le32(buf, &hdr->Unused2) ||
!rz_buf_read_le32(buf, &hdr->SourceFileNameIndex) ||
!rz_buf_read_le32(buf, &hdr->PdbFilePathNameIndex)) {
result = false;
goto err;
}
hdr->ModuleName = rz_buf_get_string(buf, rz_buf_tell(buf));
ut32 str_length = strlen(hdr->ModuleName) + 1;
if (str_length) {
rz_buf_seek(buf, str_length, RZ_BUF_CUR);
}
hdr->ObjFileName = rz_buf_get_string(buf, rz_buf_tell(buf));
str_length = strlen(hdr->ObjFileName) + 1;
if (str_length) {
rz_buf_seek(buf, str_length, RZ_BUF_CUR);
}
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);
read_len += remain;
}
rz_list_append(s->ex_hdrs, hdr);
err:
if (!result) {
free(hdr);
return false;
}
}
if (read_len != ex_size) {
return false;
}
return true;
static bool PDB_DBIModule_parse(RzBuffer *b, PDB_DBIModule *m) {
return rz_buf_read_le32(b, &m->opened) &&
PDB_DBISectionContrbution_parse(b, &m->section) &&
rz_buf_read_le16(b, &m->flags) &&
rz_buf_read_le16(b, &m->stream) &&
rz_buf_read_le32(b, &m->symbols_size) &&
rz_buf_read_le32(b, &m->line_size) &&
rz_buf_read_le32(b, &m->c13_line_size) &&
rz_buf_read_le16(b, &m->files) &&
rz_buf_read_le16(b, &m->pad) &&
rz_buf_read_le32(b, &m->filename_offsets) &&
rz_buf_read_le32(b, &m->source) &&
rz_buf_read_le32(b, &m->compiler) &&
rz_buf_read_string(b, &m->module_name) > 0 &&
rz_buf_read_string(b, &m->object_file_name) > 0;
}
static bool parse_dbi_dbg_header(RzPdbDbiStream *s, RzBuffer *buf) {
if (!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_fpo) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_exception) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_fixup) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_omap_to_src) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_omap_from_src) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_section_hdr) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_token_rid_map) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_xdata) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_pdata) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_new_fpo) ||
!rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_section_hdr_orig)) {
return false;
}
return true;
return rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_fpo) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_exception) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_fixup) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_omap_to_src) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_omap_from_src) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_section_hdr) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_token_rid_map) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_xdata) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_pdata) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_new_fpo) &&
rz_buf_read_le16(buf, (ut16 *)&s->dbg_hdr.sn_section_hdr_orig);
}
RZ_IPI bool parse_dbi_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
static bool modules_parse(RzPdbDbiStream *s, RzBuffer *stream_buffer) {
s->modules = rz_pvector_new(NULL);
if (!s->modules) {
return false;
}
RzBuffer *b = rz_buf_new_slice(stream_buffer, s->hdr_size, s->hdr.mod_info_size);
if (!b) {
return false;
}
while (!buf_empty(b)) {
PDB_DBIModule *m = RZ_NEW0(PDB_DBIModule);
if (!(m && PDB_DBIModule_parse(b, m) &&
buf_align(b, 4))) {
free(m);
goto err;
}
rz_pvector_push(s->modules, m);
}
rz_buf_free(b);
return true;
err:
rz_buf_free(b);
return false;
}
RZ_IPI bool dbi_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream) {
if (!pdb || !stream) {
return false;
}
@@ -159,16 +123,19 @@ RZ_IPI bool parse_dbi_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
return false;
}
RzBuffer *buf = stream->stream_data;
// parse header
if (!parse_dbi_stream_header(s, buf) || !parse_dbi_stream_ex_header(s, buf)) {
if (!parse_dbi_stream_header(s, buf)) {
return false;
}
s->hdr_size = rz_buf_tell(buf);
if (!modules_parse(s, buf)) {
return false;
}
// skip these streams
ut64 seek = s->hdr.section_contribution_size + s->hdr.section_map_size +
ut64 pos = s->hdr_size + s->hdr.mod_info_size + s->hdr.section_contribution_size + s->hdr.section_map_size +
s->hdr.source_info_size + s->hdr.type_server_map_size +
s->hdr.ec_substream_size;
rz_buf_seek(buf, seek, RZ_BUF_CUR);
rz_buf_seek(buf, pos, RZ_BUF_SET);
if (!parse_dbi_dbg_header(s, buf)) {
return false;
}
+29 -28
View File
@@ -4,7 +4,10 @@
#ifndef PDB_DBI_H
#define PDB_DBI_H
#include <rz_util.h>
#include <rz_pdb.h>
RZ_IPI bool dbi_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI void dbi_stream_free(RzPdbDbiStream *stream);
enum dbi_stream_version {
DSV_VC41 = 930803,
@@ -14,33 +17,31 @@ enum dbi_stream_version {
DSV_V110 = 20091201
};
typedef struct SectionContribEntry {
ut16 Section;
char Padding1[2];
st32 Offset;
st32 Size;
ut32 Characteristics;
ut16 ModuleIndex;
char Padding2[2];
ut32 DataCrc;
ut32 RelocCrc;
} SectionContr;
typedef struct {
PDBSectionOffset offset;
ut32 size;
ut32 characteristics;
ut16 module;
ut16 pad;
ut32 data_crc;
ut32 reloc_crc;
} PDB_DBISectionContrbution;
typedef struct dbi_stream_ex_header_t {
ut32 unknown;
SectionContr sec_con;
ut16 Flags;
ut16 ModuleSymStream;
ut32 SymByteSize;
ut32 C11ByteSize;
ut32 C13ByteSize;
ut16 SourceFileCount;
char Padding[2];
ut32 Unused2;
ut32 SourceFileNameIndex;
ut32 PdbFilePathNameIndex;
char *ModuleName;
char *ObjFileName;
} RzPdbDbiStreamExHdr;
typedef struct {
ut32 opened;
PDB_DBISectionContrbution section;
ut16 flags;
ut16 stream;
ut32 symbols_size;
ut32 line_size;
ut32 c13_line_size;
ut16 files;
ut16 pad;
ut32 filename_offsets;
ut32 source;
ut32 compiler;
char *module_name;
char *object_file_name;
} PDB_DBIModule;
#endif
+7 -22
View File
@@ -4,7 +4,7 @@
#include "pdb.h"
RZ_IPI bool parse_gdata_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
RZ_IPI bool gdata_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream) {
rz_return_val_if_fail(pdb && stream, false);
PDBSymbolTable *syms = pdb_global_symbols(pdb);
if (!syms) {
@@ -16,37 +16,22 @@ RZ_IPI bool parse_gdata_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
RzPdbGDataStream *s = pdb->s_gdata;
if (!s) {
RZ_LOG_ERROR("Error allocating memory.\n");
return false;
}
s->global_symbols = rz_pvector_new(free);
if (!s->global_symbols) {
return false;
goto err;
}
PDBSymbolIter iter = { 0 };
PDBSymbolTable_iter(syms, &iter);
while (true) {
PDBSymbol *symbol = RZ_NEW0(PDBSymbol);
if (!symbol) {
goto err;
}
if (!PDBSymbolIter_next(&iter, symbol)) {
free(symbol);
break;
}
if (!symbol->data) {
free(symbol);
continue;
}
rz_pvector_push(s->global_symbols, symbol);
if (!PDBSymbolIter_collect(&iter, &s->global_symbols)) {
goto err;
}
free(syms);
return true;
err:
free(syms);
return false;
}
RZ_IPI void free_gdata_stream(RzPdbGDataStream *stream) {
RZ_IPI void gdata_stream_free(RzPdbGDataStream *stream) {
if (!stream) {
return;
}
+52
View File
@@ -0,0 +1,52 @@
// SPDX-FileCopyrightText: 2023 billow <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only
#include "modi.h"
static bool PDBModuleInfo_symbols(const PDBModuleInfo *modi, PDBSymbolIter *iter) {
RzBuffer *b = rz_buf_new_slice(modi->stream, 0, modi->symbols_size);
if (!b) {
return false;
}
if (modi->symbols_size > 0) {
ut32 sig = 0;
if (!rz_buf_read_le32(b, &sig)) {
goto err;
}
if (sig != CV_SIGNATURE_C13) {
RZ_LOG_ERROR("Unsupported symbol data format: 0x%" PFMT32x "\n", sig);
goto err;
}
}
iter->b = b;
return true;
err:
rz_buf_free(b);
return false;
}
RZ_IPI bool PDBModuleInfo_parse(const RzPdb *pdb, const PDB_DBIModule *m, PDBModuleInfo *modi) {
if (!(pdb && m && modi)) {
return false;
}
modi->stream_index = m->stream;
modi->symbols_size = m->symbols_size;
if (modi->symbols_size == 0) {
return true;
}
const RzPdbMsfStream *stream = pdb_raw_steam(pdb, modi->stream_index);
if (!stream) {
return false;
}
modi->stream = stream->stream_data;
PDBSymbolIter iter = { 0 };
if (!PDBModuleInfo_symbols(modi, &iter)) {
return false;
}
if (!PDBSymbolIter_collect(&iter, &modi->symbols)) {
return false;
}
return true;
}
+19
View File
@@ -0,0 +1,19 @@
// SPDX-FileCopyrightText: 2023 billow <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only
#ifndef MODI_H
#define MODI_H
#include <rz_util/rz_buf.h>
#include "dbi.h"
#include "pdb.h"
#define CV_SIGNATURE_C6 0L // Actual signature is >64K
#define CV_SIGNATURE_C7 1L // First explicit signature
#define CV_SIGNATURE_C11 2L // C11 (vc5.x) 32-bit types
#define CV_SIGNATURE_C13 4L // C13 (vc7.x) zero terminated names
#define CV_SIGNATURE_RESERVED 5L // All signatures from 5 to 64K are reserved
RZ_IPI bool PDBModuleInfo_parse(const RzPdb *pdb, const PDB_DBIModule *m, PDBModuleInfo *modi);
#endif // MODI_H
+6 -4
View File
@@ -5,7 +5,7 @@
#include "pdb.h"
RZ_IPI bool parse_omap_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
RZ_IPI bool omap_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream) {
rz_return_val_if_fail(pdb && stream, false);
if (!pdb->s_omap) {
pdb->s_omap = RZ_NEW0(RzPdbOmapStream);
@@ -39,7 +39,7 @@ RZ_IPI bool parse_omap_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
return true;
}
RZ_IPI void free_omap_stream(RzPdbOmapStream *stream) {
RZ_IPI void omap_stream_free(RzPdbOmapStream *stream) {
if (!stream) {
return;
}
@@ -117,9 +117,11 @@ static ut64 pdb_omap_remap(RZ_NONNULL RzPdbOmapStream *omap_stream, ut64 address
* \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) {
RZ_API ut64 rz_bin_pdb_to_rva(
RZ_BORROW RZ_NONNULL const RzPdb *pdb,
RZ_BORROW RZ_NONNULL const PDBSectionOffset *section_offset) {
static const ut64 DEFAULT = UT64_MAX;
rz_return_val_if_fail(pdb && pdb->s_pe, DEFAULT);
rz_return_val_if_fail(pdb && pdb->s_pe && section_offset, DEFAULT);
PeImageSectionHeader *section_hdr = pdb_section_hdr_by_index(pdb->s_pe, section_offset->section_index);
if (!section_hdr) {
return DEFAULT;
+55 -72
View File
@@ -10,7 +10,7 @@
#include "pdb.h"
static bool parse_pdb_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
static bool pdb_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream) {
if (!pdb || !stream) {
return false;
}
@@ -35,75 +35,58 @@ static bool parse_pdb_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
return true;
}
static bool parse_stream(
RzPdb *pdb, ut32 index, bool (*f)(RzPdb *, RzPdbMsfStream *), bool try) {
RzPdbMsfStream *stream = pdb_raw_steam(pdb, index);
if (!stream) {
return try;
}
return f(pdb, stream);
}
static bool parse_streams(RzPdb *pdb) {
RzListIter *it;
RzPdbMsfStream *ms;
rz_list_foreach (pdb->streams, it, ms) {
switch (ms->stream_idx) {
case PDB_STREAM_ROOT:
break;
case PDB_STREAM_PDB:
if (!parse_pdb_stream(pdb, ms)) {
RZ_LOG_ERROR("Parse pdb stream failed.\n");
if (!(parse_stream(pdb, PDB_STREAM_PDB, pdb_stream_parse, false) &&
parse_stream(pdb, PDB_STREAM_TPI, tpi_stream_parse, false) &&
parse_stream(pdb, PDB_STREAM_DBI, dbi_stream_parse, false))) {
return false;
}
if (!(parse_stream(pdb, pdb->s_dbi->hdr.sym_record_stream, gdata_stream_parse, true) &&
parse_stream(pdb, pdb->s_dbi->dbg_hdr.sn_section_hdr, pe_stream_parse, true) &&
parse_stream(pdb, pdb->s_dbi->dbg_hdr.sn_section_hdr_orig, pe_stream_parse, true) &&
parse_stream(pdb, pdb->s_dbi->dbg_hdr.sn_omap_to_src, omap_stream_parse, true) &&
parse_stream(pdb, pdb->s_dbi->dbg_hdr.sn_omap_from_src, omap_stream_parse, true))) {
return false;
}
if (pdb->s_dbi->modules) {
pdb->module_infos = rz_pvector_new(NULL);
void **modit;
rz_pvector_foreach (pdb->s_dbi->modules, modit) {
const PDB_DBIModule *m = *modit;
PDBModuleInfo *modi = RZ_NEW0(PDBModuleInfo);
if (!modi) {
return false;
}
break;
case PDB_STREAM_TPI:
if (!parse_tpi_stream(pdb, ms)) {
RZ_LOG_ERROR("Parse tpi stream failed.\n");
if (!PDBModuleInfo_parse(pdb, m, modi)) {
free(modi);
return false;
}
break;
case PDB_STREAM_DBI:
if (!parse_dbi_stream(pdb, ms)) {
RZ_LOG_ERROR("Parse dbi stream failed.\n");
return false;
}
break;
default: {
if (!pdb->s_dbi) {
break;
}
if (ms->stream_idx == pdb->s_dbi->hdr.sym_record_stream) {
if (!parse_gdata_stream(pdb, ms)) {
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.\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.\n");
return false;
}
}
break;
}
rz_pvector_push(pdb->module_infos, modi);
}
}
return true;
}
RZ_IPI RzPdbMsfStream *pdb_raw_steam(RzPdb *pdb, ut16 index) {
if (!(pdb && pdb->streams)) {
RZ_IPI RzPdbMsfStream *pdb_raw_steam(const RzPdb *pdb, ut16 index) {
if (!(pdb && pdb->streams && pdb->msd)) {
return NULL;
}
RzListIter *it;
RzPdbMsfStream *ms;
rz_list_foreach (pdb->streams, it, ms) {
if (ms->stream_idx == index) {
return ms;
}
if (index >= pdb->msd->NumStreams) {
return NULL;
}
return NULL;
return rz_pvector_at(pdb->streams, index);
}
RZ_IPI PDBSymbolTable *pdb_global_symbols(RzPdb *pdb) {
RZ_IPI PDBSymbolTable *pdb_global_symbols(const RzPdb *pdb) {
if (!(pdb && pdb->s_dbi)) {
return NULL;
}
@@ -143,29 +126,28 @@ static ut64 count_blocks(ut64 length, ut64 block_size) {
return num_blocks;
}
static RzList /*<RzPdbMsfStream *>*/ *pdb7_extract_streams(RzPdb *pdb, RzPdbMsfStreamDirectory *msd) {
RzList *streams = rz_list_newf(msf_stream_free);
static RzPVector /*<RzPdbMsfStream *>*/ *pdb7_extract_streams(RzPdb *pdb, RzPdbMsfStreamDirectory *msd) {
RzPVector *streams = rz_pvector_new_with_len(msf_stream_free, msd->NumStreams);
if (!streams) {
goto error_memory;
}
for (size_t i = 0; i < msd->NumStreams; i++) {
RzPdbMsfStream *stream = RZ_NEW0(RzPdbMsfStream);
if (!stream) {
rz_list_free(streams);
rz_pvector_free(streams);
goto error_memory;
}
stream->stream_idx = i;
stream->stream_size = msd->StreamSizes[i];
stream->blocks_num = count_blocks(stream->stream_size, pdb->super_block->block_size);
if (!stream->stream_size) {
stream->stream_data = NULL;
rz_list_append(streams, stream);
rz_pvector_set(streams, stream->stream_idx, stream);
continue;
}
ut8 *stream_data = (ut8 *)malloc((size_t)stream->blocks_num * pdb->super_block->block_size);
if (!stream_data) {
RZ_FREE(stream);
rz_list_free(streams);
rz_pvector_free(streams);
RZ_LOG_ERROR("Error allocating memory.\n");
return NULL;
}
@@ -174,7 +156,7 @@ static RzList /*<RzPdbMsfStream *>*/ *pdb7_extract_streams(RzPdb *pdb, RzPdbMsfS
if (!rz_buf_read_le32(msd->sd, &block_idx)) {
RZ_FREE(stream);
RZ_FREE(stream_data);
rz_list_free(streams);
rz_pvector_free(streams);
return NULL;
}
rz_buf_seek(pdb->buf, (long long)block_idx * pdb->super_block->block_size, RZ_BUF_SET);
@@ -184,12 +166,11 @@ static RzList /*<RzPdbMsfStream *>*/ *pdb7_extract_streams(RzPdb *pdb, RzPdbMsfS
if (!stream->stream_data) {
RZ_FREE(stream);
RZ_FREE(stream_data);
rz_list_free(streams);
rz_pvector_free(streams);
goto error_memory;
}
rz_list_append(streams, stream);
rz_pvector_set(streams, stream->stream_idx, stream);
}
msf_stream_directory_free(msd);
return streams;
error_memory:
@@ -291,9 +272,9 @@ static bool pdb7_parse(RzPdb *pdb) {
RZ_LOG_ERROR("Error extracting stream directory.\n");
goto error;
}
pdb->msd = msd;
pdb->streams = pdb7_extract_streams(pdb, msd);
if (!pdb->streams) {
msf_stream_directory_free(msd);
RZ_LOG_ERROR("Error extracting streams.\n");
goto error;
}
@@ -399,12 +380,14 @@ RZ_API void rz_bin_pdb_free(RzPdb *pdb) {
}
rz_buf_free(pdb->buf);
free(pdb->super_block);
rz_list_free(pdb->streams);
msf_stream_directory_free(pdb->msd);
rz_pvector_free(pdb->streams);
rz_pvector_free(pdb->module_infos);
free(pdb->s_pdb);
free_dbi_stream(pdb->s_dbi);
free_gdata_stream(pdb->s_gdata);
free_omap_stream(pdb->s_omap);
free_tpi_stream(pdb->s_tpi);
free_pe_stream(pdb->s_pe);
dbi_stream_free(pdb->s_dbi);
gdata_stream_free(pdb->s_gdata);
omap_stream_free(pdb->s_omap);
tpi_stream_free(pdb->s_tpi);
pe_stream_free(pdb->s_pe);
free(pdb);
}
+73 -18
View File
@@ -10,30 +10,85 @@
#include "stream_pe.h"
#include "tpi.h"
#include "symbol.h"
#include "modi.h"
RZ_IPI RzPdbMsfStream *pdb_raw_steam(RzPdb *pdb, ut16 index);
RZ_IPI PDBSymbolTable *pdb_global_symbols(RzPdb *pdb);
#define map_err(x) \
if (!(x)) { \
goto err; \
}
static inline RzBuffer *buf_take(RzBuffer *b, ut32 len) {
if (!(b && len)) {
return NULL;
}
RzBuffer *type_buffer = rz_buf_new_slice(b, rz_buf_tell(b), len);
if (!type_buffer) {
return NULL;
}
rz_buf_seek(b, len, RZ_BUF_CUR);
return type_buffer;
}
static inline bool buf_empty(RzBuffer *b) {
if (!b) {
return true;
}
return rz_buf_tell(b) >= rz_buf_size(b);
}
static inline void buf_read_padding(RzBuffer *b) {
if (!b) {
return;
}
while (!buf_empty(b) && rz_buf_peek(b) > 0xf0) {
ut8 padding = 0;
if (!rz_buf_read8(b, &padding)) {
return;
}
if (padding > 0xf0) {
rz_buf_seek(b, (padding & 0x0f) - 1, RZ_BUF_CUR);
}
}
}
static inline bool buf_read_u8_pascal_string(RzBuffer *b, char **result) {
ut8 length = 0;
if (!rz_buf_read8(b, &length)) {
return false;
}
*result = RZ_NEWS0(char, length);
if (!*result) {
return false;
}
return rz_buf_read(b, (ut8 *)*result, length);
}
static inline bool buf_align(RzBuffer *b, ut64 alignment) {
const ut64 diff = rz_buf_tell(b) % alignment;
if (diff <= 0) {
return true;
}
ut64 off = rz_buf_tell(b);
if (rz_buf_size(b) - off < alignment - diff) {
return false;
}
return rz_buf_seek(b, alignment - diff, RZ_BUF_CUR) == off + alignment - diff;
}
RZ_IPI RzPdbMsfStream *pdb_raw_steam(const RzPdb *pdb, ut16 index);
RZ_IPI PDBSymbolTable *pdb_global_symbols(const RzPdb *pdb);
// OMAP
RZ_IPI bool parse_omap_stream(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI void free_omap_stream(RzPdbOmapStream *stream);
RZ_IPI bool omap_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI void omap_stream_free(RzPdbOmapStream *stream);
RZ_IPI int omap_remap(void *stream, int address);
// GDATA
RZ_IPI bool parse_gdata_stream(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI void free_gdata_stream(RzPdbGDataStream *stream);
// DBI
RZ_IPI bool parse_dbi_stream(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI void free_dbi_stream(RzPdbDbiStream *stream);
RZ_IPI bool gdata_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI void gdata_stream_free(RzPdbGDataStream *stream);
// PE
RZ_IPI bool parse_pe_stream(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI void free_pe_stream(RzPdbPeStream *stream);
RZ_IPI bool pe_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI void pe_stream_free(RzPdbPeStream *stream);
// TPI
RZ_IPI bool parse_tpi_stream(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI RzPdbTpiType *parse_simple_type(RzPdbTpiStream *stream, ut32 idx);
RZ_IPI void free_tpi_stream(RzPdbTpiStream *stream);
#endif
#endif
+2 -2
View File
@@ -17,7 +17,7 @@ static bool parse_image_header(PeImageSectionHeader *hdr, RzBuffer *buf) {
rz_buf_read_le32(buf, &hdr->charactestics);
}
RZ_IPI bool parse_pe_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
RZ_IPI bool pe_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream) {
rz_return_val_if_fail(pdb && stream, false);
if (!pdb->s_pe) {
pdb->s_pe = RZ_NEW0(RzPdbPeStream);
@@ -50,7 +50,7 @@ RZ_IPI bool parse_pe_stream(RzPdb *pdb, RzPdbMsfStream *stream) {
}
return true;
}
RZ_IPI void free_pe_stream(RzPdbPeStream *stream) {
RZ_IPI void pe_stream_free(RzPdbPeStream *stream) {
if (!stream) {
return;
}
+93 -12
View File
@@ -3,10 +3,7 @@
#include "symbol.h"
#define map_err(x) \
if (!(x)) { \
goto err; \
}
#include "pdb.h"
RZ_IPI bool PDBSectionOffset_parse(RzBuffer *b, PDBSectionOffset *section_offset) {
if (!section_offset) {
@@ -25,7 +22,7 @@ RZ_IPI bool PDBSectionOffset_parse(RzBuffer *b, PDBSectionOffset *section_offset
static bool symbol_name_parse(RzBuffer *b, PDBSymbolKind kind, char **result) {
if (kind < S_ST_MAX) {
// TODO: pascal
return buf_read_u8_pascal_string(b, result);
} else {
return rz_buf_read_string(b, result) > 0;
}
@@ -124,14 +121,16 @@ err:
RZ_IPI PDBSymbol *PDBSymbolTable_symbol_by_index(PDBSymbolTable *symbol_table, PDBSymbolIndex index) {
PDBSymbolIter iter = { 0 };
PDBSymbol *symbol = NULL;
map_err(PDBSymbolTable_iter(symbol_table, &iter));
map_err(PDBSymbolIter_seek(&iter, index));
PDBSymbol *symbol = RZ_NEW0(PDBSymbol);
symbol = RZ_NEW0(PDBSymbol);
map_err(symbol);
map_err(PDBSymbolIter_next(&iter, symbol));
return symbol;
err:
free(symbol);
return NULL;
}
@@ -148,14 +147,14 @@ RZ_IPI bool PDBSymbolIter_next(PDBSymbolIter *iter, PDBSymbol *symbol) {
if (length < 2) {
return false;
}
b = rz_buf_new_slice(iter->b, rz_buf_tell(iter->b), length);
map_err(b);
const ut64 begin = rz_buf_tell(iter->b);
rz_buf_seek(iter->b, length, RZ_BUF_CUR);
if (!symbol) {
continue;
goto loop_continue;
}
b = rz_buf_new_slice(iter->b, begin, length);
map_err(b);
symbol->index = index;
symbol->length = length;
map_err(PDBSymbol_parse(b, symbol));
@@ -163,10 +162,16 @@ RZ_IPI bool PDBSymbolIter_next(PDBSymbolIter *iter, PDBSymbol *symbol) {
switch (symbol->raw_kind) {
case S_ALIGN:
case S_SKIP:
continue;
goto loop_continue;
default:
if (!symbol->data) {
goto loop_continue;
}
return true;
}
loop_continue:
rz_buf_free(b);
b = NULL;
}
err:
rz_buf_free(b);
@@ -180,3 +185,79 @@ RZ_IPI bool PDBSymbolIter_seek(PDBSymbolIter *iter, PDBSymbolIndex index) {
err:
return false;
}
static void PDBSymbol_free(void *x) {
if (!x) {
return;
}
PDBSymbol *symbol = x;
if (symbol->data) {
switch (symbol->kind) {
case PDB_Public: {
PDBSPublic *d = symbol->data;
free(d->name);
break;
}
case PDB_Data: {
PDBSData *d = symbol->data;
free(d->name);
break;
}
default: rz_warn_if_reached(); break;
}
free(symbol->data);
}
free(symbol);
}
RZ_IPI bool PDBSymbolIter_collect(PDBSymbolIter *iter, RzPVector /*<PDBSymbol *>*/ **psymbols) {
RzPVector *symbols = *psymbols = rz_pvector_new(PDBSymbol_free);
if (!symbols) {
return false;
}
while (true) {
PDBSymbol *symbol = RZ_NEW0(PDBSymbol);
if (!symbol) {
rz_pvector_free(symbols);
psymbols = NULL;
return false;
}
if (!PDBSymbolIter_next(iter, symbol)) {
break;
}
rz_pvector_push(symbols, symbol);
}
return true;
}
RZ_API bool rz_pdb_all_symbols_foreach(
RZ_BORROW RZ_NONNULL const RzPdb *pdb,
RZ_BORROW RZ_NONNULL bool (*f)(const RzPdb *, const PDBSymbol *, void *),
RZ_BORROW RZ_NULLABLE void *u) {
rz_return_val_if_fail(pdb && f, false);
if (!(pdb->s_gdata && pdb->s_gdata->global_symbols)) {
return true;
}
void **it;
rz_pvector_foreach (pdb->s_gdata->global_symbols, it) {
if (!f(pdb, *it, u)) {
return false;
}
}
if (!pdb->module_infos) {
return true;
}
void **modit;
rz_pvector_foreach (pdb->module_infos, modit) {
PDBModuleInfo *modi = *modit;
if (!modi->symbols) {
continue;
}
rz_pvector_foreach (modi->symbols, it) {
if (!f(pdb, *it, u)) {
return false;
}
}
}
return true;
}
+1 -71
View File
@@ -8,79 +8,8 @@
#include <rz_util/rz_buf.h>
#include <rz_pdb.h>
typedef ut16 PDBSymbolKind;
typedef ut32 PDBTypeIndex;
typedef ut32 PDBSymbolIndex;
RZ_IPI bool PDBSectionOffset_parse(RzBuffer *b, PDBSectionOffset *section_offset);
typedef struct {
bool global : 1;
bool managed : 1;
PDBTypeIndex type_index;
PDBSectionOffset offset;
char *name;
} PDBSData;
RZ_IPI bool PDBSData_parse(RzBuffer *b, PDBSymbolKind kind, PDBSData *sdata);
typedef struct {
bool code : 1;
bool function : 1;
bool managed : 1;
bool msil : 1;
PDBSectionOffset offset;
char *name;
} PDBSPublic;
RZ_IPI bool PDBSPublic_parse(RzBuffer *b, PDBSymbolKind kind, PDBSPublic *s);
typedef struct {
PDBSymbolIndex index;
PDBSymbolKind raw_kind;
ut16 length;
enum {
PDB_ScopeEnd, /// End of a scope, such as a procedure.
PDB_ObjName, /// Name of the object file of this module.
PDB_RegisterVariable, /// A Register variable.
PDB_Constant, /// A constant value.
PDB_UserDefinedType, /// A user defined type.
PDB_MultiRegisterVariable, /// A Register variable spanning multiple registers.
PDB_Data, /// Static data, such as a global variable.
PDB_Public, /// A public symbol with a mangled name.
PDB_Procedure, /// A procedure, such as a function or method.
PDB_ThreadStorage, /// A thread local variable.
PDB_CompileFlags, /// Flags used to compile a module.
PDB_UsingNamespace, /// A using namespace directive.
PDB_ProcedureReference, /// Reference to a [`ProcedureSymbol`].
PDB_DataReference, /// Reference to an imported variable.
PDB_AnnotationReference, /// Reference to an annotation.
PDB_Trampoline, /// Trampoline thunk.
PDB_Export, /// An exported symbol.
PDB_Local, /// A local symbol in optimized code.
PDB_BuildInfo, /// Reference to build information.
PDB_InlineSite, /// The callsite of an inlined function.
PDB_InlineSiteEnd, /// End of an inline callsite.
PDB_ProcedureEnd, /// End of a procedure.
PDB_Label, /// A label.
PDB_Block, /// A block.
PDB_RegisterRelative, /// Data allocated relative to a register.
PDB_Thunk, /// A thunk.
PDB_SeparatedCode, /// A block of separated code.
PDB_DefRange, /// A live range of a variable.
PDB_DefRangeSubField, /// A live range of a sub field of a variable.
PDB_DefRangeRegister, /// A live range of a register variable.
PDB_DefRangeFramePointerRelative, /// A live range of a frame pointer-relative variable.
PDB_DefRangeFramePointerRelativeFullScope, /// A frame-pointer variable which is valid in the full scope of the function.
PDB_DefRangeSubFieldRegister, /// A live range of a sub field of a register variable.
PDB_DefRangeRegisterRelative, /// A live range of a variable related to a register.
PDB_BasePointerRelative, /// A base pointer-relative variable.
PDB_FrameProcedure, /// Extra frame and proc information.
PDB_CallSiteInfo, /// Indirect call site information.
} kind;
void *data;
} PDBSymbol;
RZ_IPI bool PDBSymbol_parse(RzBuffer *b, PDBSymbol *symbol);
typedef struct {
@@ -96,5 +25,6 @@ RZ_IPI PDBSymbol *PDBSymbolTable_symbol_by_index(PDBSymbolTable *symbol_table, P
RZ_IPI bool PDBSymbolIter_next(PDBSymbolIter *iter, PDBSymbol *symbol);
RZ_IPI bool PDBSymbolIter_seek(PDBSymbolIter *iter, PDBSymbolIndex index);
RZ_IPI bool PDBSymbolIter_collect(PDBSymbolIter *iter, RzPVector /*<PDBSymbol *>*/ **psymbols);
#endif // RIZIN_SYMBOL_H
+850 -1031
View File
File diff suppressed because it is too large Load Diff
+68 -64
View File
@@ -6,6 +6,10 @@
#include <rz_util.h>
RZ_IPI bool tpi_stream_parse(RzPdb *pdb, RzPdbMsfStream *stream);
RZ_IPI RzPdbTpiType *simple_type_parse(RzPdbTpiStream *stream, ut32 idx);
RZ_IPI void tpi_stream_free(RzPdbTpiStream *stream);
/// enumeration for virtual shape table entries
typedef enum {
VTS_near = 0x00,
@@ -250,6 +254,8 @@ typedef enum {
LF_USER_DEFINED_TYPE_MODULE_SOURCE_AND_LINE = 0x1607,
LF_CLASS_19 = 0x1608,
LF_STRUCTURE_19 = 0x1609,
LF_UNION_19 = 0x160A,
LF_INTERFACE_19 = 0x160B,
LF_ID_LAST, // one greater than the last ID record
LF_ID_MAX = LF_ID_LAST - 1,
@@ -259,6 +265,7 @@ typedef enum {
* directly. If the data is more the 0x8000 or is a negative value,
* then the data is preceeded by the proper index.
*/
LF_NUMERIC = 0x8000,
LF_CHAR = 0x8000, // signed character leaf
LF_SHORT = 0x8001, // signed short leaf
LF_USHORT = 0x8002, // unsigned short leaf
@@ -350,15 +357,15 @@ typedef struct {
} TpiCVFldattr;
typedef struct cv_funcattr {
unsigned char cxxreturnudt : 1; // true if C++ style ReturnUDT
unsigned char ctor : 1; // true if func is an instance constructor
unsigned char ctorvbase : 1; // true if func is an instance constructor of a class with virtual bases
unsigned char unused : 5; // unused
RzPdbTpiCallingConvention calling_convention;
ut8 cxxreturnudt : 1; // true if C++ style ReturnUDT
ut8 ctor : 1; // true if func is an instance constructor
ut8 ctorvbase : 1; // true if func is an instance constructor of a class with virtual bases
ut8 unused : 5; // unused
} TpiCVFuncattr;
typedef struct {
ut32 return_type;
RzPdbTpiCallingConvention call_conv;
TpiCVFuncattr func_attr;
ut16 parm_count;
ut32 arg_list;
@@ -369,7 +376,6 @@ typedef struct {
ut32 return_type;
ut32 class_type;
ut32 this_type;
RzPdbTpiCallingConvention call_conv; // 1 byte
TpiCVFuncattr func_attr;
ut16 parm_count;
ut32 arglist;
@@ -454,70 +460,67 @@ typedef struct {
typedef struct {
ut32 utype;
TpiCVPointerAttr ptr_attr;
union {
struct {
ut32 pmclass; // index of containing class for pointer to member
ut16 pmtype; // TpiCVPmType
} pmember;
struct {
ut32 index; // type index if PTR_BASE_TYPE
} pbase;
};
PDBTypeIndex containing_class;
ut8 pad;
} Tpi_LF_Pointer;
typedef struct {
char *name;
ut32 size;
} Tpi_Type_String;
typedef struct {
ut16 type_index;
void *data;
bool is_integer;
} Tpi_Type_Numeric;
enum {
TpiVariant_U64,
TpiVariant_U32,
TpiVariant_U16,
TpiVariant_U8,
TpiVariant_I64,
TpiVariant_I32,
TpiVariant_I16,
TpiVariant_I8,
} tag;
union {
ut64 u64v;
ut32 u32v;
ut16 u16v;
ut8 u8v;
st64 i64v;
st32 i32v;
st16 i16v;
st8 i8v;
};
} TpiVariant;
typedef struct {
ut32 element_type;
ut32 index_type;
ut32 stride;
Tpi_Type_Numeric size;
Tpi_Type_String name;
RzVector /*<ut32>*/ dimensions;
ut8 pad;
} Tpi_LF_Array;
typedef struct {
ut16 count;
TpiCVProperty prop; // property attribute field
ut32 field_list; // type index of LF_FIELD descriptor list
ut32 derived; // type index of derived from list if not zero
ut32 vshape; // type index of vshape table for this class
Tpi_Type_Numeric size;
Tpi_Type_String name;
Tpi_Type_String mangled_name;
ut8 pad;
} Tpi_LF_Structure, Tpi_LF_Class;
typedef enum {
ClassKind_Class,
ClassKind_Struct,
ClassKind_Interface
} ClassKind;
typedef struct {
ut16 count;
ClassKind kind;
TpiCVProperty prop; // property attribute field
ut16 unknown;
ut32 field_list; // type index of LF_FIELD descriptor list
ut32 derived; // type index of derived from list if not zero
ut32 vshape; // type index of vshape table for this class
Tpi_Type_Numeric unknown1;
Tpi_Type_Numeric size;
Tpi_Type_String name;
Tpi_Type_String mangled_name;
ut64 size;
char *name;
char *mangled_name;
ut8 pad;
} Tpi_LF_Structure_19, Tpi_LF_Class_19;
} Tpi_LF_Structure, Tpi_LF_Class;
typedef struct {
ut16 count;
TpiCVProperty prop;
ut32 field_list;
Tpi_Type_Numeric size;
Tpi_Type_String name;
Tpi_Type_String mangled_name;
ut64 size;
char *name;
char *mangled_name;
ut32 pad;
} Tpi_LF_Union;
@@ -530,7 +533,7 @@ typedef struct {
typedef struct {
ut16 count;
char *vt_descriptors;
RzVector /*<ut8>*/ descriptors;
ut8 pad;
} Tpi_LF_Vtshape;
@@ -555,22 +558,22 @@ typedef struct {
TpiCVProperty prop;
ut32 utype;
ut32 field_list;
Tpi_Type_String name;
Tpi_Type_String mangled_name;
char *name;
char *mangled_name;
ut8 pad;
} Tpi_LF_Enum;
typedef struct {
TpiCVFldattr fldattr;
Tpi_Type_Numeric enum_value;
Tpi_Type_String name;
TpiVariant value;
char *name;
ut8 pad;
} Tpi_LF_Enumerate;
typedef struct {
ut16 pad;
TpiCVFldattr fldattr;
ut32 index;
Tpi_Type_String name;
char *name;
} Tpi_LF_NestType;
typedef struct {
@@ -581,7 +584,7 @@ typedef struct {
typedef struct {
ut16 count;
ut32 mlist;
Tpi_Type_String name;
char *name;
ut8 pad;
} Tpi_LF_Method;
@@ -593,21 +596,21 @@ typedef struct {
} Tpi_Type_MethodListMember;
typedef struct {
RzList /*<Tpi_Type_MethodListMember *>*/ *members;
RzPVector /*<Tpi_Type_MethodListMember *>*/ members;
} Tpi_LF_MethodList;
typedef struct {
TpiCVFldattr fldattr;
ut32 index;
Tpi_Type_Numeric offset;
Tpi_Type_String name;
ut32 field_type;
ut64 offset;
char *name;
ut8 pad;
} Tpi_LF_Member;
typedef struct {
TpiCVFldattr fldattr;
ut32 index;
Tpi_Type_String name;
ut32 field_type;
char *name;
ut8 pad;
} Tpi_LF_StaticMember;
@@ -621,14 +624,15 @@ typedef struct {
TpiCVFldattr fldattr;
ut32 index;
ut32 offset_in_vtable;
Tpi_Type_String name;
char *name;
ut8 pad;
} Tpi_LF_OneMethod;
typedef struct {
ClassKind kind;
TpiCVFldattr fldattr;
ut32 index;
Tpi_Type_Numeric offset;
ut64 offset;
ut8 pad;
} Tpi_LF_BClass;
@@ -636,8 +640,8 @@ typedef struct {
TpiCVFldattr fldattr;
ut32 direct_vbclass_idx;
ut32 vb_pointer_idx;
Tpi_Type_Numeric vb_pointer_offset;
Tpi_Type_Numeric vb_offset_from_vbtable;
ut64 vb_pointer_offset;
ut64 vb_offset_from_vbtable;
} Tpi_LF_VBClass, Tpi_LF_IVBClass;
typedef struct {
+185 -116
View File
@@ -114,87 +114,96 @@ static void rz_core_bin_pdb_types_print(const RzTypeDB *db, const RzPdb *pdb, co
}
}
typedef struct {
RzStrBuf *buf;
const ut64 baddr;
RzCmdStateOutput *state;
} PDBDumpContext;
static bool symbol_dump(const RzPdb *pdb, const PDBSymbol *symbol, void *u) {
PDBDumpContext *ctx = u;
PJ *pj = ctx->state->d.pj;
if (symbol->kind == PDB_Public) {
const PDBSPublic *public = symbol->data;
PeImageSectionHeader *sctn_header = pdb_section_hdr_by_index(pdb->s_pe, public->offset.section_index);
if (!sctn_header) {
return true;
}
ut64 addr = rz_bin_pdb_to_rva(pdb, &public->offset);
if (addr == UT64_MAX) {
return true;
}
if (ctx->baddr != UT64_MAX) {
addr += ctx->baddr;
}
char *name = rz_demangler_msvc(public->name, RZ_DEMANGLER_FLAG_BASE);
name = (name) ? name : strdup(public->name);
switch (ctx->state->mode) {
case RZ_OUTPUT_MODE_JSON: // JSON
pj_o(pj);
pj_kn(pj, "address", addr);
pj_kN(pj, "symtype", symbol->raw_kind);
pj_ks(pj, "section_name", sctn_header->name);
pj_ks(pj, "gdata_name", name);
pj_end(pj);
break;
case RZ_OUTPUT_MODE_STANDARD:
rz_strbuf_appendf(ctx->buf, "0x%08" PFMT64x " %d %.*s %s\n",
addr,
symbol->raw_kind, PDB_SIZEOF_SECTION_NAME, sctn_header->name, name);
break;
default:
break;
}
free(name);
}
return true;
}
/**
* \brief Return the PDB global vars string
*
* \param pdb PDB instance
* \param img_base image base addr
* \param pj JSON instance
* \param mode RzOutputMode
* \param baddr image base addr
* \param state The RzCmdStateOutput instance
* \return char *
*/
RZ_API char *rz_core_bin_pdb_gvars_as_string(RZ_NONNULL const RzPdb *pdb, const ut64 img_base, PJ *pj, const RzOutputMode mode) {
rz_return_val_if_fail(pdb, NULL);
RzPdbGDataStream *gsym_data_stream = 0;
RzPdbPeStream *pe_stream = 0;
RZ_API char *rz_core_bin_pdb_gvars_as_string(
RZ_NONNULL const RzPdb *pdb, const ut64 baddr, RzCmdStateOutput *state) {
rz_return_val_if_fail(pdb && state, NULL);
RzStrBuf *buf = rz_strbuf_new(NULL);
if (!buf) {
return NULL;
}
if (mode == RZ_OUTPUT_MODE_JSON) {
PJ *pj = state->d.pj;
if (state->mode == RZ_OUTPUT_MODE_JSON) {
pj_o(pj);
pj_ka(pj, "gvars");
}
gsym_data_stream = pdb->s_gdata;
pe_stream = pdb->s_pe;
if (!pe_stream) {
if (!pdb->s_pe) {
rz_strbuf_free(buf);
return NULL;
}
void **it;
rz_pvector_foreach (gsym_data_stream->global_symbols, it) {
PDBSymbol *symbol = *it;
if (symbol->kind == PDB_Public) {
PDBSPublic *public = symbol->data;
PeImageSectionHeader *sctn_header = pdb_section_hdr_by_index(pdb->s_pe, public->offset.section_index);
if (!sctn_header) {
continue;
}
ut64 addr = rz_bin_pdb_to_rva(pdb, &public->offset);
if (addr == UT64_MAX) {
continue;
}
if (img_base != UT64_MAX) {
addr += img_base;
}
char *name = rz_demangler_msvc(public->name, RZ_DEMANGLER_FLAG_BASE);
name = (name) ? name : strdup(public->name);
switch (mode) {
case RZ_OUTPUT_MODE_JSON: // JSON
pj_o(pj);
pj_kn(pj, "address", addr);
pj_kN(pj, "symtype", symbol->raw_kind);
pj_ks(pj, "section_name", sctn_header->name);
pj_ks(pj, "gdata_name", name);
pj_end(pj);
break;
case RZ_OUTPUT_MODE_STANDARD:
rz_strbuf_appendf(buf, "0x%08" PFMT64x " %d %.*s %s\n",
addr,
symbol->raw_kind, PDB_SIZEOF_SECTION_NAME, sctn_header->name, name);
break;
default:
break;
}
free(name);
}
}
if (mode == RZ_OUTPUT_MODE_JSON) {
PDBDumpContext ctx = {
.buf = buf,
.baddr = baddr,
.state = state,
};
rz_pdb_all_symbols_foreach(pdb, symbol_dump, &ctx);
if (state->mode == RZ_OUTPUT_MODE_JSON) {
pj_end(pj);
pj_end(pj);
// We will need this for Windows Heap.
rz_strbuf_append(buf, pj_string(pj));
}
char *str = strdup(rz_strbuf_get(buf));
rz_strbuf_free(buf);
return str;
return rz_strbuf_drain(buf);
}
static void rz_core_bin_pdb_gvars_print(const RzPdb *pdb, const ut64 img_base, const RzCmdStateOutput *state) {
static void rz_core_bin_pdb_gvars_print(const RzPdb *pdb, const ut64 baddr, RzCmdStateOutput *state) {
rz_return_if_fail(pdb && state);
char *str = rz_core_bin_pdb_gvars_as_string(pdb, img_base, state->d.pj, state->mode);
char *str = rz_core_bin_pdb_gvars_as_string(pdb, baddr, state);
// We don't need to print the output of JSON because the RzCmdStateOutput will handle it.
if (state->mode == RZ_OUTPUT_MODE_STANDARD) {
rz_cons_print(str);
@@ -202,65 +211,91 @@ static void rz_core_bin_pdb_gvars_print(const RzPdb *pdb, const ut64 img_base, c
free(str);
}
static void pdb_set_symbols(
const RzCore *core, const RzPdb *pdb, const ut64 img_base, const char *pdbfile) {
typedef struct {
const RzCore *core;
const ut64 baddr;
const char *file;
} PDBLoadContext;
static bool symbol_load(const RzPdb *pdb, const PDBSymbol *symbol, void *u) {
if (!symbol) {
return true;
}
PDBLoadContext *ctx = u;
const RzDemanglerFlag dflags = rz_demangler_get_flags(ctx->core->bin->demangler);
if (symbol->kind == PDB_Public) {
const PDBSPublic *public = symbol->data;
if (RZ_STR_ISEMPTY(public->name)) {
return true;
}
char *name = rz_demangler_msvc(public->name, dflags);
name = (name) ? name : strdup(public->name);
char *filtered_name = rz_name_filter2(name, true);
char *fname = rz_str_newf("pdb.%s.%s", ctx->file, filtered_name);
ut64 addr = rz_bin_pdb_to_rva(pdb, &public->offset);
if (addr == UT64_MAX) {
return true;
}
if (ctx->baddr != UT64_MAX) {
addr += ctx->baddr;
}
RzFlagItem *item = rz_flag_set(ctx->core->flags, fname, addr, 0);
if (item) {
rz_flag_item_set_realname(item, name);
}
free(filtered_name);
free(fname);
free(name);
} else if (symbol->kind == PDB_Data) {
const PDBSData *data = symbol->data;
if (RZ_STR_ISEMPTY(data->name)) {
return true;
}
ut64 addr = rz_bin_pdb_to_rva(pdb, &data->offset);
if (addr == UT64_MAX) {
return true;
}
if (ctx->baddr != UT64_MAX) {
addr += ctx->baddr;
}
RzPdbTpiType *t = rz_bin_pdb_get_type_by_index(pdb->s_tpi, data->type_index);
if (!t) {
return true;
}
RzType *rt = rz_type_db_pdb_parse(ctx->core->analysis->typedb, pdb->s_tpi, t);
if (!rt) {
return true;
}
rz_analysis_var_global_create(ctx->core->analysis, data->name, rt, addr);
}
return true;
}
static void pdb_symbols_load(
const RzCore *core, const RzPdb *pdb, const char *pdbfile) {
rz_return_if_fail(core && pdb);
if (!(pdb->s_pe && pdb->s_gdata)) {
return;
}
RzDemanglerFlag dflags = rz_demangler_get_flags(core->bin->demangler);
ut64 baddr = rz_bin_get_baddr(core->bin);
if (!baddr || baddr == UT64_MAX) {
baddr = rz_config_get_i(core->config, "bin.baddr");
RZ_LOG_WARN("core: cannot find base address, flags will probably be misplaced\n");
}
char *file = rz_str_replace(strdup(pdbfile), ".pdb", "", 0);
rz_flag_space_push(core->flags, RZ_FLAGS_FS_SYMBOLS);
void **it;
rz_pvector_foreach (pdb->s_gdata->global_symbols, it) {
PDBSymbol *symbol = *it;
if (symbol->kind == PDB_Public) {
PDBSPublic *public = symbol->data;
PDBLoadContext ctx = {
.core = core,
.baddr = baddr,
.file = file,
};
rz_pdb_all_symbols_foreach(pdb, symbol_load, &ctx);
char *name = rz_demangler_msvc(public->name, dflags);
name = (name) ? name : strdup(public->name);
char *filtered_name = rz_name_filter2(name, true);
char *fname = rz_str_newf("pdb.%s.%s", file, filtered_name);
ut64 addr = rz_bin_pdb_to_rva(pdb, &public->offset);
if (addr == UT64_MAX) {
continue;
}
if (img_base != UT64_MAX) {
addr += img_base;
}
RzFlagItem *item = rz_flag_set(core->flags, fname, addr, 0);
if (item) {
rz_flag_item_set_realname(item, name);
}
free(filtered_name);
free(name);
} else if (symbol->kind == PDB_Data) {
const PDBSData *data = symbol->data;
if (!data->global) {
continue;
}
ut64 addr = rz_bin_pdb_to_rva(pdb, &data->offset);
if (addr == UT64_MAX) {
continue;
}
if (img_base != UT64_MAX) {
addr += img_base;
}
RzPdbTpiType *t = rz_bin_pdb_get_type_by_index(pdb->s_tpi, data->type_index);
if (!t) {
continue;
}
RzType *rt = rz_type_db_pdb_parse(core->analysis->typedb, pdb->s_tpi, t);
if (!rt) {
continue;
}
rz_analysis_var_global_create(core->analysis, data->name, rt, addr);
}
}
rz_flag_space_pop(core->flags);
free(file);
}
@@ -274,13 +309,6 @@ static void pdb_set_symbols(
*/
RZ_API RzPdb *rz_core_pdb_load_info(RZ_NONNULL RzCore *core, RZ_NONNULL const char *file) {
rz_return_val_if_fail(core && file, NULL);
ut64 baddr = rz_bin_get_baddr(core->bin);
if (!baddr || baddr == UT64_MAX) {
baddr = rz_config_get_i(core->config, "bin.baddr");
RZ_LOG_WARN("core: cannot find base address, flags will probably be misplaced\n");
}
RzPdb *pdb = rz_bin_pdb_parse_from_file(file);
if (!pdb) {
return NULL;
@@ -288,10 +316,50 @@ RZ_API RzPdb *rz_core_pdb_load_info(RZ_NONNULL RzCore *core, RZ_NONNULL const ch
// Save compound types into types database
rz_type_db_pdb_load(core->analysis->typedb, pdb);
pdb_set_symbols(core, pdb, baddr, rz_file_basename(file));
pdb_symbols_load(core, pdb, rz_file_basename(file));
return pdb;
}
static void pdb_modules_print(RZ_NONNULL RzPdb *pdb, RZ_NONNULL RzCmdStateOutput *state) {
if (!(pdb->s_dbi && pdb->s_dbi->modules)) {
return;
}
PJ *j = state->d.pj;
switch (state->mode) {
case RZ_OUTPUT_MODE_JSON:
pj_o(j);
pj_ka(j, "modules");
break;
case RZ_OUTPUT_MODE_STANDARD: {
rz_cons_println("modules:");
break;
}
default: rz_warn_if_reached();
}
void **it;
rz_pvector_foreach (pdb->s_dbi->modules, it) {
PDB_DBIModule *module = *it;
switch (state->mode) {
case RZ_OUTPUT_MODE_JSON: {
pj_o(j);
pj_ks(j, "module_name", module->module_name);
pj_ks(j, "object_file_name", module->object_file_name);
pj_end(j);
break;
}
case RZ_OUTPUT_MODE_STANDARD: {
rz_cons_println(module->module_name);
break;
}
default: rz_warn_if_reached();
}
}
if (state->mode == RZ_OUTPUT_MODE_JSON) {
pj_end(j);
pj_end(j);
}
}
/**
* \brief Print parsed PDB file info
*
@@ -311,6 +379,7 @@ RZ_API void rz_core_pdb_info_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzTypeDB
}
rz_cmd_state_output_array_start(state);
pdb_modules_print(pdb, state);
rz_core_bin_pdb_types_print(core->analysis->typedb, pdb, state);
rz_core_bin_pdb_gvars_print(pdb, baddr, state);
rz_cmd_state_output_array_end(state);
+48 -44
View File
@@ -268,6 +268,38 @@ static inline bool has_heap_globals(void) {
return RtlpHpHeapGlobalsOffset && RtlpLFHKeyOffset;
}
static bool symbol_do(const RzPdb *pdb, const PDBSymbol *symbol, void *u) {
if (has_heap_globals()) {
return false;
}
if (symbol->kind != PDB_Public) {
return true;
}
ut64 baddr = (ut64)u;
const PDBSPublic *data = symbol->data;
if (!(data && data->name)) {
return true;
}
ut64 addr = rz_bin_pdb_to_rva(pdb, &data->offset);
if (addr == UT64_MAX) {
return true;
}
if (baddr != UT64_MAX) {
addr += baddr;
}
char *name = rz_demangler_msvc(data->name, RZ_DEMANGLER_FLAG_BASE);
if (RZ_STR_EQ(name, "RtlpHpHeapGlobals")) {
RtlpHpHeapGlobalsOffset = addr;
}
if (RZ_STR_EQ(name, "RtlpLFHKey")) {
RtlpLFHKeyOffset = addr;
}
free(name);
return true;
}
static bool GetHeapGlobalsOffset(RzDebug *dbg, HANDLE h_proc) {
if (has_heap_globals()) {
return true;
@@ -311,11 +343,13 @@ static bool GetHeapGlobalsOffset(RzDebug *dbg, HANDLE h_proc) {
rz_io_fd_close(core->io, fd);
return false;
}
char *pdb_path = NULL;
RzPdb *pdb = NULL;
RzBinInfo *info = rz_bin_get_info(core->bin);
if (!info) {
goto fail;
}
char *pdb_path = rz_str_newf("%s\\ntdll.pdb\\%s\\ntdll.pdb",
pdb_path = rz_str_newf("%s\\ntdll.pdb\\%s\\ntdll.pdb",
rz_config_get(core->config, "pdb.symstore"), info->guid);
if (!pdb_path) {
goto fail;
@@ -328,62 +362,28 @@ static bool GetHeapGlobalsOffset(RzDebug *dbg, HANDLE h_proc) {
opts.symbol_server = rz_config_get(core->config, "pdb.server");
if (rz_bin_pdb_download(core->bin, NULL, false, &opts)) {
RZ_LOG_ERROR("core: Failed to download ntdll.pdb file\n");
free(pdb_path);
goto fail;
}
}
// Get ntdll.dll PDB info and parse json output
RzPdb *pdb = rz_bin_pdb_parse_from_file(pdb_path);
pdb = rz_bin_pdb_parse_from_file(pdb_path);
if (!pdb) {
free(pdb_path);
goto fail;
}
free(pdb_path);
ut64 baddr = rz_config_get_i(core->config, "bin.baddr");
if (core->bin->cur && core->bin->cur->o && core->bin->cur->o->opts.baseaddr) {
baddr = core->bin->cur->o->opts.baseaddr;
} else {
RZ_LOG_WARN("core: Cannot find base address, flags will probably be misplaced\n");
}
PJ *pj = pj_new();
if (!pj) {
rz_bin_pdb_free(pdb);
goto fail;
}
char *j = rz_core_bin_pdb_gvars_as_string(pdb, baddr, pj, RZ_OUTPUT_MODE_JSON);
if (!j) {
rz_bin_pdb_free(pdb);
pj_free(pj);
goto fail;
}
pj_free(pj);
rz_bin_pdb_free(pdb);
RzJson *json = rz_json_parse(j);
if (!json) {
RZ_LOG_ERROR("core: rz_core_pdb_info returned invalid JSON");
free(j);
goto fail;
}
free(j);
// Go through gvars array and search for the heap globals symbols
const RzJson *gvars = rz_json_get(json, "gvars");
gvars = gvars->children.first;
do {
const RzJson *gdata_name = rz_json_get(gvars, "gdata_name");
if (!strcmp(gdata_name->str_value, "RtlpHpHeapGlobals")) {
const RzJson *address = rz_json_get(gvars, "address");
RtlpHpHeapGlobalsOffset = address->num.u_value;
} else if (!strcmp(gdata_name->str_value, "RtlpLFHKey")) {
const RzJson *address = rz_json_get(gvars, "address");
RtlpLFHKeyOffset = address->num.u_value;
}
} while ((gvars = gvars->next) && !has_heap_globals());
rz_pdb_all_symbols_foreach(pdb, symbol_do, (void *)baddr);
free(json);
fail:
rz_bin_pdb_free(pdb);
free(pdb_path);
rz_bin_file_delete(core->bin, bf);
rz_bin_file_set_cur_binfile(core->bin, obf);
rz_io_fd_close(core->io, fd);
@@ -685,7 +685,8 @@ static bool GetSegmentHeapBlocks(RzDebug *dbg, HANDLE h_proc, PVOID heapBase, PH
PRTL_BALANCED_NODE node = malloc(sizeof(RTL_BALANCED_NODE));
RzStack *s = rz_stack_new(segheapHeader.LargeReservedPages);
PRTL_BALANCED_NODE curr = segheapHeader.LargeAllocMetadata.Root;
do { // while (!rz_stack_is_empty(s));
do {
// while (!rz_stack_is_empty(s));
GROW_PBLOCKS();
while (curr) {
rz_stack_push(s, curr);
@@ -870,7 +871,8 @@ static PDEBUG_BUFFER GetHeapBlocks(DWORD pid, RzDebug *dbg) {
curEntry = lfhHeader.SubSegmentZones.Flink;
// Loops through all _HEAP_SUBSEGMENTs
do { // (curEntry != firstEntry)
do {
// (curEntry != firstEntry)
HEAP_LOCAL_SEGMENT_INFO info;
HEAP_LOCAL_DATA localData;
HEAP_SUBSEGMENT subsegment;
@@ -879,7 +881,8 @@ static PDEBUG_BUFFER GetHeapBlocks(DWORD pid, RzDebug *dbg) {
WPARAM curSubsegment = (WPARAM)(curEntry + 2);
int next = 0;
do { // (next < blockZone.NextIndex)
do {
// (next < blockZone.NextIndex)
if (!ReadProcessMemory(h_proc, (PVOID)curSubsegment, &subsegment, sizeof(HEAP_SUBSEGMENT), &bytesRead) || !subsegment.BlockSize || !ReadProcessMemory(h_proc, subsegment.LocalInfo, &info, sizeof(HEAP_LOCAL_SEGMENT_INFO), &bytesRead) || !ReadProcessMemory(h_proc, info.LocalData, &localData, sizeof(HEAP_LOCAL_DATA), &bytesRead) || !ReadProcessMemory(h_proc, localData.CrtZone, &blockZone, sizeof(LFH_BLOCK_ZONE), &bytesRead)) {
break;
}
@@ -1032,7 +1035,8 @@ static PHeapBlock GetSingleSegmentBlock(RzDebug *dbg, HANDLE h_proc, PSEGMENT_HE
WPARAM segSignature;
ReadProcessMemory(h_proc, (PVOID)(pgSegOff + sizeof(LIST_ENTRY)), &segSignature, sizeof(WPARAM), NULL); // HEAP_PAGE_SEGMENT.Signature
WPARAM test = RtlpHpHeapGlobal ^ pgSegOff ^ segSignature ^ ((WPARAM)heapBase + offsetof(SEGMENT_HEAP, SegContexts));
if (test == 0xa2e64eada2e64ead) { // Hardcoded in ntdll
if (test == 0xa2e64eada2e64ead) {
// Hardcoded in ntdll
HEAP_PAGE_SEGMENT segment;
ReadProcessMemory(h_proc, (PVOID)pgSegOff, &segment, sizeof(HEAP_PAGE_SEGMENT), NULL);
WPARAM pgRangeDescOff = ((headerOff - pgSegOff) >> heap.SegContexts[0].UnitShift) << 5;
@@ -1508,4 +1512,4 @@ RZ_IPI RzList *rz_heap_list(RzCore *core) {
RtlDestroyQueryDebugBuffer(db);
return heaps_list;
}
}
+1 -1
View File
@@ -994,7 +994,7 @@ RZ_API RZ_OWN char *rz_core_bin_pdb_get_filename(RZ_NONNULL RzCore *core);
RZ_API bool rz_core_bin_pdb_load(RZ_NONNULL RzCore *core, RZ_NONNULL const char *filename);
RZ_API RzPdb *rz_core_pdb_load_info(RZ_NONNULL RzCore *core, RZ_NONNULL const char *file);
RZ_API void rz_core_pdb_info_print(RZ_NONNULL RzCore *core, RZ_NONNULL RzTypeDB *db, RZ_NONNULL RzPdb *pdb, RZ_NONNULL RzCmdStateOutput *state);
RZ_API char *rz_core_bin_pdb_gvars_as_string(RZ_NONNULL const RzPdb *pdb, const ut64 img_base, PJ *pj, const RzOutputMode mode);
RZ_API char *rz_core_bin_pdb_gvars_as_string(RZ_NONNULL const RzPdb *pdb, const ut64 img_base, RzCmdStateOutput *state);
RZ_API RzCmdStatus rz_core_bin_plugins_print(RzBin *bin, RzCmdStateOutput *state);
RZ_API bool rz_core_bin_archs_print(RZ_NONNULL RzBin *bin, RZ_NONNULL RzCmdStateOutput *state);
+121 -4
View File
@@ -58,9 +58,9 @@ typedef struct {
typedef struct dbi_stream_t {
RzPdbRzPdbDbiStreamHdr hdr;
RzList /*<RzPdbDbiStreamExHdr *>*/ *ex_hdrs;
ut64 hdr_size;
RzPVector /*<PDB_DBIModule *>*/ *modules;
RzPdbRzPdbDbiStreamDbgHeader dbg_hdr;
} RzPdbDbiStream;
// GDATA
@@ -141,11 +141,42 @@ typedef struct tpi_stream_header_t {
ut32 HashAdjBufferLength;
} RzPdbTpiStreamHeader;
typedef enum {
TpiKind_INVALID,
TpiKind_FILEDLIST,
TpiKind_ENUM,
TpiKind_ENUMERATE,
TpiKind_CLASS,
TpiKind_UNION,
TpiKind_BITFIELD,
TpiKind_POINTER,
TpiKind_ARRAY,
TpiKind_MODIFIER,
TpiKind_ARGLIST,
TpiKind_MFUNCTION,
TpiKind_METHODLIST,
TpiKind_PROCEDURE,
TpiKind_VTSHAPE,
TpiKind_VFTABLE,
TpiKind_LABEL,
TpiKind_NESTTYPE,
TpiKind_MEMBER,
TpiKind_METHOD,
TpiKind_ONEMETHOD,
TpiKind_BCLASS,
TpiKind_VFUNCTAB,
TpiKind_STMEMBER,
TpiKind_VBCLASS,
TpiKind_INDEX,
TpiKind_SIMPLE_TYPE,
} RzPDBTpiKind;
typedef struct tpi_types {
RBNode rb;
ut32 index;
ut16 leaf;
ut16 length;
RzPDBTpiKind kind;
void *data;
bool parsed;
} RzPdbTpiType;
@@ -238,16 +269,25 @@ typedef struct {
RzBuffer *sd;
} RzPdbMsfStreamDirectory;
typedef struct {
RzBuffer *stream;
ut32 symbols_size;
ut16 stream_index;
RzPVector /*<PDBSymbol *>*/ *symbols;
} PDBModuleInfo;
typedef struct rz_pdb_t {
RzBuffer *buf; // mmap of file
RzPdbMsfSuperBlock *super_block;
RzList /*<RzPdbMsfStream *>*/ *streams;
RzPdbMsfStreamDirectory *msd;
RzPVector /*<RzPdbMsfStream *>*/ *streams;
RzPdbStream *s_pdb;
RzPdbDbiStream *s_dbi;
RzPdbTpiStream *s_tpi;
RzPdbGDataStream *s_gdata;
RzPdbOmapStream *s_omap;
RzPdbPeStream *s_pe;
RzPVector /*<PDBModuleInfo *>*/ *module_infos;
} RzPdb;
typedef struct {
@@ -255,11 +295,86 @@ typedef struct {
ut16 section_index;
} PDBSectionOffset;
typedef ut16 PDBSymbolKind;
typedef ut32 PDBTypeIndex;
typedef ut32 PDBSymbolIndex;
typedef struct {
bool global : 1;
bool managed : 1;
PDBTypeIndex type_index;
PDBSectionOffset offset;
char *name;
} PDBSData;
RZ_IPI bool PDBSData_parse(RzBuffer *b, PDBSymbolKind kind, PDBSData *sdata);
typedef struct {
bool code : 1;
bool function : 1;
bool managed : 1;
bool msil : 1;
PDBSectionOffset offset;
char *name;
} PDBSPublic;
RZ_IPI bool PDBSPublic_parse(RzBuffer *b, PDBSymbolKind kind, PDBSPublic *s);
typedef struct {
PDBSymbolIndex index;
PDBSymbolKind raw_kind;
ut16 length;
enum {
PDB_ScopeEnd, /// End of a scope, such as a procedure.
PDB_ObjName, /// Name of the object file of this module.
PDB_RegisterVariable, /// A Register variable.
PDB_Constant, /// A constant value.
PDB_UserDefinedType, /// A user defined type.
PDB_MultiRegisterVariable, /// A Register variable spanning multiple registers.
PDB_Data, /// Static data, such as a global variable.
PDB_Public, /// A public symbol with a mangled name.
PDB_Procedure, /// A procedure, such as a function or method.
PDB_ThreadStorage, /// A thread local variable.
PDB_CompileFlags, /// Flags used to compile a module.
PDB_UsingNamespace, /// A using namespace directive.
PDB_ProcedureReference, /// Reference to a [`ProcedureSymbol`].
PDB_DataReference, /// Reference to an imported variable.
PDB_AnnotationReference, /// Reference to an annotation.
PDB_Trampoline, /// Trampoline thunk.
PDB_Export, /// An exported symbol.
PDB_Local, /// A local symbol in optimized code.
PDB_BuildInfo, /// Reference to build information.
PDB_InlineSite, /// The callsite of an inlined function.
PDB_InlineSiteEnd, /// End of an inline callsite.
PDB_ProcedureEnd, /// End of a procedure.
PDB_Label, /// A label.
PDB_Block, /// A block.
PDB_RegisterRelative, /// Data allocated relative to a register.
PDB_Thunk, /// A thunk.
PDB_SeparatedCode, /// A block of separated code.
PDB_DefRange, /// A live range of a variable.
PDB_DefRangeSubField, /// A live range of a sub field of a variable.
PDB_DefRangeRegister, /// A live range of a register variable.
PDB_DefRangeFramePointerRelative, /// A live range of a frame pointer-relative variable.
PDB_DefRangeFramePointerRelativeFullScope, /// A frame-pointer variable which is valid in the full scope of the function.
PDB_DefRangeSubFieldRegister, /// A live range of a sub field of a register variable.
PDB_DefRangeRegisterRelative, /// A live range of a variable related to a register.
PDB_BasePointerRelative, /// A base pointer-relative variable.
PDB_FrameProcedure, /// Extra frame and proc information.
PDB_CallSiteInfo, /// Indirect call site information.
} kind;
void *data;
} PDBSymbol;
// PDB
RZ_API bool rz_bin_pdb_extract_in_folder(RZ_NONNULL const char *file_cab, RZ_NONNULL const char *output_dir);
RZ_API RZ_OWN RzPdb *rz_bin_pdb_parse_from_file(RZ_NONNULL const char *filename);
RZ_API RZ_OWN RzPdb *rz_bin_pdb_parse_from_buf(RZ_NONNULL const RzBuffer *buf);
RZ_API void rz_bin_pdb_free(RzPdb *pdb);
RZ_API bool rz_pdb_all_symbols_foreach(
RZ_BORROW RZ_NONNULL const RzPdb *pdb,
RZ_BORROW RZ_NONNULL bool (*f)(const RzPdb *, const PDBSymbol *, void *),
RZ_BORROW RZ_NULLABLE void *u);
// TPI
RZ_API RZ_BORROW RzPdbTpiType *rz_bin_pdb_get_type_by_index(RZ_NONNULL RzPdbTpiStream *stream, ut32 index);
@@ -270,7 +385,9 @@ RZ_API RZ_BORROW char *rz_bin_pdb_get_type_name(RZ_NONNULL RzPdbTpiType *type);
RZ_API ut64 rz_bin_pdb_get_type_val(RZ_NONNULL RzPdbTpiType *type);
// OMAP
RZ_API ut64 rz_bin_pdb_to_rva(RZ_NONNULL const RzPdb *pdb, const PDBSectionOffset *section_offset);
RZ_API ut64 rz_bin_pdb_to_rva(
RZ_BORROW RZ_NONNULL const RzPdb *pdb,
RZ_BORROW RZ_NONNULL const PDBSectionOffset *section_offset);
#ifdef __cplusplus
}
+3 -1
View File
@@ -643,10 +643,12 @@ RZ_API ut64 rz_buf_read_string(RZ_NONNULL RzBuffer *b, RZ_BORROW RZ_NULLABLE cha
if (!tmp) {
return 0;
}
ut64 string_len = strlen(tmp) + 1;
const ut64 string_len = strlen(tmp) + 1;
rz_buf_seek(b, string_len, RZ_BUF_CUR);
if (s) {
*s = tmp;
} else {
free(tmp);
}
return string_len;
}
+16
View File
@@ -31,6 +31,22 @@ FILE==
CMDS=idpij bins/pdb/minimal.pdb~{}
EXPECT=<<EOF
[
{
"modules": [
{
"module_name": "* Linker Generated Manifest RES *",
"object_file_name": ""
},
{
"module_name": "C:\\Users\\emuresan\\source\\repos\\minimal\\Release\\main.obj",
"object_file_name": "C:\\Users\\emuresan\\source\\repos\\minimal\\Release\\main.obj"
},
{
"module_name": "* Linker *",
"object_file_name": ""
}
]
},
{
"types": [
{
+136 -55
View File
@@ -1,3 +1,42 @@
NAME=Modules from PDB
FILE=
CMDS=<<EOF
idpi bins/pdb/Project1.pdb~:..30
EOF
EXPECT=<<EOF
modules:
* Linker Generated Manifest RES *
C:\Users\inisider\documents\visual studio 2012\Projects\Project1\Project1\Debug\Source.obj
KERNEL32.dll
Import:KERNEL32.dll
F:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\xdll_lib\unhandld.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\atonexit.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\cinitexe.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\crtexe.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\dllargv.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\gs_cookie.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\gs_report.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\gs_support.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\merr.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\natstart.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\pesect.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\wildcard.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\asm\dllsupp.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\INTEL\xdll_lib\chandler4gs.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\fp8.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\loadcfg.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\secchk.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\_newmode.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\xncommod.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\xtxtmode.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\src\build\INTEL\xdll_obj\nativec\xthdloc.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\prebuild\build\INTEL\xdll_obj\rtc\nativecpp\\userapi.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\prebuild\build\INTEL\xdll_obj\rtc\nativecpp\\stack.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\prebuild\build\INTEL\xdll_obj\rtc\nativecpp\\pdblkup.obj
F:\dd\vctools\crt_bld\SELF_X86\crt\prebuild\build\INTEL\xdll_obj\rtc\nativecpp\\initsect.obj
EOF
RUN
NAME=Load global variables from PDB
FILE=
CMDS=<<EOF
@@ -5,33 +44,53 @@ idp bins/pdb/Project1.pdb
avg
EOF
EXPECT=<<EOF
global int32_t (*type_0x1028)() (*type_0x1097)(int32_t (*type_0x1028)()) _imp___onexit @ 0x19248
global void * __native_startup_lock @ 0x18548
global int32_t __native_startup_state @ 0x18558
global struct IMAGE_LOAD_CONFIG_DIRECTORY32_2 _load_config_used @ 0x165b0
global int32_t (*type_0x1450)(char *arg0, const char *arg1) wsprintffp @ 0x1815c
global void (*type_0x1093)() [4] __rtc_izz @ 0x16ae8
global wchar_t [26] mspdbName @ 0x1640c
global char ** argv @ 0x18140
global void (**type_0x1093)() __onexitbegin @ 0x1856c
global uint32_t __security_cookie @ 0x18024
global void (*type_0x1093)() [4] __rtc_iaa @ 0x168e0
global int32_t __defaultmatherr @ 0x18018
global void * __native_startup_lock @ 0x18548
global int32_t has_cctor @ 0x18138
global int32_t __native_startup_state @ 0x18558
global uint32_t __native_dllmain_reason @ 0x18020
global int32_t _dowildcard @ 0x18170
global struct _EXCEPTION_RECORD GS_ExceptionRecord @ 0x18188
global void (*type_0x1093)() [4] __xc_a @ 0x15000
global void (*type_0x1093)() [4] __xi_a @ 0x1530c
global bool init @ 0x18130
global int32_t argret @ 0x18148
global int32_t argc @ 0x1813c
global int32_t (*type_0x1028)() pinit @ 0x15514
global wchar_t [8] dllExt @ 0x1654c
global int32_t managedapp @ 0x1814c
global struct HINSTANCE__ * mspdb @ 0x1817c
global void (*type_0x1093)() [4] __xi_z @ 0x1571c
global struct _EXCEPTION_POINTERS GS_ExceptionPointers @ 0x165a0
global int32_t __globallocalestatus @ 0x1801c
global int32_t _commode @ 0x1816c
global int32_t DebuggerWasPresent @ 0x184a4
global void (*type_0x1093)() pcppinit @ 0x15104
global int32_t _newmode @ 0x18174
global int32_t mainret @ 0x18134
global void (*type_0x1093)() [4] __xc_z @ 0x15208
global int32_t [20] _RTC_ErrorLevels @ 0x18000
global int32_t (*type_0x1028)() (*type_0x1097)(int32_t (*type_0x1028)()) _imp___onexit @ 0x19248
global int32_t (*type_0x1028)() pcinit @ 0x15410
global const char *[20] _RTC_errlist @ 0x16034
global int32_t * _imp___commode @ 0x1927c
global uint32_t __security_cookie_complement @ 0x18028
global int32_t _fmode @ 0x18178
global struct _startupinfo startinfo @ 0x18150
global int32_t (*type_0x1141)(int32_t arg0, const char *arg1, int32_t arg2, const char *arg3, const char *arg4) _RTC_ErrorReportFunc @ 0x18160
global const char *[24] _RTC_ErrorMessages @ 0x1594c
global int32_t * _imp___fmode @ 0x19280
global void (*type_0x1093)() [4] __rtc_tzz @ 0x16df4
global void (**type_0x1093)() __onexitend @ 0x1855c
global int32_t [20] _RTC_ErrorLevels @ 0x18000
global void (*type_0x1093)() [4] __rtc_taa @ 0x16bec
global int32_t _commode @ 0x1816c
global int32_t __globallocalestatus @ 0x1801c
global void (*type_0x1093)() [4] __xi_z @ 0x1571c
global uint32_t __security_cookie @ 0x18024
global int32_t (*type_0x1450)(char *arg0, const char *arg1) wsprintffp @ 0x1815c
global int32_t * _imp___fmode @ 0x19280
global void (*type_0x1093)() [4] __rtc_izz @ 0x16ae8
global void (*type_0x1093)() [4] __xc_z @ 0x15208
global void (**type_0x1093)() __onexitbegin @ 0x1856c
global int32_t _fmode @ 0x18178
global void (*type_0x1093)() [4] __xc_a @ 0x15000
global int32_t * _imp___commode @ 0x1927c
global uint32_t __native_dllmain_reason @ 0x18020
global void (*type_0x1093)() [4] __rtc_iaa @ 0x168e0
global int32_t _newmode @ 0x18174
global int32_t _dowildcard @ 0x18170
global uint32_t __security_cookie_complement @ 0x18028
EOF
RUN
@@ -50,47 +109,69 @@ avgx __dyn_tls_init_callback
pdr @ fcn.140001316
EOF
EXPECT=<<EOF
global void * __guard_check_icall_fptr @ 0x140015000
global int32_t __favor @ 0x140011bc4
global void (*type_0x1079)(void *arg0) __castguard_check_failure_os_handled_fptr @ 0x140011ba8
global int32_t __scrt_debugger_hook_flag @ 0x140011ba4
global void (*type_0x1001)() [8] __rtc_iaa @ 0x14000ed88
global struct _RS5_IMAGE_LOAD_CONFIG_DIRECTORY64 _load_config_used @ 0x14000e2d0
global struct __type_info_node __type_info_root_node @ 0x140011b80
global void (*type_0x1001)() [8] __rtc_taa @ 0x14000f0b8
global void (*type_0x1de8)(void *arg0, uint32_t arg1, void *arg2) __dyn_tls_init_callback @ 0x140011be0
global void (*type_0x1001)() [24] std::runtime_error::`vftable' @ 0x14000d808
global void (*type_0x1001)() [8] __rtc_izz @ 0x14000efa8
global int32_t __scrt_current_native_startup_state @ 0x140011b28
global void * __guard_xfg_check_icall_fptr @ 0x140015010
global const unsigned char _guard_dispatch_icall_nop @ 0x140009a80
global void (*type_0x1001)() [8] __rtc_tzz @ 0x14000f2d8
global const int32_t __scrt_ucrt_dll_is_in_use @ 0x140011060
global void * __guard_dispatch_icall_fptr @ 0x140015020
global void * __guard_xfg_dispatch_icall_fptr @ 0x140015030
global int32_t (*type_0x1d02)(int32_t arg0, wchar_t *arg1, int32_t arg2, wchar_t *arg3, wchar_t *arg4) _RTC_ErrorReportFuncW @ 0x140011490
global int32_t __isa_available @ 0x140011038
global int32_t (*type_0x1015)() [8] __xi_a @ 0x14000c330
global void (*type_0x1001)() [8] __xc_z @ 0x14000c220
global int32_t [20] _RTC_ErrorLevels @ 0x140011018
global int32_t (*type_0x1015)() [8] __xi_z @ 0x14000c660
global unsigned char $xdatasym @ 0x14000ff40
global const unsigned char _guard_xfg_dispatch_icall_nop @ 0x140009aa0
global struct _EXCEPTION_POINTERS GS_ExceptionPointers @ 0x14000e060
global bool module_local_atexit_table_initialized @ 0x140011b39
global uint64_t __security_cookie @ 0x140011008
global void * __CastGuardVftablesEnd @ 0x14000e710
global void * __guard_dispatch_icall_fptr @ 0x140015020
global void (*type_0x1001)() [24] std::runtime_error::`vftable' @ 0x14000d808
global const int32_t __scrt_ucrt_dll_is_in_use @ 0x140011060
global void (*type_0x1001)() [24] std::exception::`vftable' @ 0x14000d530
global void (*type_0x1de8)(void *arg0, uint32_t arg1, void *arg2) __dyn_tls_dtor_callback @ 0x140011bc8
global void * __CastGuardVftablesStart @ 0x14000e600
global void (*type_0x1001)() [8] __xt_z @ 0x14000caa0
global int64_t __memset_nt_iters @ 0x140011048
global int32_t (*type_0x1015)() pre_c_initializer @ 0x14000c440
global void (*type_0x1001)() [8] __xp_z @ 0x14000c880
global const unsigned char _guard_xfg_dispatch_icall_nop @ 0x140009aa0
global void * __guard_xfg_table_dispatch_icall_fptr @ 0x140015040
global void (*type_0x1001)() [8] __xc_a @ 0x14000c000
global struct _onexit_table_t module_local_at_quick_exit_table @ 0x140011b58
global int32_t __isa_enabled @ 0x14001103c
global int32_t __scrt_default_matherr @ 0x140011034
global void (*type_0x1001)() [8] __xt_a @ 0x14000c990
global int64_t __memset_nt_iters @ 0x140011048
global struct HINSTANCE__ * mspdb @ 0x140011bb8
global void * __scrt_native_startup_lock @ 0x140011b30
global void (*type_0x1001)() [8] __xc_a @ 0x14000c000
global uint64_t __security_cookie_complement @ 0x140011000
global int64_t __memcpy_nt_iters @ 0x140011040
global void (*type_0x1001)() [8] __xp_a @ 0x14000c770
global void (*type_0x1001)() [8] __rtc_taa @ 0x14000f0b8
global const char [15] uninit_premsg @ 0x14000d8d0
global const char [43] uninit_postmsg @ 0x14000d8e0
global bool PDBOK @ 0x140011bc2
global int64_t __memcpy_nt_iters @ 0x140011040
global int32_t [20] _RTC_ErrorLevels @ 0x140011018
global void (*type_0x1001)() [8] __rtc_tzz @ 0x14000f2d8
global const char *[40] _RTC_errlist @ 0x14000df58
global void * __guard_xfg_dispatch_icall_fptr @ 0x140015030
global bool is_initialized_as_dll @ 0x140011b38
global void * __guard_xfg_table_dispatch_icall_fptr @ 0x140015040
global void (*type_0x1001)() [8] __rtc_iaa @ 0x14000ed88
global struct _onexit_table_t module_local_atexit_table @ 0x140011b40
global wchar_t [46] mspdbName @ 0x14000e078
global bool init @ 0x140011470
global void (*type_0x1001)() [8] __xt_z @ 0x14000caa0
global void (*type_0x1001)() pre_cpp_initializer @ 0x14000c110
global struct _RS5_IMAGE_LOAD_CONFIG_DIRECTORY64 _load_config_used @ 0x14000e2d0
global struct __type_info_node __type_info_root_node @ 0x140011b80
global void * __guard_check_icall_fptr @ 0x140015000
global void (*type_0x1001)() [8] __xc_z @ 0x14000c220
global bool alreadyTried @ 0x140011bc1
global void (*type_0x1001)() [8] __rtc_izz @ 0x14000efa8
global void (*type_0x1079)(void *arg0) __castguard_check_failure_os_handled_fptr @ 0x140011ba8
global struct _EXCEPTION_RECORD GS_ExceptionRecord @ 0x1400114a0
global int32_t (*type_0x1015)() [8] __xi_a @ 0x14000c330
global void (*type_0x1001)() [8] __xt_a @ 0x14000c990
global const unsigned char _guard_dispatch_icall_nop @ 0x140009a80
global int32_t __scrt_debugger_hook_flag @ 0x140011ba4
global int32_t (*type_0x1015)() [8] __xi_z @ 0x14000c660
global int32_t __scrt_current_native_startup_state @ 0x140011b28
global void (*type_0x1de8)(void *arg0, uint32_t arg1, void *arg2) __dyn_tls_init_callback @ 0x140011be0
global uint64_t _OptionsStorage @ 0x140011478
global wchar_t [8] dllExt @ 0x14000e240
global int32_t (*type_0x1d1a)(int32_t arg0, const char *arg1, int32_t arg2, const char *arg3, const char *arg4) _RTC_ErrorReportFunc @ 0x140011488
global int32_t (*type_0x1015)() post_pgo_initializer @ 0x14000c550
global void * __CastGuardVftablesStart @ 0x14000e600
global int32_t __favor @ 0x140011bc4
global void * __CastGuardVftablesEnd @ 0x14000e710
global uint64_t __security_cookie_complement @ 0x140011000
global void * __guard_xfg_check_icall_fptr @ 0x140015010
---
(nofunc) 0x140007344 [DATA] lea rcx, pdb.exceptions_test.__guard_check_icall_fptr
0x140007344 lea rcx, pdb.exceptions_test.__guard_check_icall_fptr ; 0x140015000
@@ -180,10 +261,10 @@ FILE==
CMDS=<<EOF
e bin.baddr=0
idp bins/pdb/Project1.pdb
fl~pdb:1
fl~__enc_textbss_end
e bin.baddr=0x800000
idp bins/pdb/Project1.pdb
fl~pdb:1
fl~__enc_textbss_end
EOF
EXPECT=<<EOF
0x00011000 0 pdb.Project1.__enc_textbss_end
+16
View File
@@ -1068,6 +1068,22 @@ EOF
EXPECT=<<EOF
{
"pdb": [
{
"modules": [
{
"module_name": "* Linker Generated Manifest RES *",
"object_file_name": ""
},
{
"module_name": "C:\\Users\\emuresan\\source\\repos\\minimal\\Release\\main.obj",
"object_file_name": "C:\\Users\\emuresan\\source\\repos\\minimal\\Release\\main.obj"
},
{
"module_name": "* Linker *",
"object_file_name": ""
}
]
},
{
"types": [
{
+10 -23
View File
@@ -21,6 +21,10 @@ bool pdb_info_save_types(RzAnalysis *analysis, const char *file) {
return true;
}
#define STREAMS_CHECK(x) \
mu_assert_notnull(pdb->streams, "NULL streams"); \
mu_assert_eq(rz_pvector_len(pdb->streams), (x), "Incorrect number of streams");
#define MEMBER_INIT_AND_CHECK_LEN(x) \
RzPVector *members = rz_bin_pdb_get_type_members(stream, type); \
mu_assert_notnull(members, "NULL members"); \
@@ -30,11 +34,7 @@ bool test_pdb_tpi_cpp(void) {
RzPdb *pdb = rz_bin_pdb_parse_from_file("bins/pdb/Project1.pdb");
mu_assert_notnull(pdb, "PDB parse failed.");
RzList *plist = pdb->streams;
mu_assert_notnull(plist, "PDB streams is NULL");
mu_assert_eq(pdb->streams->length, 50, "Incorrect number of streams");
STREAMS_CHECK(50);
RzPdbTpiStream *stream = pdb->s_tpi;
mu_assert_notnull(stream, "TPIs stream not found in current PDB");
@@ -42,13 +42,13 @@ bool test_pdb_tpi_cpp(void) {
mu_assert_eq(stream->header.TypeIndexBegin, 0x1000, "Wrong beginning index");
RBIter it;
RzPdbTpiType *type;
rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) {
mu_assert_notnull(type, "RzPdbTpiType is null in RBTree.");
if (type->index == 0x1028) {
mu_assert_eq(type->leaf, LF_PROCEDURE, "Incorrect data type");
Tpi_LF_Procedure *procedure = type->data;
RzPdbTpiType *arglist;
arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->arg_list);
arglist = rz_bin_pdb_get_type_by_index(stream, procedure->arg_list);
mu_assert_eq(arglist->index, 0x1027, "Wrong type index");
RzPdbTpiType *return_type;
return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->return_type);
@@ -195,11 +195,7 @@ bool test_pdb_tpi_rust(void) {
RzPdb *pdb = rz_bin_pdb_parse_from_file("bins/pdb/ghidra_rust_pdb_bug.pdb");
mu_assert_notnull(pdb, "PDB parse failed.");
RzList *plist = pdb->streams;
mu_assert_notnull(plist, "PDB streams is NULL");
mu_assert_eq(pdb->streams->length, 88, "Incorrect number of streams");
STREAMS_CHECK(88);
RzPdbTpiStream *stream = pdb->s_tpi;
mu_assert_notnull(stream, "TPIs stream not found in current PDB");
@@ -434,11 +430,7 @@ bool test_pdb_type_save(void) {
bool test_pdb_tpi_cpp_vs2019(void) {
RzPdb *pdb = rz_bin_pdb_parse_from_file("bins/pdb/vs2019_cpp_override.pdb");
mu_assert_notnull(pdb, "PDB parse failed.");
RzList *plist = pdb->streams;
mu_assert_notnull(plist, "PDB streams is NULL");
mu_assert_eq(pdb->streams->length, 75, "Incorrect number of streams");
STREAMS_CHECK(75);
RzPdbTpiStream *stream = pdb->s_tpi;
mu_assert_notnull(stream, "TPIs stream not found in current PDB");
@@ -673,11 +665,7 @@ bool test_pdb_tpi_cpp_vs2019(void) {
bool test_pdb_tpi_arm(void) {
RzPdb *pdb = rz_bin_pdb_parse_from_file("bins/pe/hello_world_arm/hello_world_arm_ZiZoO2.pdb");
mu_assert_notnull(pdb, "PDB parse failed.");
RzList *plist = pdb->streams;
mu_assert_notnull(plist, "PDB streams is NULL");
mu_assert_eq(pdb->streams->length, 399, "Incorrect number of streams");
STREAMS_CHECK(399);
RzPdbTpiStream *stream = pdb->s_tpi;
mu_assert_notnull(stream, "TPIs stream not found in current PDB");
@@ -685,7 +673,6 @@ bool test_pdb_tpi_arm(void) {
mu_assert_eq(stream->header.TypeIndexBegin, 0x1000, "Wrong beginning index");
RBIter it;
RzPdbTpiType *type;
rz_rbtree_foreach (stream->types, it, type, RzPdbTpiType, rb) {
if (type->index == 0x1A56) {
mu_assert_eq(type->leaf, LF_PROCEDURE, "Incorrect data type");