Files
raddebugger/src/linker/lnk_debug_info.h
T
Nikita SmithandRyan Fleury afd454b41f fix DBI SC image-section range mapping
Log and skip section contributions that fail to map into the linked image.
Keep a file-range-to-section-number map so compact file ranges produce the
correct DBI section numbers.
2026-07-27 14:47:12 -07:00

263 lines
8.1 KiB
C

// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#pragma once
////////////////////////////////
// RRT
global read_only String8 g_rrt_magic = str8_lit_comp("RAD-TYPE-SERVER\0");
global read_only U64 g_rrt_version = 2;
typedef struct LNK_RRT
{
String8 path;
String8 type_data_raw;
union {
String8 type_hashes;
U64 **type_hashes_unpacked[CV_TypeIndexSource_COUNT];
};
Rng1U64 type_data_ranges[CV_TypeIndexSource_COUNT];
String8 type_data [CV_TypeIndexSource_COUNT];
Rng1U64 ti_ranges [CV_TypeIndexSource_COUNT];
U64 obj_count;
U64 *obj_leaf_counts;
U64 *obj_time_stamps;
Rng1U64 *obj_ti_ranges;
CV_TypeIndex **obj_ti_maps;
String8Array obj_paths;
Rng1U64 *obj_pch_ti_ranges;
U32 *obj_pch_indices;
} LNK_RRT;
typedef struct
{
U64 count;
LNK_RRT *v;
} LNK_RRT_Array;
////////////////////////////////
// CodeView
typedef enum
{
LNK_TypeServerKind_Null,
LNK_TypeServerKind_PDB,
LNK_TypeServerKind_RRT,
} LNK_TypeServerKind;
typedef struct
{
CV_TypeServerInfo ts_info;
U64 ts_idx;
LNK_TypeServerKind ts_kind;
String8 ts_path;
U64List obj_indices;
LNK_RRT *rrt;
CV_DebugH *debug_h;
} LNK_TypeServer;
typedef struct LNK_TypeServerNode { LNK_TypeServer v; struct LNK_TypeServerNode *next; } LNK_TypeServerNode;
typedef struct LNK_TypeServerList { U64 count; LNK_TypeServerNode *first, *last; } LNK_TypeServerList;
typedef struct LNK_TypeServerArray { U64 count; LNK_TypeServer *v; } LNK_TypeServerArray;
typedef struct LNK_SymbolInput
{
U64 obj_idx;
String8 raw_symbols;
} LNK_SymbolInput;
typedef struct
{
LNK_Config *config;
U64 obj_count;
B32 is_stripped;
LNK_RRT_Array rrt_input;
U64 count;
LNK_Obj **obj_arr;
CV_DebugS *debug_s_arr;
CV_DebugT *debug_t_arr;
CV_DebugH *debug_h_arr;
U64 *obj_to_ts;
String8List *debug_s_list_arr;
U32Array int_obj_indices;
U32Array ext_obj_indices;
U32Array debug_p_indices;
U32Array type_server_indices;
Rng1U64 ts_obj_range;
LNK_TypeServerArray ts_arr;
B32 *is_type_server_discarded; // [ts_arr.count]
CV_TypeIndex min_type_indices[CV_TypeIndexSource_COUNT];
U64 symbol_input_count;
LNK_SymbolInput *symbol_inputs; // [symbol_input_count]
Rng1U64 *symbol_input_ranges; // [worker_count]
} LNK_CodeViewInput;
typedef struct
{
LNK_CodeViewInput *input;
String8Array *raw_types; // [obj_count]
CV_DebugT *out_types; // [obj_count]
} LNK_ParseCvTypes;
////////////////////////////////
// Type Merging
typedef struct { U32 obj_idx; U32 leaf_idx; } LNK_LeafRef;
typedef struct { U64 count; LNK_LeafRef **v; } LNK_LeafRefArray;
typedef struct
{
U64 cap;
LNK_LeafRef **bucket_arr;
} LNK_LeafHashTable;
typedef struct LNK_LeafRange
{
struct LNK_LeafRange *next;
Rng1U64 range;
CV_DebugT *debug_t;
} LNK_LeafRange;
typedef struct { U64 count; LNK_LeafRange *first, *last; } LNK_LeafRangeList;
typedef enum
{
LNK_MergeTypeFlag_BuildObjTiMap = (1 << 0),
LNK_MergeTypeFlag_SkipSymbolTypeFixup = (1 << 1),
LNK_MergeTypeFlag_ExportHashes = (1 << 2),
} LNK_MergeTypeFlags;
typedef struct
{
CV_TypeIndex min_type_indices[CV_TypeIndexSource_COUNT];
U64 count [CV_TypeIndexSource_COUNT];
U8 **v [CV_TypeIndexSource_COUNT];
// @type_server
CV_TypeIndex **obj_ti_maps;
U64 *hashes[CV_TypeIndexSource_COUNT];
} LNK_MergedTypes;
typedef struct
{
LNK_CodeViewInput *input;
CV_DebugS *debug_s_arr;
LNK_LeafHashTable leaf_ht_arr[CV_TypeIndexSource_COUNT];
Arena **fixed_arenas;
CV_TypeIndexSource ti_source;
U32Array indices;
Rng1U64 *ranges;
// count types per source
LNK_LeafRangeList *leaf_ranges_per_task;
U64 per_source_count[CV_TypeIndexSource_COUNT];
// extract present buckets
U64 *counts [CV_TypeIndexSource_COUNT];
U64 *offsets[CV_TypeIndexSource_COUNT];
// leaf ref radix sort
U64 obj_idx_bit_count_0;
U64 obj_idx_bit_count_1;
U64 obj_idx_bit_count_2;
U64 counts_max;
U32 **counts_arr;
LNK_LeafRef **dst;
LNK_LeafRef **src;
U64 pass_idx;
// assign type indices
U64 assigned_type_caps [CV_TypeIndexSource_COUNT];
CV_TypeIndex *assigned_type_hts [CV_TypeIndexSource_COUNT];
CV_TypeIndex min_type_indices [CV_TypeIndexSource_COUNT];
LNK_LeafRefArray unique_leaf_refs_arr[CV_TypeIndexSource_COUNT];
U64 *obj_ti_map_counts;
U64 *obj_ti_map_offsets;
CV_TypeIndex *obj_ti_batch;
U64 pop_obj_idx;
Rng1U64 *pop_range;
LNK_MergedTypes result;
} LNK_MergeTypes;
////////////////////////////////
// PDB
typedef enum
{
LNK_PDB_BuilderFlag_All = 0,
LNK_PDB_BuilderFlag_Tpi = (1<<0),
LNK_PDB_BuilderFlag_Ipi = (1<<1),
LNK_PDB_BuilderFlag_Modules = (1<<2),
LNK_PDB_BuilderFlag_SC = (1<<4),
LNK_PDB_BuilderFlag_NATVIS = (1<<5),
} LNK_PDB_BuilderFlags;
typedef struct
{
String8 image_data;
LNK_SymbolTable *symtab;
LNK_CodeViewInput *cv;
PDB_Context *pdb;
CV_StringHashTable string_ht;
PDB_DbiModule **mod_arr; // [obj_count]
U32Array *obj_indices; // [obj_count]
U64 symbol_count;
// push DBI SC Map
PE_BinInfo pe;
COFF_SectionHeader **image_section_table;
U64 image_section_table_count;
Rng1U64Array image_section_virt_ranges;
Rng1U64Array image_section_file_ranges;
U64 *image_section_file_section_numbers;
PDB_DbiSCList *sc_list; // [obj_count]
} LNK_BuildPdb;
typedef struct
{
U64 leaf_count;
U8 **leaf_arr;
Rng1U64 *ranges;
U64 hash_length;
B32 make_map;
TP_Arena *map_arena;
String8List *maps;
} LNK_TypeNameReplacer;
////////////////////////////////
// RRT
internal String8List lnk_string_list_from_rrt(Arena *arena, LNK_RRT *rrt);
internal B32 lnk_rrt_from_string (Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_out);
////////////////////////////////
// CodeView
internal LNK_CodeViewInput lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config, U64 objs_count, LNK_Obj **objs, LNK_RRT_Array rrt_input);
internal int lnk_leaf_ref_compare (LNK_LeafRef a, LNK_LeafRef b);
internal int lnk_leaf_ref_is_before (void *raw_a, void *raw_b);
internal B32 lnk_match_leaf_ref (LNK_CodeViewInput *input, LNK_LeafRef a, LNK_LeafRef b);
internal U64 lnk_hash_cv_leaf (LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInfoList ti_info_list, B32 discard_cycles);
internal void lnk_hash_cv_leaf_deep (Arena *arena, LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInfoList ti_info_list);
internal LNK_LeafRef * lnk_leaf_hash_table_insert_or_update(LNK_LeafHashTable *leaf_ht, LNK_CodeViewInput *input, CV_DebugH *hashes, U64 hash, LNK_LeafRef *new_bucket);
internal LNK_LeafRef * lnk_leaf_hash_table_search (LNK_LeafHashTable *ht, LNK_CodeViewInput *input, LNK_LeafRef leaf_ref);
internal LNK_MergedTypes lnk_merge_types (TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input, LNK_MergeTypeFlags merge_flags);
internal void lnk_replace_type_names_with_hashes (TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, LNK_TypeNameHashMode mode, U64 hash_length, String8 map_name);
////////////////////////////////
// PDB
internal String8List lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config *config, LNK_SymbolTable *symtab, LNK_CodeViewInput *cv, LNK_MergedTypes cv_types, LNK_PDB_BuilderFlags builder_flags);