Files
sigmaker-ida/idasdk76/plugins/pdb/tilbuild.hpp
2021-10-31 21:20:46 +02:00

217 lines
7.3 KiB
C++

#pragma once
//----------------------------------------------------------------------------
enum cvt_code_t
{
cvt_failed,
cvt_ok,
cvt_typedef // conversion resulted in a typedef to a named type
};
//----------------------------------------------------------------------------
// PBD provides the offset of a bitfield inside a bitfield group.
// We subclass udt_member_t in order to keep that information separate from
// the 'offset' field.
struct pdb_udt_member_t : public udt_member_t
{
uint32 bit_offset; ///< member offset in bits from start of bitfield group
};
DECLARE_TYPE_AS_MOVABLE(pdb_udt_member_t);
typedef qvector<pdb_udt_member_t> pdbudtmembervec_t; ///< vector of pdb udt member objects
//----------------------------------------------------------------------------
// stripped-down version of udt_type_data_t with only the fields used by pdb.
struct pdb_udt_type_data_t : public pdbudtmembervec_t
{
size_t total_size; ///< total structure size in bytes
uint32 taudt_bits; ///< TA... and TAUDT... bits
bool is_union; ///< is union or struct?
pdb_udt_type_data_t(void)
: total_size(0),
taudt_bits(0),
is_union(false)
{
}
void convert_to_tinfo_udt(udt_type_data_t *out);
};
DECLARE_TYPE_AS_MOVABLE(pdb_udt_type_data_t);
//----------------------------------------------------------------------------
class til_builder_t
{
protected:
pdb_ctx_t &pv;
public:
//----------------------------------------------------------------------------
struct tpinfo_t
{
cvt_code_t cvt_code;
bool is_notype;
tinfo_t type;
til_t *ti; // FIXME: do we need this?
tpinfo_t(void) : cvt_code(cvt_ok), is_notype(false), ti(NULL) {}
tpinfo_t(til_t *_ti, const tinfo_t &t) : cvt_code(cvt_ok), is_notype(false), type(t), ti(_ti) {}
const char *dstr(void) const
{
if ( cvt_code == cvt_failed )
return "#cvt_failed";
static qstring res;
if ( !type.print(&res) )
res = "#print_failed";
return res.c_str();
}
};
//----------------------------------------------------------------------------
til_builder_t(pdb_ctx_t &_pv, til_t *_ti, pdb_access_t *_pa)
: pv(_pv),
unnamed_idx(0),
level(0),
ti(_ti),
pdb_access(NULL),
enregistered_bug(false)
{
set_pdb_access(_pa);
}
virtual ~til_builder_t()
{
typemap.clear();
tpdefs.clear();
handled.clear();
creating.clear();
unnamed_types.clear();
}
void set_pdb_access(pdb_access_t *_pdb_access)
{
pdb_access = _pdb_access;
}
typedef std::map<DWORD, tpinfo_t> typemap_t;
typedef std::map<DWORD, tinfo_t> tpdefs_t;
typedef std::set<DWORD> idset_t;
typedef std::map<qstring, int> creating_t;
typedef std::set<uint32> unnamed_t;
struct vft_info_t
{
udt_type_data_t udt; // collected vft members
qstring base0; // base vftable at offset 0
vft_info_t() { udt.taudt_bits |= TAUDT_VFTABLE; }
bool empty() const { return udt.empty() && base0.empty(); }
};
typedef std::map<qstring, vft_info_t> vftmap_t;
// remove `anonymous-namespace'::
// also remove `anonymous namespace'::
void remove_anonymous_namespaces(qstring &storage);
bool get_symbol_type(tpinfo_t *out, pdb_sym_t &sym, int *p_id);
bool retrieve_type(tpinfo_t *out, pdb_sym_t &sym, pdb_sym_t *parent, int *p_id);
bool retrieve_arguments(
pdb_sym_t &sym,
func_type_data_t &fi,
pdb_sym_t *funcSym);
cm_t convert_cc(DWORD cc0) const;
bool get_variant_string_value(qstring *out, pdb_sym_t &sym) const;
uint32 get_variant_long_value(pdb_sym_t &sym) const;
bool begin_creation(DWORD tag, const qstring &name, uint32 *p_id);
uint32 end_creation(const qstring &name);
bool is_member_func(tinfo_t *class_type, pdb_sym_t &typeSym, pdb_sym_t *funcSym);
bool is_frame_reg(int regnum) const;
bool is_complex_return(pdb_sym_t &sym) const;
bool is_unnamed_tag_typedef(const tinfo_t &tif) const;
bool is_intel386(DWORD machine_type) const;
bool is_arm(DWORD machine_type) const;
int get_symbol_funcarg_info(
funcarg_t *out,
pdb_sym_t &sym,
DWORD /*dwDataKind*/,
DWORD locType,
int stack_off);
void enum_function_args(pdb_sym_t &sym, func_type_data_t &args);
cvt_code_t verify_struct(pdb_udt_type_data_t &udt) const;
cvt_code_t verify_union(
pdb_udt_type_data_t *out,
pdb_udt_type_data_t::iterator p1,
pdb_udt_type_data_t::const_iterator p2) const;
cvt_code_t create_union(
tinfo_t *out,
size_t *p_total_size,
pdb_udt_type_data_t::iterator p1,
pdb_udt_type_data_t::const_iterator p2) const;
cvt_code_t convert_basetype(tpinfo_t *out, DWORD baseType, int size) const;
cvt_code_t make_vtable_struct(tinfo_t *out, pdb_sym_t &sym);
cvt_code_t convert_udt(tinfo_t *out, pdb_sym_t &sym, DWORD64 size);
cvt_code_t create_udt(tinfo_t *out, pdb_udt_type_data_t *udt, int udtKind, const char *udt_name) const;
cvt_code_t create_udt_ref(tinfo_t *out, pdb_udt_type_data_t *udt, int udt_kind) const;
cvt_code_t really_convert_type(tpinfo_t *out, pdb_sym_t &sym, pdb_sym_t *parent, DWORD tag);
cvt_code_t convert_type(
tpinfo_t *out,
pdb_sym_t &sym,
pdb_sym_t *parent,
DWORD type,
DWORD tag);
cvt_code_t handle_overlapping_members(pdb_udt_type_data_t *udt) const;
// Will iterate on children, and call handle_function_child()
HRESULT handle_symbols(pdb_sym_t &pGlobal);
HRESULT handle_globals(pdb_sym_t &pGlobal);
HRESULT handle_publics(pdb_sym_t &pGlobal);
HRESULT handle_types(pdb_sym_t &pGlobal);
HRESULT build(pdb_sym_t &pGlobal);
ea_t get_load_address() const { return pdb_access->get_base_address(); }
HRESULT handle_symbol(pdb_sym_t &sym);
size_t get_symbol_type_length(pdb_sym_t &sym) const;
void create_vftables();
// check for MS or IDA vftable name,
// get type ordinal of vftable
// returns the type is creating
bool get_vft_name(qstring *vft_name, uint32 *ord, const char *udt_name, uint32_t offset=0);
virtual HRESULT before_iterating(pdb_sym_t &global_sym);
virtual HRESULT after_iterating(pdb_sym_t &global_sym);
virtual bool iterate_symbols_once_more(pdb_sym_t & /*global_sym*/) { return false; }
virtual bool get_symbol_name(pdb_sym_t &sym, qstring &storage);
virtual bool handle_symbol_at_ea(
pdb_sym_t &sym,
DWORD tag,
ea_t ea,
qstring &name);
virtual void type_created(ea_t /*ea*/, int /*id*/, const char * /*name*/, const tinfo_t & /*ptr*/) const;
virtual void handle_function_type(pdb_sym_t &fun_sym, ea_t ea);
virtual HRESULT handle_function_child(
pdb_sym_t &fun_sym,
ea_t ea,
pdb_sym_t &child_sym,
DWORD child_tag,
DWORD child_loc_type);
virtual cvt_code_t handle_unnamed_overlapping_member(
pdb_udt_type_data_t * /*udt*/,
qstack<qstring> * /*union_names*/,
qstring * /*name*/) const
{
return cvt_ok;
}
protected:
typemap_t typemap; // id -> type info
tpdefs_t tpdefs; // id -> enum type defined in base til
idset_t handled; // set of handled symbols
creating_t creating;
unnamed_t unnamed_types;
vftmap_t vftmap; // vftable name -> vft info
int unnamed_idx;
int level;
public:
til_t *ti;
pdb_access_t *pdb_access;
bool enregistered_bug;
};