* Hide RzAnalysis structure to force the usage of the C APIs. * Fix rop code & test * Fix linter * Fix rz_analysis_free to return void
880 lines
40 KiB
C
880 lines
40 KiB
C
// SPDX-FileCopyrightText: 2020 HoundThe <cgkajm@gmail.com>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_util.h>
|
|
#include <rz_bin.h>
|
|
#include <rz_core.h>
|
|
#include <rz_pdb.h>
|
|
#include <rz_util/rz_path.h>
|
|
#include "test_types.h"
|
|
#include "../../librz/bin/pdb/pdb.h"
|
|
#include "../unit/minunit.h"
|
|
|
|
bool pdb_info_save_types(RzAnalysis *analysis, const char *file) {
|
|
RzPdb *pdb = rz_bin_pdb_parse_from_file(file);
|
|
if (!pdb) {
|
|
return false;
|
|
}
|
|
|
|
RzTypeDB *typedb = rz_analysis_get_type_db(analysis);
|
|
rz_type_db_pdb_load(typedb, pdb);
|
|
rz_bin_pdb_free(pdb);
|
|
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"); \
|
|
mu_assert_eq(rz_pvector_len(members), (x), "wrong union member count");
|
|
|
|
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.");
|
|
STREAMS_CHECK(50);
|
|
|
|
RzPdbTpiStream *stream = pdb->s_tpi;
|
|
mu_assert_notnull(stream, "TPIs stream not found in current PDB");
|
|
mu_assert_eq(stream->header.HeaderSize + stream->header.TypeRecordBytes, 117156, "Wrong TPI size");
|
|
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, 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);
|
|
mu_assert_eq(return_type->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = return_type->data;
|
|
mu_assert_eq(simple_type->size, 4, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type");
|
|
} else if (type->index == 0x1161) {
|
|
mu_assert_eq(type->leaf, LF_POINTER, "Incorrect data type");
|
|
} else if (type->index == 0x1004) {
|
|
mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type");
|
|
bool forward_ref = rz_bin_pdb_type_is_fwdref(type);
|
|
mu_assert_true(forward_ref, "Wrong fwdref");
|
|
} else if (type->index == 0x113F) {
|
|
mu_assert_eq(type->leaf, LF_ARRAY, "Incorrect data type");
|
|
RzPdbTpiType *dump;
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->index_type);
|
|
mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = dump->data;
|
|
mu_assert_eq(simple_type->size, 4, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "uint32_t", "Incorrect return type");
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->element_type);
|
|
mu_assert_eq(dump->index, 0x113E, "Wrong element type index");
|
|
ut64 size = rz_bin_pdb_get_type_val(type);
|
|
mu_assert_eq(size, 20, "Wrong array size");
|
|
} else if (type->index == 0x145A) {
|
|
mu_assert_eq(type->leaf, LF_ENUM, "Incorrect data type");
|
|
RzPdbTpiType *dump;
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "EXCEPTION_DEBUGGER_ENUM", "wrong enum name");
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->data))->utype);
|
|
mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = dump->data;
|
|
mu_assert_eq(simple_type->size, 4, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type");
|
|
MEMBER_INIT_AND_CHECK_LEN(6);
|
|
} else if (type->index == 0x1414) {
|
|
mu_assert_eq(type->leaf, LF_VTSHAPE, "Incorrect data type");
|
|
} else if (type->index == 0x1421) {
|
|
mu_assert_eq(type->leaf, LF_MODIFIER, "Incorrect data type");
|
|
RzPdbTpiType *stype = NULL;
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->data))->modified_type);
|
|
mu_assert_eq(stype->index, 0x120F, "Incorrect modified type");
|
|
} else if (type->index == 0x1003) {
|
|
mu_assert_eq(type->leaf, LF_UNION, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "R2_TEST_UNION", "wrong union name");
|
|
MEMBER_INIT_AND_CHECK_LEN(2);
|
|
} else if (type->index == 0x100B) {
|
|
mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "TEST_CLASS", "wrong class name");
|
|
MEMBER_INIT_AND_CHECK_LEN(2);
|
|
RzPdbTpiType *stype = NULL;
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape);
|
|
mu_assert_null(stype, "wrong class vshape");
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived);
|
|
mu_assert_null(stype, "wrong class derived");
|
|
} else if (type->index == 0x1258) {
|
|
mu_assert_eq(type->leaf, LF_METHODLIST, "Incorrect data type");
|
|
// Nothing from methodlist is currently being parsed
|
|
} else if (type->index == 0x107A) {
|
|
mu_assert_eq(type->leaf, LF_MFUNCTION, "Incorrect data type");
|
|
RzPdbTpiType *typ;
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->return_type);
|
|
mu_assert_eq(typ->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = typ->data;
|
|
mu_assert_eq(simple_type->size, 1, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "bool", "Incorrect return type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->class_type);
|
|
mu_assert_eq(typ->index, 0x1079, "incorrect mfunction class type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->arglist);
|
|
mu_assert_eq(typ->index, 0x1027, "incorrect mfunction arglist");
|
|
} else if (type->index == 0x113F) {
|
|
mu_assert_eq(type->leaf, LF_FIELDLIST, "Incorrect data type");
|
|
MEMBER_INIT_AND_CHECK_LEN(2725);
|
|
void **it;
|
|
int i = 0;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *t = *it;
|
|
mu_assert_eq(t->leaf, LF_ENUMERATE, "Incorrect data type");
|
|
if (i == 0) {
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(t);
|
|
mu_assert_streq(name, "CV_ALLREG_ERR", "Wrong enum name");
|
|
ut64 value = rz_bin_pdb_get_type_val(t);
|
|
|
|
mu_assert_eq(value, 30000, "Wrong enumerate value");
|
|
}
|
|
if (i == 2724) {
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(t);
|
|
mu_assert_streq(name, "CV_AMD64_YMM15D3", "Wrong enum name");
|
|
ut64 value = rz_bin_pdb_get_type_val(t);
|
|
|
|
mu_assert_eq(value, 687, "Wrong enumerate value");
|
|
}
|
|
i++;
|
|
}
|
|
} else if (type->index == 0x1231) {
|
|
mu_assert_eq(type->leaf, LF_ARGLIST, "Incorrect data type");
|
|
} else if (type->index == 0x101A) {
|
|
mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "threadlocaleinfostruct", "Wrong name");
|
|
bool forward_ref = rz_bin_pdb_type_is_fwdref(type);
|
|
mu_assert_false(forward_ref, "Wrong fwdref");
|
|
MEMBER_INIT_AND_CHECK_LEN(18);
|
|
int i = 0;
|
|
void **it;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *t = *it;
|
|
if (i == 0) {
|
|
mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(t);
|
|
mu_assert_streq(name, "refcount", "Wrong member name");
|
|
}
|
|
if (i == 1) {
|
|
mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(t);
|
|
mu_assert_streq(name, "lc_codepage", "Wrong member name");
|
|
}
|
|
if (i == 17) {
|
|
mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(t);
|
|
mu_assert_streq(name, "locale_name", "Wrong method name");
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
rz_bin_pdb_free(pdb);
|
|
mu_end;
|
|
}
|
|
|
|
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.");
|
|
STREAMS_CHECK(88);
|
|
|
|
RzPdbTpiStream *stream = pdb->s_tpi;
|
|
mu_assert_notnull(stream, "TPIs stream not found in current PDB");
|
|
mu_assert_eq(stream->header.HeaderSize + stream->header.TypeRecordBytes, 305632, "Wrong TPI size");
|
|
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 == 0x101B) {
|
|
mu_assert_eq(type->leaf, LF_PROCEDURE, "Incorrect data type");
|
|
RzPdbTpiType *arglist;
|
|
arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->arg_list);
|
|
mu_assert_eq(arglist->index, 0x101A, "Wrong type index");
|
|
RzPdbTpiType *return_type;
|
|
return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->return_type);
|
|
mu_assert_eq(return_type->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = return_type->data;
|
|
mu_assert_eq(simple_type->size, 4, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type");
|
|
} else if (type->index == 0x1163) {
|
|
mu_assert_eq(type->leaf, LF_POINTER, "Incorrect data type");
|
|
Tpi_LF_Pointer *pointer = type->data;
|
|
mu_assert_eq(pointer->utype, 0x1162, "Incorrect pointer type");
|
|
} else if (type->index == 0x1005) {
|
|
mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type");
|
|
bool forward_ref = rz_bin_pdb_type_is_fwdref(type);
|
|
mu_assert_true(forward_ref, "Wrong fwdref");
|
|
} else if (type->index == 0x114A) {
|
|
mu_assert_eq(type->leaf, LF_ARRAY, "Incorrect data type");
|
|
RzPdbTpiType *dump;
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->index_type);
|
|
mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = dump->data;
|
|
mu_assert_eq(simple_type->size, 8, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "uint64_t", "Incorrect return type");
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->element_type);
|
|
mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
simple_type = dump->data;
|
|
mu_assert_eq(simple_type->size, 1, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "unsigned char", "Incorrect return type");
|
|
|
|
ut64 size = rz_bin_pdb_get_type_val(type);
|
|
mu_assert_eq(size, 16, "Wrong array size");
|
|
} else if (type->index == 0x1FB4) {
|
|
mu_assert_eq(type->leaf, LF_ENUM, "Incorrect data type");
|
|
RzPdbTpiType *dump;
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "ISA_AVAILABILITY", "wrong enum name");
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->data))->utype);
|
|
mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = dump->data;
|
|
mu_assert_eq(simple_type->size, 4, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type");
|
|
MEMBER_INIT_AND_CHECK_LEN(10);
|
|
} else if (type->index == 0x1E31) {
|
|
mu_assert_eq(type->leaf, LF_VTSHAPE, "Incorrect data type");
|
|
} else if (type->index == 0x1FB7) {
|
|
mu_assert_eq(type->leaf, LF_MODIFIER, "Incorrect data type");
|
|
RzPdbTpiType *stype = NULL;
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->data))->modified_type);
|
|
mu_assert_eq(stype->leaf, LF_SIMPLE_TYPE, "Incorrect modified type");
|
|
} else if (type->index == 0x1EA9) {
|
|
mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "std::bad_typeid", "wrong class name");
|
|
RzPdbTpiType *stype = NULL;
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape);
|
|
mu_assert_notnull(stype, "wrong class vshape");
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived);
|
|
mu_assert_null(stype, "wrong class derived");
|
|
} else if (type->index == 0x1E27) {
|
|
mu_assert_eq(type->leaf, LF_METHODLIST, "Incorrect data type");
|
|
// Nothing from methodlist is currently being parsed
|
|
} else if (type->index == 0x181C) {
|
|
mu_assert_eq(type->leaf, LF_MFUNCTION, "Incorrect data type");
|
|
RzPdbTpiType *typ;
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->return_type);
|
|
mu_assert_eq(typ->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = typ->data;
|
|
mu_assert_eq(simple_type->size, 0, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "void", "Incorrect return type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->class_type);
|
|
mu_assert_eq(typ->index, 0x107F, "incorrect mfunction class type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->arglist);
|
|
mu_assert_eq(typ->index, 0x1000, "incorrect mfunction arglist");
|
|
} else if (type->index == 0x13BF) {
|
|
mu_assert_eq(type->leaf, LF_FIELDLIST, "Incorrect data type");
|
|
// check size
|
|
MEMBER_INIT_AND_CHECK_LEN(3);
|
|
void **it;
|
|
int i = 0;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *t = *it;
|
|
mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type");
|
|
if (i == 0) {
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(t);
|
|
mu_assert_streq(name, "RUST$ENUM$DISR", "Wrong member name");
|
|
}
|
|
if (i == 2) {
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(t);
|
|
mu_assert_streq(name, "__0", "Wrong member name");
|
|
}
|
|
i++;
|
|
}
|
|
} else if (type->index == 0x1164) {
|
|
mu_assert_eq(type->leaf, LF_ARGLIST, "Incorrect data type");
|
|
} else if (type->index == 0x1058) {
|
|
mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "std::thread::local::fast::Key<core::cell::Cell<core::option::Option<core::ptr::non_null::NonNull<core::task::wake::Context>>>>", "Wrong name");
|
|
|
|
bool forward_ref = rz_bin_pdb_type_is_fwdref(type);
|
|
mu_assert_false(forward_ref, "Wrong fwdref");
|
|
ut64 size = rz_bin_pdb_get_type_val(type);
|
|
|
|
mu_assert_eq(size, 24, "Wrong struct size");
|
|
|
|
MEMBER_INIT_AND_CHECK_LEN(2);
|
|
|
|
int i = 0;
|
|
void **it;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *t = *it;
|
|
if (i == 0) {
|
|
mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(t);
|
|
mu_assert_streq(name, "inner", "Wrong member name");
|
|
}
|
|
if (i == 1) {
|
|
mu_assert_eq(t->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(t);
|
|
mu_assert_streq(name, "dtor_state", "Wrong member name");
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
rz_bin_pdb_free(pdb);
|
|
mu_end;
|
|
}
|
|
|
|
bool test_pdb_type_save(void) {
|
|
RzAnalysis *analysis = rz_analysis_new(NULL);
|
|
RzTypeDB *typedb = rz_analysis_get_type_db(analysis);
|
|
const char *sdb_types_path = rz_analysis_get_sdb_types_path(analysis);
|
|
rz_type_db_init(typedb, sdb_types_path, "x86", 32, "windows");
|
|
|
|
mu_assert_true(pdb_info_save_types(analysis, "bins/pdb/Project1.pdb"), "pdb parsing failed");
|
|
|
|
// Check the enum presence and validity
|
|
RzBaseType *test_enum = rz_type_db_get_base_type(typedb, "R2_TEST_ENUM");
|
|
mu_assert_notnull(test_enum, "NULL type");
|
|
mu_assert_eq(test_enum->kind, RZ_BASE_TYPE_KIND_ENUM, "R2_TEST_ENUM is enum");
|
|
mu_assert_true(has_enum_val(test_enum, "eENUM1_R2", 0x10), "eNUM1_R2 = 0x10");
|
|
mu_assert_true(has_enum_val(test_enum, "eENUM2_R2", 0x20), "eNUM2_R2 = 0x20");
|
|
mu_assert_true(has_enum_val(test_enum, "eENUM_R2_MAX", 0x21), "eNUM2_R2 = 0x21");
|
|
|
|
mu_assert_false(has_enum_case(test_enum, "no_case"), "no such enum case");
|
|
|
|
// Check the union presence and validity
|
|
RzBaseType *test_union = rz_type_db_get_base_type(typedb, "R2_TEST_UNION");
|
|
mu_assert_notnull(test_union, "NULL type");
|
|
mu_assert_eq(test_union->kind, RZ_BASE_TYPE_KIND_UNION, "R2_TEST_UNION is union");
|
|
mu_assert_true(has_union_member(test_union, "r2_union_var_1"), "r2_union_var_1");
|
|
mu_assert_true(has_union_member(test_union, "r2_union_var_2"), "r2_union_var_2");
|
|
// Test member types also
|
|
mu_assert_true(has_union_member_type(typedb, test_union, "r2_union_var_1", "int32_t"), "r2_union_var_1 type");
|
|
mu_assert_true(has_union_member_type(typedb, test_union, "r2_union_var_2", "double"), "rz_union_var_2 type");
|
|
mu_assert_false(has_union_member(test_union, "noSuchMember"), "no such struct member");
|
|
|
|
RzBaseType *m64_union = rz_type_db_get_base_type(typedb, "__m64");
|
|
mu_assert_notnull(m64_union, "NULL type");
|
|
mu_assert_eq(m64_union->kind, RZ_BASE_TYPE_KIND_UNION, "__m64 is union");
|
|
mu_assert_true(has_union_member(m64_union, "m64_f32"), "m64_f32");
|
|
mu_assert_true(has_union_member(m64_union, "m64_i8"), "m64_i8");
|
|
mu_assert_true(has_union_member(m64_union, "m64_i16"), "m64_i16");
|
|
mu_assert_true(has_union_member(m64_union, "m64_i32"), "m64_i32");
|
|
mu_assert_true(has_union_member(m64_union, "m64_i64"), "m64_i64");
|
|
mu_assert_true(has_union_member(m64_union, "m64_u8"), "m64_u8");
|
|
mu_assert_true(has_union_member(m64_union, "m64_u16"), "m64_u16");
|
|
mu_assert_true(has_union_member(m64_union, "m64_u32"), "m64_u32");
|
|
mu_assert_true(has_union_member(m64_union, "m64_u64"), "m64_u64");
|
|
// Test member types also
|
|
mu_assert_true(has_union_member_type(typedb, m64_union, "m64_u64", "uint64_t"), "m64_u64 type");
|
|
mu_assert_true(has_union_member_type(typedb, m64_union, "m64_f32", "float [8]"), "m64_f32 type");
|
|
mu_assert_true(has_union_member_type(typedb, m64_union, "m64_i8", "char [8]"), "m64_i8 type");
|
|
mu_assert_true(has_union_member_type(typedb, m64_union, "m64_i32", "int32_t [8]"), "m64_i32 type");
|
|
mu_assert_true(has_union_member_type(typedb, m64_union, "m64_i16", "int16_t [8]"), "m64_i16 type");
|
|
mu_assert_true(has_union_member_type(typedb, m64_union, "m64_i64", "int64_t"), "m64_i64 type");
|
|
mu_assert_true(has_union_member_type(typedb, m64_union, "m64_u8", "unsigned char [8]"), "m64_u8 type");
|
|
mu_assert_true(has_union_member_type(typedb, m64_union, "m64_u16", "uint16_t [8]"), "m64_u16 type");
|
|
mu_assert_true(has_union_member_type(typedb, m64_union, "m64_u32", "uint32_t [8]"), "m64_u32 type");
|
|
|
|
mu_assert_false(has_union_member(m64_union, "noSuchMember"), "no such union member");
|
|
// We dont handle class integration for now, so disable the following unit test.
|
|
// Check the structure presence and validity
|
|
// RzBaseType *test_class = rz_type_db_get_base_type(typedb, "TEST_CLASS");
|
|
// mu_assert_eq(test_class->kind, RZ_BASE_TYPE_KIND_STRUCT, "TEST_CLASS is struct");
|
|
// mu_assert_true(has_struct_member(test_class, "class_var1"), "class_var1");
|
|
// mu_assert_true(has_struct_member(test_class, "calss_var2"), "calss_var2");
|
|
// TODO: test member types also
|
|
// check_kv("struct.TEST_CLASS.class_var1", "int32_t,0,0");
|
|
// check_kv("struct.TEST_CLASS.calss_var2", "uint16_t,4,0");
|
|
|
|
// mu_assert_false(has_struct_member(test_class, "noSuchMember"), "no such struct member");
|
|
// Check the structure presence and validity
|
|
|
|
// Forward defined structure
|
|
RzBaseType *localeinfo = rz_type_db_get_base_type(typedb, "localeinfo_struct");
|
|
mu_assert_notnull(localeinfo, "NULL type");
|
|
mu_assert_eq(localeinfo->kind, RZ_BASE_TYPE_KIND_STRUCT, "localeinfo_struct is struct");
|
|
mu_assert_true(has_struct_member(localeinfo, "locinfo"), "locinfo");
|
|
mu_assert_true(has_struct_member(localeinfo, "mbcinfo"), "mbcinfo");
|
|
// Test member types also
|
|
mu_assert_true(has_struct_member_type(typedb, localeinfo, "locinfo", "struct threadlocaleinfostruct *"), "locinfo type");
|
|
mu_assert_true(has_struct_member_type(typedb, localeinfo, "mbcinfo", "struct threadmbcinfostruct *"), "mbcinfo type");
|
|
|
|
mu_assert_false(has_struct_member(localeinfo, "noSuchMember"), "no such struct member");
|
|
|
|
rz_analysis_free(analysis);
|
|
mu_end;
|
|
}
|
|
|
|
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.");
|
|
STREAMS_CHECK(75);
|
|
|
|
RzPdbTpiStream *stream = pdb->s_tpi;
|
|
mu_assert_notnull(stream, "TPIs stream not found in current PDB");
|
|
mu_assert_eq(stream->header.HeaderSize + stream->header.TypeRecordBytes, 233588, "Wrong TPI size");
|
|
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 == 0x1A5F) {
|
|
mu_assert_eq(type->leaf, LF_PROCEDURE, "Incorrect data type");
|
|
RzPdbTpiType *arglist;
|
|
arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->arg_list);
|
|
mu_assert_eq(arglist->index, 0x1A5E, "Wrong type index");
|
|
RzPdbTpiType *return_type;
|
|
return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->return_type);
|
|
mu_assert_eq(return_type->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = return_type->data;
|
|
mu_assert_eq(simple_type->size, 0, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "void", "Incorrect return type");
|
|
} else if (type->index == 0x1A64) {
|
|
mu_assert_eq(type->leaf, LF_POINTER, "Incorrect data type");
|
|
Tpi_LF_Pointer *pointer = type->data;
|
|
mu_assert_eq(pointer->utype, 0x1A63, "Incorrect pointer type");
|
|
} else if (type->index == 0x1ACD) {
|
|
mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type");
|
|
bool forward_ref = rz_bin_pdb_type_is_fwdref(type);
|
|
mu_assert_false(forward_ref, "Wrong fwdref");
|
|
} else if (type->index == 0x1B3C) {
|
|
mu_assert_eq(type->leaf, LF_ARRAY, "Incorrect data type");
|
|
RzPdbTpiType *dump;
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->index_type);
|
|
mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = dump->data;
|
|
mu_assert_eq(simple_type->size, 4, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "uint32_t", "Incorrect return type");
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->element_type);
|
|
mu_assert_eq(dump->index, 0x7A, "Wrong element type index");
|
|
ut64 size = rz_bin_pdb_get_type_val(type);
|
|
mu_assert_eq(size, 16, "Wrong array size");
|
|
} else if (type->index == 0x20D6) {
|
|
mu_assert_eq(type->leaf, LF_ENUM, "Incorrect data type");
|
|
RzPdbTpiType *dump;
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "ReplacesCorHdrNumericDefines", "wrong enum name");
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->data))->utype);
|
|
mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = dump->data;
|
|
mu_assert_eq(simple_type->size, 4, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type");
|
|
MEMBER_INIT_AND_CHECK_LEN(25);
|
|
} else if (type->index == 0x1A5A) {
|
|
mu_assert_eq(type->leaf, LF_VTSHAPE, "Incorrect data type");
|
|
} else if (type->index == 0x2163) {
|
|
mu_assert_eq(type->leaf, LF_MODIFIER, "Incorrect data type");
|
|
RzPdbTpiType *stype = NULL;
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->data))->modified_type);
|
|
mu_assert_eq(stype->index, 0x22, "Incorrect modified type");
|
|
} else if (type->leaf == 0x2151) {
|
|
mu_assert_eq(type->leaf, LF_UNION, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "__m64", "wrong union name");
|
|
MEMBER_INIT_AND_CHECK_LEN(9);
|
|
} else if (type->index == 0x239B) {
|
|
mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "CTest1", "wrong class name");
|
|
MEMBER_INIT_AND_CHECK_LEN(5);
|
|
RzPdbTpiType *stype = NULL;
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape);
|
|
mu_assert_notnull(stype, "wrong class vshape");
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived);
|
|
mu_assert_null(stype, "wrong class derived");
|
|
} else if (type->index == 0x23DC) {
|
|
mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "CTest2", "wrong class name");
|
|
MEMBER_INIT_AND_CHECK_LEN(4);
|
|
int i = 0;
|
|
void **it;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *stype = *it;
|
|
if (i == 0) {
|
|
mu_assert_eq(stype->leaf, LF_BCLASS, "Incorrect data type");
|
|
} else if (i == 1) {
|
|
mu_assert_eq(stype->leaf, LF_ONEMETHOD, "Incorrect data type");
|
|
name = rz_bin_pdb_get_type_name(stype);
|
|
mu_assert_streq(name, "Bar", "wrong member name");
|
|
} else if (i == 2) {
|
|
mu_assert_eq(stype->leaf, LF_METHOD, "Incorrect data type");
|
|
name = rz_bin_pdb_get_type_name(stype);
|
|
mu_assert_streq(name, "CTest2", "wrong member name");
|
|
}
|
|
i++;
|
|
}
|
|
RzPdbTpiType *stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape);
|
|
mu_assert_eq(stype->index, 0x11E8, "wrong class vshape");
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived);
|
|
mu_assert_null(stype, "wrong class derived");
|
|
} else if (type->index == 0x2299) {
|
|
mu_assert_eq(type->leaf, LF_CLASS_19, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "type_info", "wrong class name");
|
|
MEMBER_INIT_AND_CHECK_LEN(12);
|
|
RzPdbTpiType *stype = NULL;
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape);
|
|
mu_assert_notnull(stype, "wrong class vshape");
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived);
|
|
mu_assert_null(stype, "wrong class derived");
|
|
} else if (type->index == 0x2147) {
|
|
mu_assert_eq(type->leaf, LF_BITFIELD, "Incorrect data type");
|
|
RzPdbTpiType *base_type = NULL;
|
|
base_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Bitfield *)(type->data))->base_type);
|
|
mu_assert_notnull(base_type, "Bitfield base type is NULL");
|
|
} else if (type->index == 0x2209) {
|
|
mu_assert_eq(type->leaf, LF_METHODLIST, "Incorrect data type");
|
|
// Nothing from methodlist is currently being parsed
|
|
} else if (type->index == 0x224F) {
|
|
mu_assert_eq(type->leaf, LF_MFUNCTION, "Incorrect data type");
|
|
RzPdbTpiType *typ;
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->return_type);
|
|
mu_assert_eq(typ->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = typ->data;
|
|
mu_assert_eq(simple_type->size, 0, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "void", "Incorrect return type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->class_type);
|
|
mu_assert_eq(typ->index, 0x2247, "incorrect mfunction class type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->this_type);
|
|
mu_assert_eq(typ->index, 0x2248, "incorrect mfunction this type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->arglist);
|
|
mu_assert_eq(typ->index, 0x224E, "incorrect mfunction arglist");
|
|
} else if (type->index == 0x239A) {
|
|
mu_assert_eq(type->leaf, LF_FIELDLIST, "Incorrect data type");
|
|
MEMBER_INIT_AND_CHECK_LEN(5);
|
|
int i = 0;
|
|
void **it;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *type_info = *it;
|
|
if (i == 1) {
|
|
mu_assert_eq(type_info->leaf, LF_ONEMETHOD, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_info);
|
|
mu_assert_streq(name, "Foo", "Wrong enum name");
|
|
}
|
|
if (i == 3) {
|
|
mu_assert_eq(type_info->leaf, LF_METHOD, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_info);
|
|
mu_assert_streq(name, "CTest1", "Wrong enum name");
|
|
}
|
|
i++;
|
|
}
|
|
} else if (type->index == 0x2392) {
|
|
mu_assert_eq(type->leaf, LF_ARGLIST, "Incorrect data type");
|
|
} else if (type->index == 0x208F) {
|
|
mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "_s__RTTICompleteObjectLocator", "Wrong name");
|
|
bool forward_ref = rz_bin_pdb_type_is_fwdref(type);
|
|
mu_assert_false(forward_ref, "Wrong fwdref");
|
|
|
|
MEMBER_INIT_AND_CHECK_LEN(5)
|
|
int i = 0;
|
|
void **it;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *type_structure = *it;
|
|
if (i == 0) {
|
|
mu_assert_eq(type_structure->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_structure);
|
|
mu_assert_streq(name, "signature", "Wrong member name");
|
|
}
|
|
if (i == 1) {
|
|
mu_assert_eq(type_structure->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_structure);
|
|
mu_assert_streq(name, "offset", "Wrong member name");
|
|
}
|
|
if (i == 4) {
|
|
mu_assert_eq(type_structure->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_structure);
|
|
mu_assert_streq(name, "pClassDescriptor", "Wrong method name");
|
|
}
|
|
i++;
|
|
}
|
|
} else if (type->index == 0x2184) {
|
|
mu_assert_eq(type->leaf, LF_STRUCTURE_19, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "_RS5_IMAGE_LOAD_CONFIG_DIRECTORY32", "Wrong name");
|
|
bool forward_ref;
|
|
forward_ref = rz_bin_pdb_type_is_fwdref(type);
|
|
mu_assert_false(forward_ref, "Wrong fwdref");
|
|
MEMBER_INIT_AND_CHECK_LEN(48);
|
|
int i = 0;
|
|
void **it;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *type_structure_19 = *it;
|
|
if (i == 0) {
|
|
mu_assert_eq(type_structure_19->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_structure_19);
|
|
mu_assert_streq(name, "Size", "Wrong member name");
|
|
}
|
|
if (i == 1) {
|
|
mu_assert_eq(type_structure_19->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_structure_19);
|
|
mu_assert_streq(name, "TimeDateStamp", "Wrong member name");
|
|
}
|
|
if (i == 17) {
|
|
mu_assert_eq(type_structure_19->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_structure_19);
|
|
mu_assert_streq(name, "SecurityCookie", "Wrong method name");
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
rz_bin_pdb_free(pdb);
|
|
mu_end;
|
|
}
|
|
|
|
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.");
|
|
STREAMS_CHECK(399);
|
|
|
|
RzPdbTpiStream *stream = pdb->s_tpi;
|
|
mu_assert_notnull(stream, "TPIs stream not found in current PDB");
|
|
mu_assert_eq(stream->header.HeaderSize + stream->header.TypeRecordBytes, 454428, "Wrong TPI size");
|
|
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");
|
|
RzPdbTpiType *arglist;
|
|
arglist = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->arg_list);
|
|
mu_assert_eq(arglist->index, 0x1A54, "Wrong type index");
|
|
RzPdbTpiType *return_type;
|
|
return_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Procedure *)(type->data))->return_type);
|
|
mu_assert_eq(return_type->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = return_type->data;
|
|
mu_assert_eq(simple_type->size, 0, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "void", "Incorrect return type");
|
|
} else if (type->index == 0x1A5B) {
|
|
mu_assert_eq(type->leaf, LF_POINTER, "Incorrect data type");
|
|
Tpi_LF_Pointer *pointer = type->data;
|
|
mu_assert_eq(pointer->utype, 0x1A4C, "Incorrect pointer type");
|
|
} else if (type->index == 0x1A2B) {
|
|
mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type");
|
|
bool forward_ref = rz_bin_pdb_type_is_fwdref(type);
|
|
mu_assert_false(forward_ref, "Wrong fwdref");
|
|
} else if (type->index == 0x1B2B) {
|
|
mu_assert_eq(type->leaf, LF_ARRAY, "Incorrect data type");
|
|
RzPdbTpiType *dump;
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->index_type);
|
|
mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = dump->data;
|
|
mu_assert_eq(simple_type->size, 4, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "uint32_t", "Incorrect return type");
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Array *)(type->data))->element_type);
|
|
mu_assert_eq(dump->index, 0x1242, "Wrong element type index");
|
|
ut64 size = rz_bin_pdb_get_type_val(type);
|
|
mu_assert_eq(size, 16, "Wrong array size");
|
|
} else if (type->index == 0x1B9C) {
|
|
mu_assert_eq(type->leaf, LF_ENUM, "Incorrect data type");
|
|
RzPdbTpiType *dump;
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "__crt_lowio_text_mode", "wrong enum name");
|
|
dump = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Enum *)(type->data))->utype);
|
|
mu_assert_eq(dump->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = dump->data;
|
|
mu_assert_eq(simple_type->size, 1, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "char", "Incorrect return type");
|
|
MEMBER_INIT_AND_CHECK_LEN(3)
|
|
} else if (type->index == 0x1126) {
|
|
mu_assert_eq(type->leaf, LF_VTSHAPE, "Incorrect data type");
|
|
} else if (type->index == 0x113C) {
|
|
mu_assert_eq(type->leaf, LF_MODIFIER, "Incorrect data type");
|
|
RzPdbTpiType *stype = NULL;
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Modifier *)(type->data))->modified_type);
|
|
mu_assert_eq(stype->index, 0x112D, "Incorrect modified type");
|
|
} else if (type->leaf == 0x2151) {
|
|
mu_assert_eq(type->leaf, LF_UNION, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "_IMAGE_SECTION_HEADER::<unnamed-type-Misc>", "wrong union name");
|
|
MEMBER_INIT_AND_CHECK_LEN(2)
|
|
} else if (type->index == 0x121D) {
|
|
mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "std::bad_alloc", "wrong class name");
|
|
MEMBER_INIT_AND_CHECK_LEN(6)
|
|
RzPdbTpiType *stype = NULL;
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape);
|
|
mu_assert_notnull(stype, "wrong class vshape");
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived);
|
|
mu_assert_null(stype, "wrong class derived");
|
|
} else if (type->index == 0x150A) {
|
|
mu_assert_eq(type->leaf, LF_CLASS, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "FH4::TryBlockMap4::iterator", "wrong class name");
|
|
MEMBER_INIT_AND_CHECK_LEN(9)
|
|
int i = 0;
|
|
void **it;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *stype = *it;
|
|
if (i == 0) {
|
|
mu_assert_eq(stype->leaf, LF_ONEMETHOD, "Incorrect data type");
|
|
name = rz_bin_pdb_get_type_name(stype);
|
|
mu_assert_notnull(name, "name is null");
|
|
mu_assert_streq(name, "iterator", "wrong member name");
|
|
} else if (i == 1) {
|
|
mu_assert_eq(stype->leaf, LF_ONEMETHOD, "Incorrect data type");
|
|
name = rz_bin_pdb_get_type_name(stype);
|
|
mu_assert_notnull(name, "name is null");
|
|
mu_assert_streq(name, "operator++", "wrong member name");
|
|
} else if (i == 8) {
|
|
mu_assert_eq(stype->leaf, LF_MEMBER, "Incorrect data type");
|
|
name = rz_bin_pdb_get_type_name(stype);
|
|
mu_assert_notnull(name, "name is null");
|
|
mu_assert_streq(name, "_currBlock", "wrong member name");
|
|
}
|
|
i++;
|
|
}
|
|
RzPdbTpiType *stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->vshape);
|
|
mu_assert_null(stype, "vtshape is not null");
|
|
stype = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Class *)(type->data))->derived);
|
|
mu_assert_null(stype, "wrong class derived");
|
|
} else if (type->index == 0x1638) {
|
|
mu_assert_eq(type->leaf, LF_BITFIELD, "Incorrect data type");
|
|
RzPdbTpiType *base_type = NULL;
|
|
base_type = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_Bitfield *)(type->data))->base_type);
|
|
mu_assert_notnull(base_type, "Bitfield base type is NULL");
|
|
} else if (type->index == 0x167F) {
|
|
mu_assert_eq(type->leaf, LF_METHODLIST, "Incorrect data type");
|
|
} else if (type->index == 0x168C) {
|
|
mu_assert_eq(type->leaf, LF_MFUNCTION, "Incorrect data type");
|
|
RzPdbTpiType *typ;
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->return_type);
|
|
mu_assert_eq(typ->leaf, LF_SIMPLE_TYPE, "Incorrect return type");
|
|
Tpi_LF_SimpleType *simple_type = typ->data;
|
|
mu_assert_eq(simple_type->size, 4, "Incorrect return type");
|
|
mu_assert_streq(simple_type->type, "int32_t", "Incorrect return type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->class_type);
|
|
mu_assert_eq(typ->index, 0x165B, "incorrect mfunction class type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->this_type);
|
|
mu_assert_null(typ, "incorrect mfunction this type");
|
|
typ = rz_bin_pdb_get_type_by_index(stream, ((Tpi_LF_MFcuntion *)(type->data))->arglist);
|
|
mu_assert_eq(typ->index, 0x168A, "incorrect mfunction arglist");
|
|
} else if (type->index == 0x16A1) {
|
|
mu_assert_eq(type->leaf, LF_FIELDLIST, "Incorrect data type");
|
|
MEMBER_INIT_AND_CHECK_LEN(100);
|
|
|
|
int i = 0;
|
|
void **it;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *type_info = *it;
|
|
if (i == 3) {
|
|
mu_assert_eq(type_info->leaf, LF_MEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_info);
|
|
mu_assert_streq(name, "ZNameList", "Wrong enum name");
|
|
}
|
|
if (i == 11) {
|
|
mu_assert_eq(type_info->leaf, LF_ONEMETHOD, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_info);
|
|
mu_assert_streq(name, "getDecoratedName", "Wrong enum name");
|
|
}
|
|
i++;
|
|
}
|
|
} else if (type->index == 0x16A7) {
|
|
mu_assert_eq(type->leaf, LF_ARGLIST, "Incorrect data type");
|
|
} else if (type->index == 0x16E6) {
|
|
mu_assert_eq(type->leaf, LF_STRUCTURE, "Incorrect data type");
|
|
char *name;
|
|
name = rz_bin_pdb_get_type_name(type);
|
|
mu_assert_streq(name, "std::_Num_base", "Wrong name");
|
|
bool forward_ref = rz_bin_pdb_type_is_fwdref(type);
|
|
mu_assert_false(forward_ref, "Wrong fwdref");
|
|
MEMBER_INIT_AND_CHECK_LEN(23)
|
|
int i = 0;
|
|
void **it;
|
|
rz_pvector_foreach (members, it) {
|
|
RzPdbTpiType *type_structure = *it;
|
|
if (i == 0) {
|
|
mu_assert_eq(type_structure->leaf, LF_STMEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_structure);
|
|
mu_assert_streq(name, "has_denorm", "Wrong member name");
|
|
}
|
|
if (i == 6) {
|
|
mu_assert_eq(type_structure->leaf, LF_STMEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_structure);
|
|
mu_assert_streq(name, "is_exact", "Wrong member name");
|
|
}
|
|
if (i == 13) {
|
|
mu_assert_eq(type_structure->leaf, LF_STMEMBER, "Incorrect data type");
|
|
char *name = NULL;
|
|
name = rz_bin_pdb_get_type_name(type_structure);
|
|
mu_assert_streq(name, "traps", "Wrong method name");
|
|
}
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
rz_bin_pdb_free(pdb);
|
|
mu_end;
|
|
}
|
|
|
|
int test_tpi_type_node_cmp(const void *incoming, const RBNode *in_tree, void *user) {
|
|
ut64 ia = *(ut64 *)incoming;
|
|
ut64 ta = container_of(in_tree, const RzPdbTpiType, rb)->index;
|
|
if (ia < ta) {
|
|
return -1;
|
|
} else if (ia > ta) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool all_tests() {
|
|
mu_run_test(test_pdb_tpi_cpp);
|
|
mu_run_test(test_pdb_tpi_rust);
|
|
mu_run_test(test_pdb_type_save);
|
|
mu_run_test(test_pdb_tpi_cpp_vs2019);
|
|
mu_run_test(test_pdb_tpi_arm);
|
|
return tests_passed != tests_run;
|
|
}
|
|
|
|
mu_main(all_tests)
|