mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-16 00:52:23 -07:00
moved common codeview code to the main layer
This commit is contained in:
@@ -6,6 +6,139 @@
|
||||
|
||||
#include "generated/codeview.meta.c"
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal CV_Arch
|
||||
cv_arch_from_coff_machine(COFF_MachineType machine)
|
||||
{
|
||||
CV_Arch arch = 0;
|
||||
switch(machine)
|
||||
{
|
||||
case COFF_MachineType_X64: arch = CV_Arch_X64; break;
|
||||
case COFF_MachineType_X86: arch = CV_Arch_8086; break;
|
||||
case COFF_MachineType_AM33: arch = CV_Arch_AM33; break;
|
||||
case COFF_MachineType_ARM: NotImplemented; break;
|
||||
case COFF_MachineType_ARM64: arch = CV_Arch_ARM64; break;
|
||||
case COFF_MachineType_ARMNT: arch = CV_Arch_ARMNT; break;
|
||||
case COFF_MachineType_EBC: arch = CV_Arch_EBC; break;
|
||||
case COFF_MachineType_IA64: arch = CV_Arch_IA64; break;
|
||||
case COFF_MachineType_M32R: arch = CV_Arch_M32R; break;
|
||||
case COFF_MachineType_MIPS16: arch = CV_Arch_MIPS16; break;
|
||||
case COFF_MachineType_MIPSFPU: NotImplemented; break;
|
||||
case COFF_MachineType_MIPSFPU16: NotImplemented; break;
|
||||
case COFF_MachineType_POWERPC: NotImplemented; break;
|
||||
case COFF_MachineType_POWERPCFP: arch = CV_Arch_PPCFP; break;
|
||||
case COFF_MachineType_R4000: NotImplemented; break;
|
||||
case COFF_MachineType_RISCV32: NotImplemented; break;
|
||||
case COFF_MachineType_RISCV64: NotImplemented; break;
|
||||
case COFF_MachineType_RISCV128: NotImplemented; break;
|
||||
case COFF_MachineType_SH3: arch = CV_Arch_SH3; break;
|
||||
case COFF_MachineType_SH3DSP: arch = CV_Arch_SH3DSP; break;
|
||||
case COFF_MachineType_SH4: arch = CV_Arch_SH4; break;
|
||||
case COFF_MachineType_SH5: NotImplemented; break;
|
||||
case COFF_MachineType_THUMB: arch = CV_Arch_THUMB; break;
|
||||
case COFF_MachineType_WCEMIPSV2: NotImplemented; break;
|
||||
}
|
||||
return arch;
|
||||
}
|
||||
|
||||
internal U64
|
||||
cv_size_from_reg(CV_Arch arch, CV_Reg reg)
|
||||
{
|
||||
switch(arch)
|
||||
{
|
||||
case CV_Arch_8086: return cv_size_from_reg_x86(reg);
|
||||
case CV_Arch_X64 : return cv_size_from_reg_x64(reg);
|
||||
default: NotImplemented;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_reg_sp(CV_Arch arch, CV_Reg reg)
|
||||
{
|
||||
switch(arch)
|
||||
{
|
||||
case CV_Arch_8086: return reg == CV_Regx86_ESP;
|
||||
case CV_Arch_X64: return reg == CV_Regx64_RSP;
|
||||
default: NotImplemented;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
cv_size_from_reg_x86(CV_Reg reg)
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
#define X(NAME, CODE, RDI_NAME, BYTE_POS, BYTE_SIZE) case CV_Regx86_##NAME: return BYTE_SIZE;
|
||||
CV_Reg_X86_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal U64
|
||||
cv_size_from_reg_x64(CV_Reg reg)
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
#define X(NAME, CODE, RDI_NAME, BYTE_POS, BYTE_SIZE) case CV_Regx64_##NAME: return BYTE_SIZE;
|
||||
CV_Reg_X64_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal CV_EncodedFramePtrReg
|
||||
cv_pick_fp_encoding(CV_SymFrameproc *frameproc, B32 is_local_param)
|
||||
{
|
||||
CV_EncodedFramePtrReg fp_reg = 0;
|
||||
if(is_local_param)
|
||||
{
|
||||
fp_reg = CV_FrameprocFlags_ExtractParamBasePointer(frameproc->flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
fp_reg = CV_FrameprocFlags_ExtractLocalBasePointer(frameproc->flags);
|
||||
}
|
||||
return fp_reg;
|
||||
}
|
||||
|
||||
internal CV_Reg
|
||||
cv_decode_fp_reg(CV_Arch arch, CV_EncodedFramePtrReg encoded_reg)
|
||||
{
|
||||
CV_Reg fp_reg = 0;
|
||||
switch (arch)
|
||||
{
|
||||
case CV_Arch_8086:
|
||||
{
|
||||
switch (encoded_reg)
|
||||
{
|
||||
case CV_EncodedFramePtrReg_None : break;
|
||||
case CV_EncodedFramePtrReg_StackPtr: AssertAlways(!"TODO(nick): not tested, this is a guess");
|
||||
fp_reg = CV_Regx86_ESP; break;
|
||||
case CV_EncodedFramePtrReg_FramePtr: fp_reg = CV_Regx86_EBP; break;
|
||||
case CV_EncodedFramePtrReg_BasePtr : fp_reg = CV_Regx86_EBX; break;
|
||||
default: InvalidPath;
|
||||
}
|
||||
} break;
|
||||
case CV_Arch_X64:
|
||||
{
|
||||
switch (encoded_reg)
|
||||
{
|
||||
case CV_EncodedFramePtrReg_None : break;
|
||||
case CV_EncodedFramePtrReg_StackPtr: fp_reg = CV_Regx64_RSP; break;
|
||||
case CV_EncodedFramePtrReg_FramePtr: fp_reg = CV_Regx64_RBP; break;
|
||||
case CV_EncodedFramePtrReg_BasePtr : fp_reg = CV_Regx64_R13; break;
|
||||
default: InvalidPath;
|
||||
}
|
||||
} break;
|
||||
default: NotImplemented;
|
||||
}
|
||||
return fp_reg;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ CodeView Common Decoding Helper Functions
|
||||
|
||||
@@ -259,6 +392,760 @@ cv_inline_annot_signed_from_unsigned_operand(U32 value)
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal CV_TypeIndexInfo *
|
||||
cv_symbol_type_index_info_push(Arena *arena, CV_TypeIndexInfoList *list, CV_TypeIndexSource source, U64 offset)
|
||||
{
|
||||
CV_TypeIndexInfo *info = push_array_no_zero(arena, CV_TypeIndexInfo, 1);
|
||||
info->next = 0;
|
||||
info->offset = offset;
|
||||
info->source = source;
|
||||
|
||||
SLLQueuePush(list->first, list->last, info);
|
||||
list->count += 1;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
internal CV_TypeIndexInfoList
|
||||
cv_get_symbol_type_index_offsets(Arena *arena, CV_SymKind kind, String8 data)
|
||||
{
|
||||
CV_TypeIndexInfoList list = {0};
|
||||
switch (kind) {
|
||||
case CV_SymKind_BUILDINFO: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_SymBuildInfo, id));
|
||||
} break;
|
||||
case CV_SymKind_GDATA32:
|
||||
case CV_SymKind_LDATA32: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymData32, itype));
|
||||
} break;
|
||||
case CV_SymKind_LPROC32_ID:
|
||||
case CV_SymKind_GPROC32_ID:
|
||||
case CV_SymKind_LPROC32_DPC_ID: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_SymProc32, itype));
|
||||
} break;
|
||||
case CV_SymKind_GPROC32:
|
||||
case CV_SymKind_LPROC32:
|
||||
case CV_SymKind_LPROC32_DPC: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymProc32, itype));
|
||||
} break;
|
||||
case CV_SymKind_UDT: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymUDT, itype));
|
||||
} break;
|
||||
case CV_SymKind_GTHREAD32: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymThread32, itype));
|
||||
} break;
|
||||
case CV_SymKind_FILESTATIC: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymFileStatic, itype));
|
||||
} break;
|
||||
case CV_SymKind_LOCAL: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymLocal, itype));
|
||||
} break;
|
||||
case CV_SymKind_REGREL32:
|
||||
case CV_SymKind_BPREL32: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymRegrel32, itype));
|
||||
} break;
|
||||
case CV_SymKind_REGISTER: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymRegister, itype));
|
||||
} break;
|
||||
case CV_SymKind_CONSTANT: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymConstant, itype));
|
||||
} break;
|
||||
case CV_SymKind_CALLSITEINFO: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymCallSiteInfo, itype));
|
||||
} break;
|
||||
case CV_SymKind_CALLERS:
|
||||
case CV_SymKind_CALLEES:
|
||||
case CV_SymKind_INLINEES: {
|
||||
Assert(data.size >= sizeof(CV_SymFunctionList));
|
||||
CV_SymFunctionList *func_list = (CV_SymFunctionList*)data.str;
|
||||
for (U64 i = 0; i < func_list->count; ++i) {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, sizeof(CV_SymFunctionList) + i * sizeof(CV_TypeIndex));
|
||||
}
|
||||
} break;
|
||||
case CV_SymKind_INLINESITE: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_SymInlineSite, inlinee));
|
||||
} break;
|
||||
case CV_SymKind_HEAPALLOCSITE: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_SymHeapAllocSite, itype));
|
||||
} break;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
internal CV_TypeIndexInfoList
|
||||
cv_get_leaf_type_index_offsets(Arena *arena, CV_LeafKind leaf_kind, String8 data)
|
||||
{
|
||||
CV_TypeIndexInfoList list = {0};
|
||||
switch (leaf_kind) {
|
||||
case CV_LeafKind_NOTYPE:
|
||||
case CV_LeafKind_VTSHAPE:
|
||||
case CV_LeafKind_LABEL:
|
||||
case CV_LeafKind_NULL:
|
||||
case CV_LeafKind_NOTTRAN: {
|
||||
// no type indices
|
||||
} break;
|
||||
case CV_LeafKind_MODIFIER: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafModifier, itype));
|
||||
} break;
|
||||
case CV_LeafKind_POINTER: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafPointer, itype));
|
||||
CV_LeafPointer *ptr = (CV_LeafPointer *)data.str;
|
||||
CV_PointerKind ptr_kind = CV_PointerAttribs_ExtractKind(ptr->attribs);
|
||||
if (ptr_kind == CV_PointerKind_BaseType) {
|
||||
// TODO: add CV_LeafPointerBaseType
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, sizeof(CV_LeafPointer) + 0);
|
||||
} else {
|
||||
CV_PointerMode ptr_mode = CV_PointerAttribs_ExtractMode(ptr->attribs);
|
||||
if (ptr_mode == CV_PointerMode_PtrMem || ptr_mode == CV_PointerMode_PtrMethod) {
|
||||
// TODO: add type for the CvLeafPointerMember to syms_cv.mc
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, sizeof(CV_LeafPointer) + 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case CV_LeafKind_ARRAY: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafArray, entry_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafArray, index_itype));
|
||||
} break;
|
||||
case CV_LeafKind_CLASS:
|
||||
case CV_LeafKind_STRUCTURE:
|
||||
case CV_LeafKind_INTERFACE: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct, field_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct, derived_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct, vshape_itype));
|
||||
} break;
|
||||
case CV_LeafKind_CLASS2:
|
||||
case CV_LeafKind_STRUCT2: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct2, field_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct2, derived_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafStruct2, vshape_itype));
|
||||
} break;
|
||||
case CV_LeafKind_UNION: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafUnion, field_itype));
|
||||
} break;
|
||||
case CV_LeafKind_ALIAS: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafAlias, itype));
|
||||
} break;
|
||||
case CV_LeafKind_FUNC_ID: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_LeafFuncId, scope_string_id));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafFuncId, itype));
|
||||
} break;
|
||||
case CV_LeafKind_MFUNC_ID: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFuncId, owner_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFuncId, itype));
|
||||
} break;
|
||||
case CV_LeafKind_STRING_ID: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_LeafStringId, substr_list_id));
|
||||
} break;
|
||||
case CV_LeafKind_UDT_SRC_LINE: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafUDTSrcLine, udt_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_LeafUDTSrcLine, src_string_id));
|
||||
} break;
|
||||
case CV_LeafKind_UDT_MOD_SRC_LINE: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafUDTModSrcLine, udt_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, OffsetOf(CV_LeafUDTModSrcLine, src_string_id));
|
||||
} break;
|
||||
case CV_LeafKind_BUILDINFO: {
|
||||
Assert(data.size >= sizeof(CV_LeafBuildInfo));
|
||||
CV_LeafBuildInfo *build_info = (CV_LeafBuildInfo *)data.str;
|
||||
for (U16 i = 0; i < build_info->count; ++i) {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, sizeof(CV_LeafBuildInfo) + i * sizeof(CV_ItemId));
|
||||
}
|
||||
} break;
|
||||
case CV_LeafKind_ENUM: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafEnum, base_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafEnum, field_itype));
|
||||
} break;
|
||||
case CV_LeafKind_PROCEDURE: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafProcedure, ret_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafProcedure, arg_itype));
|
||||
} break;
|
||||
case CV_LeafKind_MFUNCTION: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFunction, ret_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFunction, class_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFunction, this_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMFunction, arg_itype));
|
||||
} break;
|
||||
case CV_LeafKind_VFTABLE: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafVFTable, owner_itype));
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafVFTable, base_table_itype));
|
||||
} break;
|
||||
case CV_LeafKind_VFTPATH: {
|
||||
Assert(sizeof(CV_LeafVFPath) <= data.size);
|
||||
CV_LeafVFPath *vfpath = (CV_LeafVFPath *)data.str;
|
||||
for (U32 i = 0; i < vfpath->count; ++i) {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, sizeof(CV_LeafVFPath) + i * sizeof(CV_TypeId));
|
||||
}
|
||||
} break;
|
||||
case CV_LeafKind_TYPESERVER:
|
||||
case CV_LeafKind_TYPESERVER2:
|
||||
case CV_LeafKind_TYPESERVER_ST: {
|
||||
// no type indices
|
||||
} break;
|
||||
case CV_LeafKind_SKIP: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafSkip, itype));
|
||||
} break;
|
||||
case CV_LeafKind_SUBSTR_LIST: {
|
||||
Assert(sizeof(CV_LeafArgList) <= data.size);
|
||||
CV_LeafArgList *arg_list = (CV_LeafArgList*)data.str;
|
||||
for (U32 i = 0; i < arg_list->count; ++i) {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, sizeof(CV_LeafArgList) + i * sizeof(CV_TypeIndex));
|
||||
}
|
||||
} break;
|
||||
case CV_LeafKind_ARGLIST: {
|
||||
Assert(sizeof(CV_LeafArgList) <= data.size);
|
||||
CV_LeafArgList *arg_list = (CV_LeafArgList*)data.str;
|
||||
for (U32 i = 0; i < arg_list->count; ++i) {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, sizeof(CV_LeafArgList) + i * sizeof(CV_TypeIndex));
|
||||
}
|
||||
} break;
|
||||
case CV_LeafKind_LIST:
|
||||
case CV_LeafKind_FIELDLIST: {
|
||||
for (U64 cursor = 0; cursor < data.size; ) {
|
||||
CV_LeafKind list_member_kind = 0;
|
||||
U64 read_size = str8_deserial_read_struct(data, cursor, &list_member_kind);
|
||||
|
||||
if(read_size != sizeof(list_member_kind)) {
|
||||
Assert(!"malformed LF_FIELDLIST");
|
||||
break;
|
||||
}
|
||||
cursor += read_size;
|
||||
|
||||
switch (list_member_kind) {
|
||||
default: Assert(!"TODO: handle malformed field member"); break;
|
||||
case CV_LeafKind_INDEX: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafIndex, itype));
|
||||
cursor += sizeof(CV_LeafIndex);
|
||||
} break;
|
||||
case CV_LeafKind_MEMBER: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafMember, itype));
|
||||
cursor += sizeof(CV_LeafMember);
|
||||
|
||||
CV_NumericParsed size;
|
||||
cursor += cv_read_numeric(data, cursor, &size);
|
||||
|
||||
String8 name;
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
} break;
|
||||
case CV_LeafKind_STMEMBER: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafStMember, itype));
|
||||
cursor += sizeof(CV_LeafStMember);
|
||||
|
||||
String8 name;
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
} break;
|
||||
case CV_LeafKind_METHOD: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafMethod, list_itype));
|
||||
cursor += sizeof(CV_LeafMethod);
|
||||
|
||||
String8 name;
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
} break;
|
||||
case CV_LeafKind_ONEMETHOD: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafOneMethod, itype));
|
||||
|
||||
CV_LeafOneMethod onemethod;
|
||||
cursor += str8_deserial_read_struct(data, cursor, &onemethod);
|
||||
|
||||
CV_MethodProp prop = CV_FieldAttribs_ExtractMethodProp(onemethod.attribs);
|
||||
if(prop == CV_MethodProp_PureIntro || prop == CV_MethodProp_Intro)
|
||||
{
|
||||
cursor += sizeof(U32); // virtoff
|
||||
}
|
||||
|
||||
String8 name;
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
} break;
|
||||
case CV_LeafKind_ENUMERATE: {
|
||||
// no type index
|
||||
cursor += sizeof(CV_LeafEnumerate);
|
||||
CV_NumericParsed value;
|
||||
cursor += cv_read_numeric(data, cursor, &value);
|
||||
String8 name;
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
} break;
|
||||
case CV_LeafKind_NESTTYPE: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafNestType, itype));
|
||||
cursor += sizeof(CV_LeafNestType);
|
||||
|
||||
String8 name;
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
} break;
|
||||
case CV_LeafKind_NESTTYPEEX: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafNestTypeEx, itype));
|
||||
|
||||
cursor += sizeof(CV_LeafNestTypeEx);
|
||||
String8 name;
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
} break;
|
||||
case CV_LeafKind_BCLASS: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafBClass, itype));
|
||||
|
||||
cursor += sizeof(CV_LeafBClass);
|
||||
CV_NumericParsed offset;
|
||||
cursor += cv_read_numeric(data, cursor, &offset);
|
||||
} break;
|
||||
case CV_LeafKind_VBCLASS:
|
||||
case CV_LeafKind_IVBCLASS: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafVBClass, itype));
|
||||
cursor += sizeof(CV_LeafVBClass);
|
||||
|
||||
CV_NumericParsed virtual_base_pointer;
|
||||
cursor += cv_read_numeric(data, cursor, &virtual_base_pointer);
|
||||
|
||||
CV_NumericParsed virtual_base_offset;
|
||||
cursor += cv_read_numeric(data, cursor, &virtual_base_offset);
|
||||
} break;
|
||||
case CV_LeafKind_VFUNCTAB: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafVFuncTab, itype));
|
||||
cursor += sizeof(CV_LeafVFuncTab);
|
||||
} break;
|
||||
case CV_LeafKind_VFUNCOFF: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafVFuncOff, itype));
|
||||
cursor += sizeof(CV_LeafVFuncOff);
|
||||
} break;
|
||||
}
|
||||
cursor = AlignPow2(cursor, 4);
|
||||
}
|
||||
} break;
|
||||
case CV_LeafKind_METHOD: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMethod, list_itype));
|
||||
} break;
|
||||
case CV_LeafKind_METHODLIST: {
|
||||
for (U64 cursor = 0; cursor < data.size; ) {
|
||||
// read method
|
||||
CV_LeafMethodListMember method;
|
||||
U64 read_size = str8_deserial_read_struct(data, cursor, &method);
|
||||
|
||||
// error check read
|
||||
if (read_size != sizeof(method)) {
|
||||
Assert(!"malformed LF_METHODLIST");
|
||||
break;
|
||||
}
|
||||
|
||||
// push type index offset
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, cursor + OffsetOf(CV_LeafMethodListMember, itype));
|
||||
|
||||
// take into account intro virtual offset
|
||||
CV_MethodProp mprop = CV_FieldAttribs_ExtractMethodProp(method.attribs);
|
||||
if (mprop == CV_MethodProp_Intro || mprop == CV_MethodProp_PureIntro) {
|
||||
read_size += sizeof(U32);
|
||||
}
|
||||
|
||||
// advance
|
||||
cursor += read_size;
|
||||
}
|
||||
} break;
|
||||
case CV_LeafKind_ONEMETHOD: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafOneMethod, itype));
|
||||
} break;
|
||||
case CV_LeafKind_BITFIELD: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafBitField, itype));
|
||||
} break;
|
||||
case CV_LeafKind_PRECOMP:
|
||||
case CV_LeafKind_REFSYM: {
|
||||
// no type indices
|
||||
} break;
|
||||
case CV_LeafKind_INDEX: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafIndex, itype));
|
||||
} break;
|
||||
case CV_LeafKind_MEMBER: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafMember, itype));
|
||||
} break;
|
||||
case CV_LeafKind_VFUNCTAB: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafVFuncTab, itype));
|
||||
} break;
|
||||
case CV_LeafKind_VFUNCOFF: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafVFuncOff, itype));
|
||||
} break;
|
||||
case CV_LeafKind_NESTTYPE: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafNestType, itype));
|
||||
} break;
|
||||
case CV_LeafKind_NESTTYPEEX: {
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_TPI, OffsetOf(CV_LeafNestTypeEx, itype));
|
||||
} break;
|
||||
default: {
|
||||
NotImplemented;
|
||||
} break;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
internal CV_TypeIndexInfoList
|
||||
cv_get_inlinee_type_index_offsets(Arena *arena, String8 raw_data)
|
||||
{
|
||||
CV_TypeIndexInfoList list = {0};
|
||||
|
||||
U64 cursor = 0;
|
||||
|
||||
// first four bytes are always signature
|
||||
CV_C13InlineeLinesSig sig = max_U32;
|
||||
cursor += str8_deserial_read_struct(raw_data, cursor, &sig);
|
||||
|
||||
while(cursor < raw_data.size)
|
||||
{
|
||||
// read header
|
||||
CV_C13InlineeSourceLineHeader *header = (CV_C13InlineeSourceLineHeader *) str8_deserial_get_raw_ptr(raw_data, cursor, sizeof(CV_C13InlineeSourceLineHeader));
|
||||
|
||||
// store type index offset
|
||||
cv_symbol_type_index_info_push(arena, &list, CV_TypeIndexSource_IPI, cursor + OffsetOf(CV_C13InlineeSourceLineHeader, inlinee));
|
||||
|
||||
// advance past header
|
||||
cursor += sizeof(*header);
|
||||
|
||||
// skip extra files
|
||||
B32 has_extra_files = (sig == CV_C13InlineeLinesSig_EXTRA_FILES);
|
||||
if (has_extra_files)
|
||||
{
|
||||
U32 file_count = 0;
|
||||
cursor += str8_deserial_read_struct(raw_data, cursor, &file_count);
|
||||
cursor += /* file id: */ sizeof(U32) * file_count;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
internal String8Array
|
||||
cv_get_data_around_type_indices(Arena *arena, CV_TypeIndexInfoList ti_list, String8 data)
|
||||
{
|
||||
String8Array result;
|
||||
if(ti_list.count > 0)
|
||||
{
|
||||
result.count = ti_list.count + 1;
|
||||
result.v = push_array_no_zero(arena, String8, result.count);
|
||||
|
||||
U64 cursor = 0;
|
||||
U64 ti_idx = 0;
|
||||
|
||||
for(CV_TypeIndexInfo *ti_info = ti_list.first; ti_info != 0; ti_info = ti_info->next, ++ti_idx)
|
||||
{
|
||||
result.v[ti_idx].size = ti_info->offset - cursor;
|
||||
result.v[ti_idx].str = data.str + cursor;
|
||||
cursor = ti_info->offset + sizeof(CV_TypeIndex);
|
||||
}
|
||||
|
||||
result.v[result.count-1].size = data.size - cursor;
|
||||
result.v[result.count-1].str = data.str + cursor;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.count = 1;
|
||||
result.v = push_array_no_zero(arena, String8, 1);
|
||||
result.v[0] = data;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CV_TypeIndexSource
|
||||
cv_type_index_source_from_leaf_kind(CV_LeafKind leaf_kind)
|
||||
{
|
||||
CV_TypeIndexSource source;
|
||||
if(leaf_kind == CV_LeafKind_FUNC_ID ||
|
||||
leaf_kind == CV_LeafKind_MFUNC_ID ||
|
||||
leaf_kind == CV_LeafKind_BUILDINFO ||
|
||||
leaf_kind == CV_LeafKind_SUBSTR_LIST ||
|
||||
leaf_kind == CV_LeafKind_STRING_ID ||
|
||||
leaf_kind == CV_LeafKind_UDT_SRC_LINE ||
|
||||
leaf_kind == CV_LeafKind_UDT_MOD_SRC_LINE)
|
||||
{
|
||||
source = CV_TypeIndexSource_IPI;
|
||||
}
|
||||
else if(leaf_kind == CV_LeafKind_NOTYPE)
|
||||
{
|
||||
source = CV_TypeIndexSource_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
source = CV_TypeIndexSource_TPI;
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
internal U64
|
||||
cv_name_offset_from_symbol(CV_SymKind kind, String8 data)
|
||||
{
|
||||
U64 offset = data.size;
|
||||
switch (kind) {
|
||||
case CV_SymKind_COMPILE: break;
|
||||
case CV_SymKind_OBJNAME: break;
|
||||
case CV_SymKind_THUNK32: {
|
||||
offset = sizeof(CV_SymThunk32);
|
||||
} break;
|
||||
case CV_SymKind_LABEL32: {
|
||||
offset = sizeof(CV_SymLabel32);
|
||||
} break;
|
||||
case CV_SymKind_REGISTER: {
|
||||
offset = sizeof(CV_SymRegister);
|
||||
} break;
|
||||
case CV_SymKind_CONSTANT: {
|
||||
offset = sizeof(CV_SymConstant);
|
||||
CV_NumericParsed size;
|
||||
offset += cv_read_numeric(data, offset, &size);
|
||||
} break;
|
||||
case CV_SymKind_UDT: {
|
||||
offset = sizeof(CV_SymUDT);
|
||||
} break;
|
||||
case CV_SymKind_BPREL32: {
|
||||
offset = sizeof(CV_SymBPRel32);
|
||||
} break;
|
||||
case CV_SymKind_LDATA32:
|
||||
case CV_SymKind_GDATA32: {
|
||||
offset = sizeof(CV_SymData32);
|
||||
} break;
|
||||
case CV_SymKind_PUB32: {
|
||||
offset = sizeof(CV_SymPub32);
|
||||
} break;
|
||||
case CV_SymKind_LPROC32:
|
||||
case CV_SymKind_GPROC32:
|
||||
case CV_SymKind_LPROC32_ID:
|
||||
case CV_SymKind_GPROC32_ID: {
|
||||
offset = sizeof(CV_SymProc32);
|
||||
} break;
|
||||
case CV_SymKind_REGREL32: {
|
||||
offset = sizeof(CV_SymRegrel32);
|
||||
} break;
|
||||
case CV_SymKind_LTHREAD32:
|
||||
case CV_SymKind_GTHREAD32: {
|
||||
offset = sizeof(CV_SymData32);
|
||||
} break;
|
||||
case CV_SymKind_COMPILE2: break;
|
||||
case CV_SymKind_LOCALSLOT: {
|
||||
offset = sizeof(CV_SymSlot);
|
||||
} break;
|
||||
case CV_SymKind_PROCREF:
|
||||
case CV_SymKind_LPROCREF:
|
||||
case CV_SymKind_DATAREF: {
|
||||
offset = sizeof(CV_SymRef2);
|
||||
} break;
|
||||
case CV_SymKind_TRAMPOLINE: break;
|
||||
case CV_SymKind_LOCAL: {
|
||||
offset = sizeof(CV_SymLocal);
|
||||
} break;
|
||||
default: InvalidPath;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
internal String8
|
||||
cv_name_from_symbol(CV_SymKind kind, String8 data)
|
||||
{
|
||||
U64 buf_off = cv_name_offset_from_symbol(kind, data);
|
||||
U8 *buf_ptr = data.str + buf_off;
|
||||
U8 *buf_opl = data.str + data.size;
|
||||
String8 name = str8_cstring_capped(buf_ptr, buf_opl);
|
||||
return name;
|
||||
}
|
||||
|
||||
internal CV_UDTInfo
|
||||
cv_get_udt_info(CV_LeafKind kind, String8 data)
|
||||
{
|
||||
String8 name = str8_zero();
|
||||
String8 unique_name = str8_zero();
|
||||
CV_TypeProps props = 0;
|
||||
|
||||
switch(kind) {
|
||||
case CV_LeafKind_CLASS:
|
||||
case CV_LeafKind_STRUCTURE:
|
||||
case CV_LeafKind_INTERFACE: {
|
||||
U64 cursor = 0;
|
||||
|
||||
CV_LeafStruct udt;
|
||||
cursor += str8_deserial_read_struct(data, cursor, &udt);
|
||||
|
||||
props = udt.props;
|
||||
|
||||
CV_NumericParsed size;
|
||||
cursor += cv_read_numeric(data, cursor, &size);
|
||||
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
|
||||
if (udt.props & CV_TypeProp_HasUniqueName) {
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &unique_name);
|
||||
}
|
||||
} break;
|
||||
|
||||
case CV_LeafKind_CLASS2:
|
||||
case CV_LeafKind_STRUCT2: {
|
||||
U64 cursor = 0;
|
||||
|
||||
CV_LeafStruct2 udt;
|
||||
cursor += str8_deserial_read_struct(data, cursor, &udt);
|
||||
|
||||
props = udt.props;
|
||||
|
||||
CV_NumericParsed size;
|
||||
cursor += cv_read_numeric(data, cursor, &size);
|
||||
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
|
||||
if (udt.props & CV_TypeProp_HasUniqueName) {
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &unique_name);
|
||||
}
|
||||
} break;
|
||||
|
||||
case CV_LeafKind_UNION: {
|
||||
U64 cursor = 0;
|
||||
|
||||
CV_LeafUnion udt;
|
||||
cursor += str8_deserial_read_struct(data, cursor, &udt);
|
||||
|
||||
CV_NumericParsed size;
|
||||
cursor += cv_read_numeric(data, cursor, &size);
|
||||
|
||||
props = udt.props;
|
||||
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
|
||||
if(udt.props & CV_TypeProp_HasUniqueName) {
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &unique_name);
|
||||
}
|
||||
} break;
|
||||
|
||||
case CV_LeafKind_ENUM: {
|
||||
U64 cursor = 0;
|
||||
|
||||
CV_LeafEnum udt;
|
||||
cursor += str8_deserial_read_struct(data, cursor, &udt);
|
||||
|
||||
props = udt.props;
|
||||
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &name);
|
||||
|
||||
if(udt.props & CV_TypeProp_HasUniqueName) {
|
||||
cursor += str8_deserial_read_cstr(data, cursor, &unique_name);
|
||||
}
|
||||
} break;
|
||||
|
||||
// dbi/tpi.cpp:1332
|
||||
case CV_LeafKind_UDT_SRC_LINE: {
|
||||
CV_LeafUDTSrcLine *src_line = str8_deserial_get_raw_ptr(data, 0, sizeof(CV_LeafUDTSrcLine));
|
||||
name = str8_struct(&src_line->udt_itype);
|
||||
} break;
|
||||
case CV_LeafKind_UDT_MOD_SRC_LINE: {
|
||||
CV_LeafUDTModSrcLine *mod_src_line = str8_deserial_get_raw_ptr(data, 0, sizeof(CV_LeafUDTModSrcLine));
|
||||
name = str8_struct(&mod_src_line->udt_itype);
|
||||
} break;
|
||||
|
||||
case CV_LeafKind_ALIAS: {
|
||||
str8_deserial_read_cstr(data, 0, &name);
|
||||
} break;
|
||||
|
||||
default: {
|
||||
InvalidPath;
|
||||
} break;
|
||||
}
|
||||
|
||||
CV_UDTInfo info = {0};
|
||||
info.name = name;
|
||||
info.unique_name = unique_name;
|
||||
info.props = props;
|
||||
return info;
|
||||
}
|
||||
|
||||
internal String8
|
||||
cv_name_from_udt_info(CV_UDTInfo udt_info)
|
||||
{
|
||||
if (udt_info.props & CV_TypeProp_HasUniqueName) {
|
||||
return udt_info.unique_name;
|
||||
}
|
||||
return udt_info.name;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_udt_name_anon(String8 name)
|
||||
{
|
||||
// corresponds to fUDTAnon from dbi/tm.cpp:817
|
||||
B32 is_anon = str8_match(str8_lit("<unnamed-tag>"), name, 0) ||
|
||||
str8_match(str8_lit("__unnamed"), name, 0) ||
|
||||
str8_match(str8_lit("::<unnamed-tag>"), name, StringMatchFlag_RightSideSloppy) ||
|
||||
str8_match(str8_lit("::__unnamed"), name, StringMatchFlag_RightSideSloppy);
|
||||
return is_anon;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_udt(CV_LeafKind kind)
|
||||
{
|
||||
B32 is_udt = kind == CV_LeafKind_CLASS ||
|
||||
kind == CV_LeafKind_STRUCTURE ||
|
||||
kind == CV_LeafKind_CLASS2 ||
|
||||
kind == CV_LeafKind_STRUCT2 ||
|
||||
kind == CV_LeafKind_INTERFACE ||
|
||||
kind == CV_LeafKind_UNION ||
|
||||
kind == CV_LeafKind_ENUM ||
|
||||
kind == CV_LeafKind_UDT_MOD_SRC_LINE ||
|
||||
kind == CV_LeafKind_UDT_SRC_LINE ||
|
||||
kind == CV_LeafKind_ALIAS;
|
||||
return is_udt;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_global_symbol(CV_SymKind kind)
|
||||
{
|
||||
B32 is_global_symbol = kind == CV_SymKind_CONSTANT ||
|
||||
kind == CV_SymKind_GDATA16 ||
|
||||
kind == CV_SymKind_GDATA32_16t ||
|
||||
kind == CV_SymKind_GDATA32_ST ||
|
||||
kind == CV_SymKind_GDATA32 ||
|
||||
kind == CV_SymKind_GTHREAD32_16t ||
|
||||
kind == CV_SymKind_GTHREAD32_ST ||
|
||||
kind == CV_SymKind_GTHREAD32;
|
||||
return is_global_symbol;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_typedef(CV_SymKind kind)
|
||||
{
|
||||
B32 is_typedef = kind == CV_SymKind_UDT_16t ||
|
||||
kind == CV_SymKind_UDT_ST ||
|
||||
kind == CV_SymKind_UDT;
|
||||
return is_typedef;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_scope_symbol(CV_SymKind kind)
|
||||
{
|
||||
B32 is_scope = kind == CV_SymKind_GPROC32 ||
|
||||
kind == CV_SymKind_LPROC32 ||
|
||||
kind == CV_SymKind_BLOCK32 ||
|
||||
kind == CV_SymKind_THUNK32 ||
|
||||
kind == CV_SymKind_INLINESITE ||
|
||||
kind == CV_SymKind_INLINESITE2 ||
|
||||
kind == CV_SymKind_WITH32 ||
|
||||
kind == CV_SymKind_SEPCODE ||
|
||||
kind == CV_SymKind_GPROC32_ID ||
|
||||
kind == CV_SymKind_LPROC32_ID;
|
||||
return is_scope;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_end_symbol(CV_SymKind kind)
|
||||
{
|
||||
B32 is_end = kind == CV_SymKind_END ||
|
||||
kind == CV_SymKind_PROC_ID_END ||
|
||||
kind == CV_SymKind_INLINESITE_END;
|
||||
return is_end;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_leaf_type_server(CV_LeafKind kind)
|
||||
{
|
||||
B32 is_type_server = kind == CV_LeafKind_TYPESERVER ||
|
||||
kind == CV_LeafKind_TYPESERVER2 ||
|
||||
kind == CV_LeafKind_TYPESERVER_ST;
|
||||
return is_type_server;
|
||||
}
|
||||
|
||||
internal B32
|
||||
cv_is_leaf_pch(CV_LeafKind kind)
|
||||
{
|
||||
B32 is_pch = kind == CV_LeafKind_PRECOMP ||
|
||||
kind == CV_LeafKind_PRECOMP_ST ||
|
||||
kind == CV_LeafKind_PRECOMP_16t;
|
||||
return is_pch;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ CodeView Parsing Functions
|
||||
|
||||
@@ -647,3 +1534,19 @@ cv_c13_parsed_from_data(Arena *arena, String8 c13_data, String8 strtbl, COFF_Sec
|
||||
ProfEnd();
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ Enum <-> String
|
||||
|
||||
internal String8
|
||||
cv_string_from_type_index_source(CV_TypeIndexSource ti_source)
|
||||
{
|
||||
switch (ti_source) {
|
||||
case CV_TypeIndexSource_NULL: return str8_lit(""); break;
|
||||
case CV_TypeIndexSource_TPI: return str8_lit("TPI"); break;
|
||||
case CV_TypeIndexSource_IPI: return str8_lit("IPI"); break;
|
||||
case CV_TypeIndexSource_COUNT: break;
|
||||
}
|
||||
return str8_zero();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
////////////////////////////////
|
||||
//~ rjf: CodeView Format Shared Types
|
||||
|
||||
#define CV_MinComplexTypeIndex 0x1000
|
||||
|
||||
#define CV_TypeIndex_Max max_U32
|
||||
typedef U32 CV_TypeIndex;
|
||||
typedef CV_TypeIndex CV_TypeId;
|
||||
@@ -2902,6 +2904,51 @@ struct CV_C13InlineeSourceLineHeader
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
////////////////////////////////
|
||||
//~ Type Index Helper
|
||||
|
||||
typedef enum CV_TypeIndexSource CV_TypeIndexSource;
|
||||
enum CV_TypeIndexSource
|
||||
{
|
||||
CV_TypeIndexSource_NULL,
|
||||
CV_TypeIndexSource_TPI,
|
||||
CV_TypeIndexSource_IPI,
|
||||
CV_TypeIndexSource_COUNT
|
||||
};
|
||||
|
||||
typedef struct CV_TypeIndexInfo CV_TypeIndexInfo;
|
||||
struct CV_TypeIndexInfo
|
||||
{
|
||||
struct CV_TypeIndexInfo *next;
|
||||
U64 offset;
|
||||
CV_TypeIndexSource source;
|
||||
};
|
||||
|
||||
typedef struct CV_TypeIndexInfoList CV_TypeIndexInfoList;
|
||||
struct CV_TypeIndexInfoList
|
||||
{
|
||||
U64 count;
|
||||
CV_TypeIndexInfo *first;
|
||||
CV_TypeIndexInfo *last;
|
||||
};
|
||||
|
||||
typedef struct CV_TypeIndexArray CV_TypeIndexArray;
|
||||
struct CV_TypeIndexArray
|
||||
{
|
||||
U32 count;
|
||||
CV_TypeIndex *v;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef struct CV_UDTInfo CV_UDTInfo;
|
||||
struct CV_UDTInfo
|
||||
{
|
||||
String8 name;
|
||||
String8 unique_name;
|
||||
CV_TypeProps props;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ CodeView Common Parser Types
|
||||
|
||||
@@ -3077,6 +3124,16 @@ struct CV_TypeIdArray
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal CV_Arch cv_arch_from_coff_machine(COFF_MachineType machine);
|
||||
internal U64 cv_size_from_reg_x86(CV_Reg reg);
|
||||
internal U64 cv_size_from_reg_x64(CV_Reg reg);
|
||||
internal U64 cv_size_from_reg(CV_Arch arch, CV_Reg reg);
|
||||
internal B32 cv_is_reg_sp(CV_Arch arch, CV_Reg reg);
|
||||
internal CV_EncodedFramePtrReg cv_pick_fp_encoding(CV_SymFrameproc *frameproc, B32 is_local_param);
|
||||
internal CV_Reg cv_decode_fp_reg(CV_Arch arch, CV_EncodedFramePtrReg encoded_reg);
|
||||
|
||||
////////////////////////////////
|
||||
//~ CodeView Common Decoding Helper Functions
|
||||
|
||||
@@ -3099,6 +3156,25 @@ internal U64 cv_decode_inline_annot_s32(String8 data, U64 offset, S32 *out_value
|
||||
|
||||
internal S32 cv_inline_annot_signed_from_unsigned_operand(U32 value);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal CV_TypeIndexInfoList cv_get_symbol_type_index_offsets(Arena *arena, CV_SymKind kind, String8 data);
|
||||
internal CV_TypeIndexInfoList cv_get_leaf_type_index_offsets(Arena *arena, CV_LeafKind leaf_kind, String8 data);
|
||||
internal CV_TypeIndexInfoList cv_get_inlinee_type_index_offsets(Arena *arena, String8 raw_data);
|
||||
internal String8Array cv_get_data_around_type_indices(Arena *arena, CV_TypeIndexInfoList ti_list, String8 data);
|
||||
internal CV_TypeIndexSource cv_type_index_source_from_leaf_kind(CV_LeafKind leaf_kind);
|
||||
|
||||
internal U64 cv_name_offset_from_symbol(CV_SymKind kind, String8 data);
|
||||
internal String8 cv_name_from_symbol(CV_SymKind kind, String8 data);
|
||||
|
||||
internal B32 cv_is_udt_name_anon(String8 name);
|
||||
internal B32 cv_is_udt(CV_LeafKind kind);
|
||||
internal B32 cv_is_global_symbol(CV_SymKind kind);
|
||||
internal B32 cv_is_typedef(CV_SymKind kind);
|
||||
internal B32 cv_is_scope_symbol(CV_SymKind kind);
|
||||
internal B32 cv_is_end_symbol(CV_SymKind kind);
|
||||
internal B32 cv_is_leaf_type_server(CV_LeafKind kind);
|
||||
internal B32 cv_is_leaf_pch(CV_LeafKind kind);
|
||||
|
||||
////////////////////////////////
|
||||
//~ CodeView Parsing Functions
|
||||
@@ -3118,4 +3194,9 @@ internal CV_LeafParsed *cv_leaf_from_data(Arena *arena, String8 leaf_data, CV_Ty
|
||||
|
||||
internal CV_C13Parsed *cv_c13_parsed_from_data(Arena *arena, String8 c13_data, String8 strtbl, COFF_SectionHeaderArray sections);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Enum <-> String
|
||||
|
||||
internal String8 cv_string_from_type_index_source(CV_TypeIndexSource ti_source);
|
||||
|
||||
#endif // CODEVIEW_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CV_MinComplexTypeIndex 0x1000
|
||||
|
||||
////////////////////////////////
|
||||
// Aligns
|
||||
|
||||
@@ -38,34 +36,6 @@ typedef struct CV_SymbolHeader
|
||||
////////////////////////////////
|
||||
// Type Index Helpers
|
||||
|
||||
typedef enum CV_TypeIndexSource
|
||||
{
|
||||
CV_TypeIndexSource_NULL,
|
||||
CV_TypeIndexSource_TPI,
|
||||
CV_TypeIndexSource_IPI,
|
||||
CV_TypeIndexSource_COUNT
|
||||
} CV_TypeIndexSource;
|
||||
|
||||
typedef struct CV_TypeIndexInfo
|
||||
{
|
||||
struct CV_TypeIndexInfo *next;
|
||||
U64 offset;
|
||||
CV_TypeIndexSource source;
|
||||
} CV_TypeIndexInfo;
|
||||
|
||||
typedef struct CV_TypeIndexInfoList
|
||||
{
|
||||
U64 count;
|
||||
CV_TypeIndexInfo *first;
|
||||
CV_TypeIndexInfo *last;
|
||||
} CV_TypeIndexInfoList;
|
||||
|
||||
typedef struct CV_TypeIndexArray
|
||||
{
|
||||
U32 count;
|
||||
CV_TypeIndex *v;
|
||||
} CV_TypeIndexArray;
|
||||
|
||||
//- $$Symbols
|
||||
|
||||
typedef struct CV_Symbol
|
||||
@@ -198,13 +168,6 @@ typedef struct CV_C13LinesHeaderList
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef struct CV_UDTInfo
|
||||
{
|
||||
String8 name;
|
||||
String8 unique_name;
|
||||
CV_TypeProps props;
|
||||
} CV_UDTInfo;
|
||||
|
||||
typedef struct CV_TypeServerInfo
|
||||
{
|
||||
String8 name;
|
||||
@@ -417,42 +380,17 @@ typedef struct
|
||||
} CV_Str8ListFromDebugT;
|
||||
|
||||
////////////////////////////////
|
||||
// Type Index Helpers
|
||||
|
||||
internal CV_TypeIndexInfo * cv_symbol_type_index_info_push(Arena *arena, CV_TypeIndexInfoList *list, CV_TypeIndexSource source, U64 offset);
|
||||
internal CV_TypeIndexInfoList cv_get_symbol_type_index_offsets(Arena *arena, CV_SymKind kind, String8 data);
|
||||
internal CV_TypeIndexInfoList cv_get_leaf_type_index_offsets(Arena *arena, CV_LeafKind leaf_kind, String8 data);
|
||||
internal CV_TypeIndexInfoList cv_get_inlinee_type_index_offsets(Arena *arena, String8 raw_data);
|
||||
internal String8Array cv_get_data_around_type_indices(Arena *arena, CV_TypeIndexInfoList ti_list, String8 data);
|
||||
internal CV_TypeIndexSource cv_type_index_source_from_leaf_kind(CV_LeafKind leaf_kind);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U64 cv_name_offset_from_symbol(CV_SymKind kind, String8 data);
|
||||
internal String8 cv_name_from_symbol (CV_SymKind kind, String8 data);
|
||||
internal String8 cv_name_from_udt_info (CV_UDTInfo udt_info);
|
||||
|
||||
internal B32 cv_is_udt_name_anon (String8 name);
|
||||
internal B32 cv_is_udt (CV_LeafKind kind);
|
||||
internal B32 cv_is_global_symbol (CV_SymKind kind);
|
||||
internal B32 cv_is_typedef (CV_SymKind kind);
|
||||
internal B32 cv_is_scope_symbol (CV_SymKind kind);
|
||||
internal B32 cv_is_end_symbol (CV_SymKind kind);
|
||||
internal B32 cv_is_leaf_type_server(CV_LeafKind kind);
|
||||
internal B32 cv_is_leaf_pch (CV_LeafKind kind);
|
||||
|
||||
internal CV_ObjInfo cv_obj_info_from_symbol(CV_Symbol symbol);
|
||||
internal CV_TypeServerInfo cv_type_server_info_from_leaf(CV_Leaf leaf);
|
||||
internal CV_PrecompInfo cv_precomp_info_from_leaf(CV_Leaf leaf);
|
||||
|
||||
internal B32 cv_is_reg_sp(CV_Arch arch, CV_Reg reg);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Leaf Helpers
|
||||
|
||||
internal U64 cv_compute_leaf_record_size(String8 data, U64 align);
|
||||
internal U64 cv_serialize_leaf_to_buffer(U8 *buffer, U64 buffer_cursor, U64 buffer_size, CV_LeafKind kind, String8 data, U64 align);
|
||||
internal String8 cv_serialize_leaf_ex(Arena *arena, CV_LeafKind kind, String8 data, U64 align);
|
||||
internal String8 cv_serialize_raw_leaf(Arena *arena, CV_LeafKind kind, String8 data, U64 align);
|
||||
internal String8 cv_serialize_leaf(Arena *arena, CV_Leaf *leaf, U64 align);
|
||||
internal CV_Leaf cv_make_leaf(Arena *arena, CV_LeafKind kind, String8 data);
|
||||
internal U64 cv_deserial_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out);
|
||||
@@ -506,6 +444,9 @@ internal U64 cv_debug_t_array_count_leaves(U64 count, CV_DebugT *arr
|
||||
|
||||
internal String8List cv_str8_list_from_debug_t_parallel(TP_Context *tp, Arena *arena, CV_DebugT types);
|
||||
|
||||
////////////////////////////////
|
||||
//~ Sub Section helpers
|
||||
|
||||
// $$Symbols
|
||||
internal void cv_parse_symbol_sub_section(Arena *arena, CV_SymbolList *list, U64 offset_base, String8 data, U64 align);
|
||||
internal void cv_symbol_list_push_node(CV_SymbolList *list, CV_SymbolNode *node);
|
||||
@@ -518,15 +459,12 @@ internal void cv_symbol_list_concat_in_place_arr(CV_SymbolList *lis
|
||||
internal U64 cv_symbol_list_arr_get_count(U64 count, CV_SymbolList *list_arr);
|
||||
internal String8List cv_data_from_symbol_list(Arena *arena, CV_SymbolList symbol_list, U64 align);
|
||||
internal CV_SymbolList cv_global_scope_symbols_from_list(Arena *arena, CV_SymbolList list);
|
||||
internal CV_ScopeList cv_symbol_tree_from_symbol_list(Arena *arena, CV_SymbolList list);
|
||||
internal CV_SymbolList cv_build_symbol_tree(Arena *arena, CV_ScopeList symbol_tree, U64 symbol_base, U64 align);
|
||||
internal CV_SymbolPtrArray cv_symbol_ptr_array_from_list(Arena *arena, TP_Context *tp, U64 count, CV_SymbolList *symbol_list_arr);
|
||||
|
||||
// $$FileChksms
|
||||
#define CV_MAP_STRING_TO_OFFSET_FUNC(name) U64 name(void *ud, String8 string)
|
||||
typedef CV_MAP_STRING_TO_OFFSET_FUNC(CV_MapStringToOffsetFunc);
|
||||
|
||||
//internal String8 cv_c13_file_chksms_from_sub_sections(String8 c13_data, CV_C13Parsed *ss);
|
||||
internal void cv_c13_patch_string_offsets_in_checksum_list(CV_ChecksumList checksum_list, String8 string_data, U64 string_data_base_offset, CV_StringHashTable string_ht);
|
||||
internal String8List cv_c13_collect_source_file_names(Arena *arena, CV_ChecksumList checksum_list, String8 string_data);
|
||||
|
||||
@@ -566,19 +504,6 @@ internal String8 cv_pack_string_hash_table(Arena *arena, TP_Con
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal CV_EncodedFramePtrReg cv_pick_fp_encoding(CV_SymFrameproc *frameproc, B32 is_local_param);
|
||||
internal CV_Reg cv_decode_fp_reg(CV_Arch arch, CV_EncodedFramePtrReg encoded_reg);
|
||||
internal Rng1U64List cv_make_defined_range_list_from_gaps(Arena *arena, Rng1U64 defrange, CV_LvarAddrGap *gaps, U64 gap_count);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal U64 cv_size_from_reg_x86(CV_Reg reg);
|
||||
internal U64 cv_size_from_reg_x64(CV_Reg reg);
|
||||
internal U64 cv_size_from_reg(CV_Arch arch, CV_Reg reg);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal CV_Arch cv_arch_from_coff_machine(COFF_MachineType machine);
|
||||
internal String8 cv_string_from_type_index_source(CV_TypeIndexSource ti_source);
|
||||
internal Rng1U64List cv_make_defined_range_list_from_gaps(Arena *arena, Rng1U64 defrange, CV_LvarAddrGap *gaps, U64 gap_count);
|
||||
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir
|
||||
|
||||
// TODO: temp hack, remove when we have null obj with .debug$T
|
||||
{
|
||||
String8 raw_null_leaf = cv_serialize_leaf_ex(scratch.arena, CV_LeafKind_NOTYPE, str8(0,0), 1);
|
||||
String8 raw_null_leaf = cv_serialize_raw_leaf(scratch.arena, CV_LeafKind_NOTYPE, str8(0,0), 1);
|
||||
|
||||
String8List srl = {0};
|
||||
str8_serial_begin(scratch.arena, &srl);
|
||||
|
||||
@@ -1330,7 +1330,7 @@ pdb_type_server_make_leaf(PDB_TypeServer *ts, CV_LeafKind kind, String8 data)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
|
||||
String8 leaf = cv_serialize_leaf_ex(ts->arena, kind, data, PDB_LEAF_ALIGN);
|
||||
String8 leaf = cv_serialize_raw_leaf(ts->arena, kind, data, PDB_LEAF_ALIGN);
|
||||
String8Node *node = str8_list_push(ts->arena, &ts->leaf_list, leaf);
|
||||
|
||||
ProfEnd();
|
||||
|
||||
+3
-44
@@ -586,50 +586,9 @@ pdb_gsi_symbol_from_string(PDB_GsiParsed *gsi, String8 symbol_data, String8 stri
|
||||
sym_opl = symbol_data.str + opl_off;
|
||||
}
|
||||
|
||||
String8 sym_name = str8_zero();
|
||||
switch(sym_header->kind)
|
||||
{
|
||||
case CV_SymKind_CONSTANT:
|
||||
{
|
||||
CV_SymConstant *sym = (CV_SymConstant*)(sym_header+1);
|
||||
CV_NumericParsed dummy;
|
||||
U64 numeric_size = cv_read_numeric(symbol_data, off + sizeof(CV_RecHeader), &dummy);
|
||||
sym_name = str8_cstring_capped((U8*)(sym+1)+numeric_size, sym_opl);
|
||||
}break;
|
||||
case CV_SymKind_LDATA32:
|
||||
case CV_SymKind_GDATA32:
|
||||
{
|
||||
CV_SymData32 *sym = (CV_SymData32 *)(sym_header+1);
|
||||
sym_name = str8_cstring_capped(sym+1, sym_opl);
|
||||
}break;
|
||||
case CV_SymKind_LTHREAD32:
|
||||
case CV_SymKind_GTHREAD32:
|
||||
{
|
||||
if(off + sizeof(CV_RecHeader) + sizeof(CV_SymThread32) <= symbol_data.size)
|
||||
{
|
||||
CV_SymThread32 *sym = (CV_SymThread32 *)(sym_header+1);
|
||||
sym_name = str8_cstring_capped(sym+1, sym_opl);
|
||||
}
|
||||
}break;
|
||||
case CV_SymKind_UDT:
|
||||
{
|
||||
if(off + sizeof(CV_RecHeader) + sizeof(CV_SymUDT) <= symbol_data.size)
|
||||
{
|
||||
CV_SymUDT *sym = (CV_SymUDT *)(sym_header+1);
|
||||
sym_name = str8_cstring_capped(sym+1, sym_opl);
|
||||
}
|
||||
}break;
|
||||
case CV_SymKind_LPROCREF:
|
||||
case CV_SymKind_PROCREF:
|
||||
{
|
||||
if(off + sizeof(CV_RecHeader) + sizeof(CV_SymRef2) <= symbol_data.size)
|
||||
{
|
||||
CV_SymRef2 *sym = (CV_SymRef2 *)(sym_header+1);
|
||||
sym_name = str8_cstring_capped(sym+1, sym_opl);
|
||||
}
|
||||
}break;
|
||||
default: InvalidPath;
|
||||
}
|
||||
Rng1U64 raw_symbol_range = rng_1u64(off + sizeof(*sym_header), off + (sym_header->size - sizeof(sym_header->kind)));
|
||||
String8 raw_symbol = str8_substr(symbol_data, raw_symbol_range);
|
||||
String8 sym_name = cv_name_from_symbol(sym_header->kind, raw_symbol);
|
||||
|
||||
if(str8_match(sym_name, string, 0))
|
||||
{
|
||||
|
||||
@@ -415,22 +415,6 @@ p2r_location_from_addr_reg_off(Arena *arena, RDI_Arch arch, RDI_RegCode reg_code
|
||||
return result;
|
||||
}
|
||||
|
||||
internal CV_EncodedFramePtrReg
|
||||
p2r_cv_encoded_fp_reg_from_frameproc(CV_SymFrameproc *frameproc, B32 param_base)
|
||||
{
|
||||
CV_EncodedFramePtrReg result = 0;
|
||||
CV_FrameprocFlags flags = frameproc->flags;
|
||||
if(param_base)
|
||||
{
|
||||
result = CV_FrameprocFlags_ExtractParamBasePointer(flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CV_FrameprocFlags_ExtractLocalBasePointer(flags);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal RDI_RegCode
|
||||
p2r_reg_code_from_arch_encoded_fp_reg(RDI_Arch arch, CV_EncodedFramePtrReg encoded_reg)
|
||||
{
|
||||
@@ -2762,7 +2746,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work)
|
||||
U64 gap_count = ((U8*)sym_data_opl - (U8*)gaps) / sizeof(*gaps);
|
||||
|
||||
// rjf: select frame pointer register
|
||||
CV_EncodedFramePtrReg encoded_fp_reg = p2r_cv_encoded_fp_reg_from_frameproc(frameproc, defrange_target_is_param);
|
||||
CV_EncodedFramePtrReg encoded_fp_reg = cv_pick_fp_encoding(frameproc, defrange_target_is_param);
|
||||
RDI_RegCode fp_register_code = p2r_reg_code_from_arch_encoded_fp_reg(in->arch, encoded_fp_reg);
|
||||
|
||||
// rjf: build location
|
||||
@@ -2834,7 +2818,7 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work)
|
||||
|
||||
// rjf: unpack sym
|
||||
CV_SymDefrangeFramepointerRelFullScope *defrange_fprel_full_scope = (CV_SymDefrangeFramepointerRelFullScope*)sym_header_struct_base;
|
||||
CV_EncodedFramePtrReg encoded_fp_reg = p2r_cv_encoded_fp_reg_from_frameproc(frameproc, defrange_target_is_param);
|
||||
CV_EncodedFramePtrReg encoded_fp_reg = cv_pick_fp_encoding(frameproc, defrange_target_is_param);
|
||||
RDI_RegCode fp_register_code = p2r_reg_code_from_arch_encoded_fp_reg(in->arch, encoded_fp_reg);
|
||||
|
||||
// rjf: build location
|
||||
|
||||
@@ -568,7 +568,6 @@ internal RDI_TypeKind p2r_rdi_type_kind_from_cv_basic_type(CV_BasicType basic_ty
|
||||
//~ rjf: Location Info Building Helpers
|
||||
|
||||
internal RDIM_Location *p2r_location_from_addr_reg_off(Arena *arena, RDI_Arch arch, RDI_RegCode reg_code, U32 reg_byte_size, U32 reg_byte_pos, S64 offset, B32 extra_indirection);
|
||||
internal CV_EncodedFramePtrReg p2r_cv_encoded_fp_reg_from_frameproc(CV_SymFrameproc *frameproc, B32 param_base);
|
||||
internal RDI_RegCode p2r_reg_code_from_arch_encoded_fp_reg(RDI_Arch arch, CV_EncodedFramePtrReg encoded_reg);
|
||||
internal void p2r_location_over_lvar_addr_range(Arena *arena, RDIM_ScopeChunkList *scopes, RDIM_LocationSet *locset, RDIM_Location *location, CV_LvarAddrRange *range, COFF_SectionHeader *section, CV_LvarAddrGap *gaps, U64 gap_count);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user