Leak A - calling-convention string leaked Leak B - orphaned callables on duplicate names Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
394 lines
10 KiB
C
394 lines
10 KiB
C
// SPDX-FileCopyrightText: 2021 Basstorm <basstorm@nyist.edu.cn>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#ifndef RZ_PDB_H
|
|
#define RZ_PDB_H
|
|
|
|
#include <rz_util.h>
|
|
#include <rz_type.h>
|
|
#include <rz_cmd.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define CAB_SIGNATURE "MSCF"
|
|
#define PDB_SIGNATURE "Microsoft C/C++ MSF 7.00\r\n\x1a\x44\x53\x00\x00\x00"
|
|
#define PDB_SIGNATURE_LEN 32
|
|
|
|
#define GET_BF(value, start, len) (((value) >> (start)) & ((1 << len) - 1))
|
|
|
|
// DBI
|
|
typedef struct dbi_stream_header_t {
|
|
st32 version_signature;
|
|
ut32 version_header;
|
|
ut32 age;
|
|
ut16 global_stream_index;
|
|
ut16 build_number;
|
|
ut16 public_stream_index;
|
|
ut16 pdb_dll_version;
|
|
ut16 sym_record_stream;
|
|
ut16 pdb_dll_rbld;
|
|
ut32 mod_info_size;
|
|
ut32 section_contribution_size;
|
|
ut32 section_map_size;
|
|
ut32 source_info_size;
|
|
ut32 type_server_map_size;
|
|
ut32 mfc_type_server_index;
|
|
ut32 optional_dbg_header_size;
|
|
ut32 ec_substream_size;
|
|
ut16 flags;
|
|
ut16 machine;
|
|
ut32 padding;
|
|
} RzPdbRzPdbDbiStreamHdr;
|
|
|
|
typedef struct {
|
|
st16 sn_fpo;
|
|
st16 sn_exception;
|
|
st16 sn_fixup;
|
|
st16 sn_omap_to_src;
|
|
st16 sn_omap_from_src;
|
|
st16 sn_section_hdr;
|
|
st16 sn_token_rid_map;
|
|
st16 sn_xdata;
|
|
st16 sn_pdata;
|
|
st16 sn_new_fpo;
|
|
st16 sn_section_hdr_orig;
|
|
} RzPdbRzPdbDbiStreamDbgHeader;
|
|
|
|
typedef struct dbi_stream_t {
|
|
RzPdbRzPdbDbiStreamHdr hdr;
|
|
ut64 hdr_size;
|
|
RzPVector /*<PDB_DBIModule *>*/ *modules;
|
|
RzPdbRzPdbDbiStreamDbgHeader dbg_hdr;
|
|
} RzPdbDbiStream;
|
|
|
|
// GDATA
|
|
typedef struct {
|
|
RzPVector /*<GDataGlobal *>*/ *global_symbols;
|
|
} RzPdbGDataStream;
|
|
|
|
// OMAP
|
|
typedef struct
|
|
{
|
|
RzList /*<OmapEntry *>*/ *entries;
|
|
ut64 *froms;
|
|
} RzPdbOmapStream;
|
|
|
|
// PE Stream
|
|
typedef struct {
|
|
RzList /*<PeImageSectionHeader *>*/ *sections_hdrs;
|
|
} RzPdbPeStream;
|
|
|
|
// TPI
|
|
typedef enum {
|
|
NEAR_C = 0x00000000,
|
|
FAR_C = 0x00000001,
|
|
NEAR_PASCAL = 0x00000002,
|
|
FAR_PASCAL = 0x00000003,
|
|
NEAR_FAST = 0x00000004,
|
|
FAR_FAST = 0x00000005,
|
|
SKIPPED = 0x00000006,
|
|
NEAR_STD = 0x00000007,
|
|
FAR_STD = 0x00000008,
|
|
NEAR_SYS = 0x00000009,
|
|
FAR_SYS = 0x0000000A,
|
|
THISCALL = 0x0000000B,
|
|
MIPSCALL = 0x0000000C,
|
|
GENERIC = 0x0000000D,
|
|
ALPHACALL = 0x0000000E,
|
|
PPCCALL = 0x0000000F,
|
|
SHCALL = 0x00000010,
|
|
ARMCALL = 0x00000011,
|
|
AM33CALL = 0x00000012,
|
|
TRICALL = 0x00000013,
|
|
SH5CALL = 0x00000014,
|
|
M32RCALL = 0x00000015,
|
|
CLRCALL = 0x00000016,
|
|
INLINECALL = 0x00000017,
|
|
NEAR_VEC = 0X00000018,
|
|
RESERVED = 0x00000019,
|
|
MAX_CV_CALL
|
|
} RzPdbTpiCallingConvention;
|
|
|
|
typedef enum {
|
|
V40 = 19950410,
|
|
V41 = 19951122,
|
|
V50 = 19961031,
|
|
V70 = 19990903,
|
|
V80 = 20040203,
|
|
} RzPdbTpiStreamVersion;
|
|
|
|
typedef struct tpi_stream_header_t {
|
|
RzPdbTpiStreamVersion Version;
|
|
ut32 HeaderSize;
|
|
ut32 TypeIndexBegin;
|
|
ut32 TypeIndexEnd;
|
|
ut32 TypeRecordBytes;
|
|
|
|
ut16 HashStreamIndex;
|
|
ut16 HashAuxStreamIndex;
|
|
ut32 HashKeySize;
|
|
ut32 NumHashBuckets;
|
|
|
|
st32 HashValueBufferOffset;
|
|
ut32 HashValueBufferLength;
|
|
|
|
st32 IndexOffsetBufferOffset;
|
|
ut32 IndexOffsetBufferLength;
|
|
|
|
st32 HashAdjBufferOffset;
|
|
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;
|
|
|
|
typedef struct tpi_stream_t {
|
|
RzPdbTpiStreamHeader header;
|
|
RBTree types;
|
|
ut64 type_index_base;
|
|
RzList /*<RzBaseType *>*/ *print_type;
|
|
} RzPdbTpiStream;
|
|
|
|
// PDB
|
|
typedef enum pdb_stream_index_t {
|
|
PDB_STREAM_ROOT = 0, // PDB_ROOT_DIRECTORY
|
|
PDB_STREAM_PDB, // PDB STREAM INFO
|
|
PDB_STREAM_TPI, // TYPE INFO
|
|
PDB_STREAM_DBI, // DEBUG INFO
|
|
|
|
PDB_STREAM_GSYM,
|
|
PDB_STREAM_SECT_HDR,
|
|
PDB_STREAM_SECT__HDR_ORIG,
|
|
PDB_STREAM_OMAP_TO_SRC,
|
|
PDB_STREAM_OMAP_FROM_SRC,
|
|
PDB_STREAM_FPO,
|
|
PDB_STREAM_FPO_NEW,
|
|
PDB_STREAM_XDATA,
|
|
PDB_STREAM_PDATA,
|
|
PDB_STREAM_TOKEN_RID_MAP,
|
|
PDB_STREAM_MAX
|
|
} RzRzPdbStreamIndex;
|
|
|
|
enum pdb_stream_version {
|
|
VC2 = 19941610,
|
|
VC4 = 19950623,
|
|
VC41 = 19950814,
|
|
VC50 = 19960307,
|
|
VC98 = 19970604,
|
|
VC70Dep = 19990604,
|
|
VC70 = 20000404,
|
|
VC80 = 20030901,
|
|
VC110 = 20091201,
|
|
VC140 = 20140508,
|
|
};
|
|
|
|
/**
|
|
* Like GUID in windows.h/guiddef.h
|
|
*/
|
|
typedef struct {
|
|
ut32 data1;
|
|
ut16 data2;
|
|
ut16 data3;
|
|
ut8 data4[8];
|
|
} RzPdbGuid;
|
|
|
|
typedef struct {
|
|
ut32 version;
|
|
ut32 signature;
|
|
ut32 age;
|
|
RzPdbGuid unique_id;
|
|
} RzRzPdbStreamHeader;
|
|
|
|
typedef struct {
|
|
RzRzPdbStreamHeader hdr;
|
|
/* Todo: parse named table */
|
|
} RzPdbStream;
|
|
|
|
/**
|
|
* \brief MSF file format header https://llvm.org/docs/PDB/MsfFile.html#the-superblock
|
|
*/
|
|
typedef struct {
|
|
char file_magic[PDB_SIGNATURE_LEN]; ///< Must be equal to "Microsoft C / C++ MSF 7.00\\r\\n" followed by the bytes 1A 44 53 00 00 00.
|
|
ut32 block_size; ///< The block size of the internal file system.
|
|
ut32 free_block_map_block; ///< The index of a block within the file, the data within that block is not used.
|
|
ut32 num_blocks; ///< The total number of blocks in the file
|
|
ut32 num_directory_bytes; ///< The size of the stream directory, in bytes.
|
|
ut32 unknown;
|
|
ut32 block_map_addr; ///< The index of a block within the MSF file.
|
|
} RzPdbMsfSuperBlock;
|
|
|
|
typedef struct {
|
|
ut32 stream_idx;
|
|
ut32 stream_size;
|
|
ut32 blocks_num;
|
|
RzBuffer *stream_data;
|
|
} RzPdbMsfStream;
|
|
|
|
typedef struct {
|
|
ut32 NumStreams;
|
|
ut32 *StreamSizes;
|
|
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;
|
|
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;
|
|
size_t RtlpHpHeapGlobalsOffset; ///< Related to windows heap
|
|
size_t RtlpLFHKeyOffset; ///< Related to windows heap
|
|
} RzPdb;
|
|
|
|
typedef struct {
|
|
ut32 offset;
|
|
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;
|
|
|
|
typedef struct {
|
|
bool code : 1;
|
|
bool function : 1;
|
|
bool managed : 1;
|
|
bool msil : 1;
|
|
PDBSectionOffset offset;
|
|
char *name;
|
|
} PDBSPublic;
|
|
|
|
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 RzPdb *pdb,
|
|
RZ_BORROW RZ_NONNULL bool (*f)(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);
|
|
RZ_API RZ_BORROW const char *rz_bin_pdb_calling_convention_as_string(RZ_NONNULL RzPdbTpiCallingConvention idx);
|
|
RZ_API bool rz_bin_pdb_type_is_fwdref(RZ_NONNULL RzPdbTpiType *t);
|
|
RZ_API RZ_BORROW RzPVector /*<RzPdbTpiType *>*/ *rz_bin_pdb_get_type_members(RZ_NONNULL RzPdbTpiStream *stream, RzPdbTpiType *t);
|
|
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_BORROW RZ_NONNULL const RzPdb *pdb,
|
|
RZ_BORROW RZ_NONNULL const PDBSectionOffset *section_offset);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|