Files
raddebugger/src/msvc_crt/msvc_crt.h
T

381 lines
12 KiB
C++

// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef MSVC_CRT
#define MSVC_CRT
////////////////////////////////
// CRT Symbols
// _load_config_used points to PE_LoadConfig32/PE_LoadConfig64
// and symbols below are used to patch patricual fields of the struct.
#define MSCRT_LOAD_CONFIG_SYMBOL_NAME "_load_config_used"
#define MSCRT_ENCLAVE_CONFIG_SYMBOL_NAME "__enclave_config"
#define MSCRT_GUARD_FLAGS_SYMBOL_NAME "__guard_flags"
#define MSCRT_GUARD_FIDS_TABLE_SYMBOL_NAME "__guard_fids_table"
#define MSCRT_GUARD_FIDS_COUNT_SYMBOL_NAME "__guard_fids_count"
#define MSCRT_GUARD_IAT_TABLE_SYMBOL_NAME "__guard_iat_table"
#define MSCRT_GUARD_IAT_COUNT_SYMBOL_NAME "__guard_iat_count"
#define MSCRT_GUARD_LONGJMP_TABLE_SYMBOL_NAME "__guard_longjmp_table"
#define MSCRT_GUARD_LONGJMP_COUNT_SYMBOL_NAME "__guard_longjmp_count"
#define MSCRT_GUARD_EHCONT_TABLE_SYMBOL_NAME "__guard_eh_cont_table"
#define MSCRT_GUARD_EHCONT_COUNT_SYMBOL_NAME "__guard_eh_cont_count"
// x86 load config fields
#define MSCRT_SAFE_SE_HANDLER_TABLE_SYMBOL_NAME "__safe_se_handler_table"
#define MSCRT_SAFE_SE_HANDLER_COUNT_SYMBOL_NAME "__safe_se_handler_count"
// load symbols from delayimp.lib
#define MSCRT_DELAY_LOAD_HELPER2_SYMBOL_NAME "__delayLoadHelper2"
#define MSCRT_DELAY_LOAD_HELPER2_X86_SYMBOL_NAME "___delayLoadHelper2@8"
// _tls_used is a special section in CRT which has format of
// PE_TLSHeader32 or PE_TLSHeader64, according to machine type.
#define MSCRT_TLS_SYMBOL_NAME "_tls_used"
////////////////////////////////
// feature flags in absolute symbol @feat.00
enum
{
MSCRT_FeatFlag_HAS_SAFE_SEH = (1 << 0), // /safeseh
MSCRT_FeatFlag_UNKNOWN_4 = (1 << 4),
MSCRT_FeatFlag_GUARD_STACK = (1 << 8), // /GS
MSCRT_FeatFlag_SDL = (1 << 9), // /sdl
MSCRT_FeatFlag_GUARD_CF = (1 << 11), // /guard:cf
MSCRT_FeatFlag_GUARD_EH_CONT = (1 << 14), // /guard:ehcont
MSCRT_FeatFlag_NO_RTTI = (1 << 17), // /GR-
MSCRT_FeatFlag_KERNEL = (1 << 30), // /kernel
};
typedef U32 MSCRT_FeatFlags;
typedef struct MSCRT_VCFeatures
{
U32 pre_vcpp;
U32 c_cpp;
U32 gs;
U32 sdl;
U32 guard_n;
} MSCRT_VCFeatures;
////////////////////////////////
// GS Handler
#define MSCRT_GSHandler_GetFlags(x) (((x) & 0x00000007) >> 0)
#define MSCRT_GSHandler_GetCookieOffset(x) (((x) & 0xFFFFFFF8) >> 3)
typedef U8 MSCRT_GSHandlerFlags;
enum
{
MSCRT_GSHandlerFlag_EHandler = (1 << 0),
MSCRT_GSHandlerFlag_UHandler = (1 << 1),
MSCRT_GSHandlerFlag_HasAlignment = (1 << 2)
};
////////////////////////////////
// Exceptions < v4
#define MSCRT_MAGIC_GET_CHECK(x) ((x) & 0x1FFFFFFF)
#define MSCRT_MAGIC_GET_FLAGS(x) (((x) & 0xE0000000) >> 29)
// Magic numbers are incremented by one everytime there is a new version.
// Top 3 bits are reserved for flags.
enum
{
MSCRT_Magic1 = 0x19930520,
MSCRT_Magic2 = 0x19930521,
MSCRT_Magic3 = 0x19930522,
// pure magic indicates that exception cannot be caught in native or managed code.
MSCRT_PureMagic1 = 0x1994000,
};
enum
{
MSCRT_MagicFlag_EHS = (1 << 0),
MSCRT_MagicFlag_DYNSTALKING = (1 << 1),
MSCRT_MagicFlag_EHNOEXCEPT = (1 << 2)
};
typedef U32 MSCRT_Flags;
enum
{
MSCRT_Flag_SynchronousExceptionOnly = (1 << 0),
MSCRT_Flag_UNKNOWN = (1 << 1),
MSCRT_Flag_StopUnwind = (1 << 2), // When set unwinding can't continue.
};
enum
{
MSCRT_CatchableType_IsSimpleType = (1 << 0),
MSCRT_CatchableType_ByRefOnly = (1 << 1),
MSCRT_CatchableType_HasVirtualBase = (1 << 2), // type is a class with virtual base
MSCRT_CatchableType_IsWinRTHandle = (1 << 3), // type is a WinRT handle
MSCRT_CatchableType_IsStdBadAlloc = (1 << 4) // type is a std::bad_alloc
};
enum
{
MSCRT_ThrowInfo_IsConst = (1 << 0),
MSCRT_ThrowInfo_IsVolatile = (1 << 1),
MSCRT_ThrowInfo_IsUnaligned = (1 << 2),
MSCRT_ThrowInfo_IsPure = (1 << 3), // thrown object is from pure module
MSCRT_ThrowInfo_IsWinRT = (1 << 4) // thrown object is a WinRT exception
};
typedef U32 MSCRT_EhHandlerTypeFlags;
enum
{
MSCRT_EhHandlerTypeFlag_IsConst = (1 << 0), // referenced type is 'const'
MSCRT_EhHandlerTypeFlag_IsVolatile = (1 << 1), // referenced type is 'volatile'
MSCRT_EhHandlerTypeFlag_IsUnaligned = (1 << 2), // referenced type is 'unaligned'
MSCRT_EhHandlerTypeFlag_IsReference = (1 << 3), // catch type is by reference
MSCRT_EhHandlerTypeFlag_IsResumable = (1 << 4), // catch may choose to resume
MSCRT_EhHandlerTypeFlag_IsStdDotDot = (1 << 6), // catch(...)
MSCRT_EhHandlerTypeFlag_IsComplusEH = (1 << 31) // is handling EH in complus
};
typedef struct MSCRT_FuncInfo32
{
U32 magic;
U32 max_state;
U32 unwind_map_voff;
U32 try_block_map_count;
U32 try_block_map_voff;
U32 ip_map_count;
U32 ip_map_voff;
U32 frame_offset_unwind_helper;
U32 es_type_list_voff; // llvm emits zero, not sure what this supposed to be
MSCRT_Flags eh_flags;
} MSCRT_FuncInfo32;
typedef struct MSCRT_IPState32
{
U32 ip;
S32 state;
} MSCRT_IPState32;
typedef struct MSCRT_UnwindMap32
{
S32 next_state;
U32 action_virt_off;
} MSCRT_UnwindMap32;
typedef struct MSCRT_EhHandlerType32
{
MSCRT_EhHandlerTypeFlags adjectives;
U32 descriptor_voff;
U32 catch_obj_frame_offset;
U32 catch_handler_voff;
U32 fp_distance;
} MSCRT_EhHandlerType32;
typedef struct MSCRT_TryMapBlock32
{
S32 try_low;
S32 try_high;
S32 catch_high;
S32 catch_handlers_count;
U32 catch_handlers_voff;
} MSCRT_TryMapBlock32;
typedef struct MSCRT_ExceptionSpecTypeList32
{
S32 count;
U32 handlers_voff;
} MSCRT_ExceptionSpecTypeList32;
typedef struct MSCRT_TryMapBlock
{
S32 try_low;
S32 try_high;
S32 catch_high;
S32 catch_handlers_count;
MSCRT_EhHandlerType32 *catch_handlers;
} MSCRT_TryMapBlock;
typedef struct MSCRT_ExceptionSpecTypeList
{
S32 count;
MSCRT_EhHandlerType32 *handlers;
} MSCRT_ExceptionSpecTypeList;
typedef struct MSCRT_FuncInfo
{
U32 magic;
U32 max_state;
MSCRT_UnwindMap32 *unwind_map;
U32 try_block_map_count;
MSCRT_TryMapBlock *try_block_map;
U32 ip_map_count;
MSCRT_IPState32 *ip_map;
U32 frame_offset_unwind_helper;
MSCRT_ExceptionSpecTypeList es_type_list;
MSCRT_Flags eh_flags;
} MSCRT_FuncInfo;
////////////////////////////////
// C++ Exceptions V4
typedef U8 MSCRT_FuncInfoV4Flags;
enum
{
MSCRT_FuncInfoV4Flag_IsCatch = (1 << 0), // catch funclet
MSCRT_FuncInfoV4Flag_IsSeparated = (1 << 1), // func has separate code segment
MSCRT_FuncInfoV4Flag_IsBBT = (1 << 2), // flags set by basic block trasformations
MSCRT_FuncInfoV4Flag_UnwindMap = (1 << 3), // unwind map is present
MSCRT_FuncInfoV4Flag_TryBlockMap = (1 << 4), // try block map is present
MSCRT_FuncInfoV4Flag_EHs = (1 << 5),
MSCRT_FuncInfoV4Flag_NoExcept = (1 << 6),
MSCRT_FuncInfoV4Flag_Reserved = (1 << 7)
};
typedef U32 MSCRT_UnwindMapV4Type;
enum
{
MSCRT_UnwindMapV4Type_NoUW = 0, // no unwind action associated with this state
MSCRT_UnwindMapV4Type_DtorWithObj = 1, // dtor with an object offset
MSCRT_UnwindMapV4Type_DtorWithPtrToObj = 2, // dtor with an offset that contains a pointer to the object to be destroyed
MSCRT_UnwindMapV4Type_VOFF = 3, // dtor that has a direct function that is called that knows where the object is and can perform more exotic destruction
};
enum
{
MSCRT_ContV4Type_NoMetadata = 1, // no metadata use whatever funclet returns
MSCRT_ContV4Type_OneFuncRelAddr = 2,
MSCRT_ContV4Type_TwoFuncRelAddr = 3
};
#define MSCRT__EH_HANDLER_V4_FLAGS_EXTRACT_CONT_TYPE(x) (((x) & MSCRT_EhHandlerV4Flag_ContVOffMask) >> MSVC_CRTHandlerV4Flag_ContVOffShift)
typedef U8 MSCRT_EhHandlerV4Flags;
enum
{
MSCRT_EhHandlerV4Flag_Adjectives = (1 << 0), // set if adjectives are present
MSCRT_EhHandlerV4Flag_DispType = (1 << 1), // set if type descriptors are present
MSCRT_EhHandlerV4Flag_DispCatchObj = (1 << 2), // set if catch object object is present
MSCRT_EhHandlerV4Flag_ContIsVOff = (1 << 3), // continuantion addresses are VOFF rather than function relative
MSCRT_EhHandlerV4Flag_ContVOffMask = 0x30,
MSCRT_EhHandlerV4Flag_ContVOffShift = 4,
};
typedef struct MSCRT_EhHandlerTypeV4
{
MSCRT_EhHandlerV4Flags flags;
MSCRT_EhHandlerTypeFlags adjectives;
S32 type_voff;
U32 catch_obj_voff;
S32 catch_code_voff;
U64 catch_funclet_cont_addr[2];
U32 catch_funclet_cont_addr_count;
} MSCRT_EhHandlerTypeV4;
typedef struct MSCRT_EhHandlerTypeV4Array
{
U64 count;
MSCRT_EhHandlerTypeV4 *v;
} MSCRT_EhHandlerTypeV4Array;
typedef struct MSCRT_TryBlockMap32V4
{
U32 try_low;
U32 try_high;
U32 catch_high;
S32 handler_array_voff;
} MSCRT_TryBlockMap32V4;
typedef struct MSCRT_IP2State32V4
{
U32 count;
U32 *voffs;
S32 *states;
} MSCRT_IP2State32V4;
typedef struct MSCRT_SepIPState32V4
{
S32 func_start_voff;
S32 ip_map_voff;
} MSCRT_SepIPState32V4;
typedef struct MSCRT_FuncInfo32V4
{
MSCRT_FuncInfoV4Flags header;
U32 bbt_flags;
S32 unwind_map_voff;
S32 try_block_map_voff;
S32 ip_to_state_map_voff;
S32 wrt_frame_establisher_voff; // used only in catch funclets
} MSCRT_FuncInfo32V4;
typedef struct MSCRT_UnwindEntryV4
{
MSCRT_UnwindMapV4Type type;
S32 action;
U32 object;
U32 next_off;
} MSCRT_UnwindEntryV4;
typedef struct MSCRT_UnwindMapV4
{
U32 count;
MSCRT_UnwindEntryV4 *v;
} MSCRT_UnwindMapV4;
typedef struct MSCRT_TryBlockMapV4
{
U32 try_low;
U32 try_high;
U32 catch_high;
MSCRT_EhHandlerTypeV4Array handlers;
} MSCRT_TryBlockMapV4;
typedef struct MSCRT_TryBlockMapV4Array
{
U64 count;
MSCRT_TryBlockMapV4 *v;
} MSCRT_TryBlockMapV4Array;
typedef struct MSCRT_ParsedFuncInfoV4
{
MSCRT_FuncInfoV4Flags header;
U32 bbt_flags;
MSCRT_UnwindMapV4 unwind_map;
MSCRT_TryBlockMapV4Array try_block_map;
MSCRT_IP2State32V4 ip2state_map;
} MSCRT_ParsedFuncInfoV4;
//- Entry Point
internal String8 msvcrt_ctr_entry_from_user_entry(String8 user_entry_point);
//- Delay Load Helper
internal String8 mscrt_delay_load_helper_name_from_machine(COFF_MachineType machine);
//- Exception info < v4
internal U64 mscrt_parse_func_info(Arena *arena, String8 raw_data, U64 section_count, COFF_SectionHeader *sections, U64 off, MSCRT_FuncInfo *func_info);
//- Exception info v4
internal U64 mscrt_parse_handler_type_v4 (String8 raw_data, U64 offset, U64 func_voff, MSCRT_EhHandlerTypeV4 *handler);
internal U64 mscrt_parse_unwind_v4_entry (String8 raw_data, U64 offset, MSCRT_UnwindEntryV4 *entry_out);
internal U64 mscrt_parse_handler_type_v4_array (Arena *arena, String8 raw_data, U64 offset, U64 func_voff, MSCRT_EhHandlerTypeV4Array *array_out);
internal U64 mscrt_parse_unwind_map_v4 (Arena *arena, String8 raw_data, U64 off, MSCRT_UnwindMapV4 *map_out);
internal U64 mscrt_parse_try_block_map_array_v4(Arena *arena, String8 raw_data, U64 off, U64 section_count, COFF_SectionHeader *sections, U64 func_voff, MSCRT_TryBlockMapV4Array *map_out);
internal U64 mscrt_parse_ip2state_map_v4 (Arena *arena, String8 raw_data, U64 off, U64 func_voff, MSCRT_IP2State32V4 *ip2state_map_out);
internal U64 mscrt_parse_func_info_v4 (Arena *arena, String8 raw_data, U64 section_count, COFF_SectionHeader *sections, U64 off, U64 func_voff, MSCRT_ParsedFuncInfoV4 *func_info_out);
internal Rng1U64List
mscrt_catch_blocks_from_data_x8664(Arena *arena,
String8 raw_data,
U64 section_count,
COFF_SectionHeader *sections,
Rng1U64 except_frange);
////////////////////////////////
//~ rjf: Enum -> String
internal String8 mscrt_string_from_eh_adjectives(Arena *arena, MSCRT_EhHandlerTypeFlags adjectives);
#endif // MSVC_CRT