WIP change symbol extraction approach

This commit is contained in:
Nikita Smith
2026-04-06 12:04:31 -07:00
parent f57b149939
commit e0c6df710f
12 changed files with 921 additions and 994 deletions
+1
View File
@@ -448,6 +448,7 @@ C_LINKAGE void __asan_unpoison_memory_region(void const volatile *addr, size_t s
#endif
#define TryRead(func__, cursor__, label__) do { U64 size__ = (func__); if (size__ == 0) { Assert(0 && "failed read"); goto label__; } cursor__ += size__; } while (0)
#define TryReadBreak(func__, cursor__) { U64 size__ = (func__); if (size__ == 0) { Assert(0 && "failed read"); break; } cursor__ += size__; }
////////////////////////////////
//~ rjf: Base Types
+10
View File
@@ -24,6 +24,16 @@ void_node_concat_atomic(VoidNode **head, VoidNode *node)
node->next = ins_atomic_ptr_eval_assign(head, node);
}
internal VoidNode *
void_list_push(Arena *arena, VoidList *list, void *v)
{
VoidNode *n = push_array(arena, VoidNode, 1);
n->v = v;
SLLQueuePush(list->first, list->last, n);
list->count += 1;
return n;
}
internal void
u64_list_push_node(U64List *list, U64Node *n)
{
+8 -41
View File
@@ -3,49 +3,16 @@
#pragma once
typedef struct VoidNode
{
struct VoidNode *next;
void *v;
} VoidNode;
typedef struct VoidNode { void *v; struct VoidNode *next; } VoidNode;
typedef struct U32Node { U32 data; struct U32Node *next; } U32Node;
typedef struct U64Node { U64 data; struct U64Node *next; } U64Node;
typedef struct S64Node { S64 v; struct S64Node *next; } S64Node;
typedef struct U32Node
{
struct U32Node *next;
U32 data;
} U32Node;
typedef struct VoidList { U64 count; VoidNode *first, *last; } VoidList;
typedef struct U64List { U64 count; U64Node *first, *last; } U64List;
typedef struct S64List { U64 count; S64Node *first, *last; } S64List;
typedef struct U64Node
{
struct U64Node *next;
U64 data;
} U64Node;
typedef struct U64List
{
U64 count;
U64Node *first;
U64Node *last;
} U64List;
typedef struct S64Node
{
S64 v;
struct S64Node *next;
} S64Node;
typedef struct S64List
{
U64 count;
S64Node *first;
S64Node *last;
} S64List;
typedef struct S64Array
{
U64 count;
S64 *v;
} S64Array;
typedef struct S64Array { U64 count; S64 *v; } S64Array;
////////////////////////////////
+155 -118
View File
@@ -241,6 +241,67 @@ cv_data_from_symbol(Arena *arena, CV_Symbol *symbol, U64 align)
return result;
}
internal U64
cv_read_symbol(String8 raw_data, U64 off, U64 align, CV_Symbol *symbol_out)
{
Assert(raw_data.size >= sizeof(CV_SymbolHeader));
U8 *symbol_ptr = raw_data.str + off;
CV_SymbolHeader header = { .v = memory_read32(symbol_ptr) };
Assert(header.size >= sizeof(CV_SymKind));
Assert(sizeof(CV_SymSize) + header.size <= raw_data.size);
symbol_out->kind = header.kind;
symbol_out->data = str8(symbol_ptr + sizeof(CV_SymbolHeader), header.size - sizeof(CV_SymKind));
U64 symbol_size = AlignPow2(sizeof(CV_SymbolHeader) + symbol_out->data.size, align);
Assert(symbol_size <= raw_data.size);
return symbol_size;
}
internal U8 *
cv_ptr_from_symbol(CV_Symbol symbol)
{
return symbol.data.str - sizeof(CV_SymbolHeader);
}
internal CV_SymKind *
cv_kind_ptr_from_symbol(CV_Symbol symbol)
{
return &((CV_SymbolHeader *)cv_ptr_from_symbol(symbol))->kind;
}
internal CV_Symbol
cv_symbol_from_ptr(U8 *ptr)
{
CV_Symbol symbol = {0};
cv_read_symbol(str8(ptr, max_U64), 0, 1, &symbol);
return symbol;
}
internal String8
cv_raw_from_symbol(void *ptr)
{
CV_SymbolHeader *header = ptr;
return str8(ptr, header->size + sizeof(header->size));
}
internal B32
cv_symbol_match(CV_Symbol a, CV_Symbol b)
{
B32 is_match = 0;
CV_SymbolHeader *a_ptr = (CV_SymbolHeader *)cv_ptr_from_symbol(a);
CV_SymbolHeader *b_ptr = (CV_SymbolHeader *)cv_ptr_from_symbol(b);
if (a_ptr->size == b_ptr->size) {
is_match = MemoryMatch(a_ptr + sizeof(CV_SymSize), b_ptr + sizeof(CV_SymSize), a_ptr->size);
}
return is_match;
}
internal String8
cv_make_symbol(Arena *arena, CV_SymKind kind, String8 data)
{
@@ -949,144 +1010,58 @@ cv_pack_string_hash_table(Arena *arena, TP_Context *tp, CV_StringHashTable strin
////////////////////////////////
//~ Symbol Deduper
internal int
cv_symbol_deduper_is_before(void *raw_a, void *raw_b)
internal void *
cv_symbol_deduper_insert_or_update(void **buckets, U64 bucket_cap, U64 hash, void *symbol_ptr)
{
return raw_a < raw_b;
}
internal CV_SymbolNode **
cv_symbol_deduper_insert_or_update(CV_SymbolNode ***buckets, U64 cap, U64 hash, CV_SymbolNode **new_bucket)
{
CV_SymbolNode **result = 0;
B32 is_inserted_or_updated = 0;
U64 best_idx = hash % cap;
U64 idx = best_idx;
CV_Symbol symbol = cv_symbol_from_ptr(symbol_ptr);
U8 *result = 0;
B32 is_inserted_or_updated = 0;
U64 best_idx = hash % bucket_cap;
U64 bucket_idx = best_idx;
do {
retry:;
CV_SymbolNode **curr_bucket = buckets[idx];
void *curr_ptr = buckets + bucket_idx;
Assert(curr_ptr != symbol_ptr);
Assert(curr_bucket != new_bucket);
if (curr_bucket == 0) {
CV_SymbolNode **compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket);
if (compare_bucket == curr_bucket) {
if (curr_ptr == 0) {
U8 *cmp = ins_atomic_ptr_eval_cond_assign(&buckets[bucket_idx], symbol_ptr, curr_ptr);
if (cmp == curr_ptr) {
// success, bucket was inserted
is_inserted_or_updated = 1;
break;
}
// another thread took the bucket...
goto retry;
} else if ((*curr_bucket)->data.kind == (*new_bucket)->data.kind &&
(*curr_bucket)->data.data.size == (*new_bucket)->data.data.size &&
MemoryMatch((*curr_bucket)->data.data.str, (*new_bucket)->data.data.str, (*new_bucket)->data.data.size)) {
if (cv_symbol_deduper_is_before(curr_bucket, new_bucket)) {
result = new_bucket;
} else {
CV_Symbol curr = cv_symbol_from_ptr(curr_ptr);
is_inserted_or_updated = 1;
if (cv_symbol_match(curr, symbol)) {
if (curr_ptr < symbol_ptr) {
// do not update, more recent symbol is in the bucket
result = symbol_ptr;
is_inserted_or_updated = 1;
break;
}
// don't need to update, more recent leaf is in the bucket
break;
void *cmp = ins_atomic_ptr_eval_cond_assign(&buckets[bucket_idx], symbol_ptr, curr_ptr);
if (cmp == curr_ptr) {
result = cmp;
is_inserted_or_updated = 1;
break;
}
// another thread took the bucket...
goto retry;
}
CV_SymbolNode **compare_bucket = ins_atomic_ptr_eval_cond_assign(&buckets[idx], new_bucket, curr_bucket);
if (compare_bucket == curr_bucket) {
result = compare_bucket;
is_inserted_or_updated = 1;
break;
}
// another thread took the bucket...
goto retry;
}
// advance
idx = (idx + 1) % cap;
} while (idx != best_idx);
bucket_idx = (bucket_idx + 1) == bucket_cap ? 0 : bucket_idx + 1;
} while (bucket_idx != best_idx);
Assert(is_inserted_or_updated);
return result;
}
internal
THREAD_POOL_TASK_FUNC(cv_symbol_deduper_insert_task)
{
ProfBeginFunction();
CV_SymbolDeduperTask *task = raw_task;
Rng1U64 range = task->ranges[task_id];
for (U64 symbol_idx = range.min; symbol_idx < range.max; ++symbol_idx) {
CV_SymbolNode **symbol_node = &task->symbols[symbol_idx];
U64 hash = hash_from_cv_symbol(&(*symbol_node)->data);
cv_symbol_deduper_insert_or_update(task->u.buckets, task->cap, hash, symbol_node);
}
ProfEnd();
}
internal
THREAD_POOL_TASK_FUNC(cv_symbol_deduper_deref_buckets_task)
{
ProfBeginFunction();
CV_SymbolDeduperTask *task = raw_task;
Rng1U64 range = task->ranges[task_id];
for (U64 bucket_idx = range.min; bucket_idx < range.max; ++bucket_idx) {
CV_SymbolNode **bucket = task->u.buckets[bucket_idx];
if (bucket) {
task->u.deref_buckets[bucket_idx] = *bucket;
}
}
ProfEnd();
}
internal void
cv_dedup_symbol_ptr_array(TP_Context *tp, CV_SymbolPtrArray *symbols)
{
ProfBeginDynamic("Dedup Symbols [Count %llu]", symbols->count);
Temp scratch = scratch_begin(0, 0);
ProfBegin("Setup Task");
CV_SymbolDeduperTask task = {0};
task.symbols = symbols->v;
task.cap = (U64)((F64)symbols->count * 1.3);
task.u.buckets = push_array(scratch.arena, CV_SymbolNode **, task.cap);
ProfEnd();
ProfBegin("Dedup");
task.ranges = tp_divide_work(scratch.arena, symbols->count, tp->worker_count);
tp_for_parallel(tp, 0, tp->worker_count, cv_symbol_deduper_insert_task, &task);
ProfEnd();
ProfBegin("Deref Buckets");
task.ranges = tp_divide_work(scratch.arena, task.cap, tp->worker_count);
tp_for_parallel(tp, 0, tp->worker_count, cv_symbol_deduper_deref_buckets_task, &task);
ProfEnd();
ProfBegin("Copy Extant Buckets");
U64 unique_symbol_count = 0;
for (U64 bucket_idx = 0; bucket_idx < task.cap; ++bucket_idx) {
CV_SymbolNode *bucket = task.u.deref_buckets[bucket_idx];
if (bucket) {
symbols->v[unique_symbol_count++] = bucket;
}
}
ProfEnd();
Assert(unique_symbol_count <= symbols->count);
symbols->count = unique_symbol_count;
ProfBeginDynamic("Sort [Count %llu]", symbols->count);
radsort(symbols->v, symbols->count, cv_symbol_deduper_is_before);
ProfEnd();
scratch_end(scratch);
ProfEnd();
}
////////////////////////////////
//~ .debug$T helpers
@@ -1528,6 +1503,68 @@ cv_patch_symbol_tree_offsets(CV_SymbolList list, U64 base_offset, U64 align)
return serial_size;
}
internal U64
cv_patch_symbol_tree_offsets_new(String8List raw_symbols, U64 base_offset, U64 align)
{
Temp scratch = scratch_begin(0, 0);
struct Stack { struct Stack *next; CV_Symbol symbol; U64 offset; };
struct Stack *stack = 0, *free_list = 0;
U64 symbol_offset = safe_cast_u32(base_offset);
for EachNode(n, String8Node, raw_symbols.first) {
for (U64 cursor = 0, depth = 0; cursor + sizeof(CV_SymbolHeader) <= n->string.size; ) {
CV_Symbol symbol = {0};
U64 read_size = cv_read_symbol(n->string, cursor, CV_SymbolAlign, &symbol);
if (read_size == 0) { break; }
cursor += read_size;
if (symbol.kind == CV_SymKind_SKIP) { continue; }
if (cv_is_scope_symbol(symbol.kind)) {
// NOTE: We don't patch 'next' offset in PROC symbols because
// it's not used by visual studio and MSVC leaves the offsets
// zeroed. LLD is on the same page.
Assert(symbol.data.size >= sizeof(U32)*2);
// patch parent symbol offset
if (stack) {
memory_write32(symbol.data.str, stack->offset);
}
// reuse/alloc frame
struct Stack *frame = free_list;
if (frame) { SLLStackPop(free_list); }
else { frame = push_array_no_zero(scratch.arena, struct Stack, 1); }
// push frame to the stack
frame->symbol = symbol;
frame->offset = symbol_offset;
SLLStackPush(stack, frame);
depth += 1;
} else if (cv_is_end_symbol(symbol.kind)) {
// patch symbol end
U32 *end_off_ptr = (U32 *)stack->symbol.data.str + /* skip parent off */ 1;
memory_write32(end_off_ptr, symbol_offset);
// recycle frame
struct Stack *free_frame = stack;
SLLStackPop(stack);
SLLStackPush(free_list, free_frame);
if (depth == 0) { Assert(0 && "malformed symbol stream"); goto next_block; }
depth -= 1;
}
// advance tree offset
symbol_offset += cv_size_from_symbol(&symbol, align);
}
next_block:;
}
scratch_end(scratch);
return symbol_offset - base_offset;
}
// $$FileChksms
internal void
+13 -14
View File
@@ -14,10 +14,13 @@ typedef union CV_LeafHeader
U32 v;
} CV_LeafHeader;
typedef struct CV_SymbolHeader
typedef union CV_SymbolHeader
{
CV_SymSize size;
CV_SymKind kind;
struct {
CV_SymSize size;
CV_SymKind kind;
};
U32 v;
} CV_SymbolHeader;
////////////////////////////////
@@ -337,17 +340,6 @@ typedef struct CV_StringHashTableResult
////////////////////////////////
//~ Task Contexts
typedef struct
{
U64 cap;
union {
CV_SymbolNode ***buckets;
CV_SymbolNode **deref_buckets;
} u;
Rng1U64 *ranges;
CV_SymbolNode **symbols;
} CV_SymbolDeduperTask;
typedef struct
{
CV_SymbolList *list_arr;
@@ -398,6 +390,13 @@ internal U64 cv_size_from_symbol(CV_Symbol *symbol, U64 align);
internal U64 cv_write_symbol(U8 *buffer, U64 buffer_cursor, U64 buffer_size, CV_Symbol *symbol, U64 align);
internal String8 cv_data_from_symbol(Arena *arena, CV_Symbol *symbol, U64 align);
internal U64 cv_read_symbol(String8 raw_data, U64 off, U64 align, CV_Symbol *symbol_out);
internal U8 * cv_ptr_from_symbol(CV_Symbol symbol);
internal CV_SymKind * cv_kind_ptr_from_symbol(CV_Symbol symbol);
internal CV_Symbol cv_symbol_from_ptr(U8 *ptr);
internal String8 cv_raw_from_symbol(void *ptr);
internal B32 cv_symbol_match(CV_Symbol a, CV_Symbol b);
internal String8 cv_make_symbol(Arena *arena, CV_SymKind kind, String8 data);
internal String8 cv_make_obj_name(Arena *arena, String8 obj_path, U32 sig);
internal String8 cv_make_comp3(Arena *arena, CV_Compile3Flags flags, CV_Language lang, CV_Arch arch, U16 ver_fe_major, U16 ver_fe_minor, U16 ver_fe_build, U16 ver_feqfe, U16 ver_major, U16 ver_minor, U16 ver_build, U16 ver_qfe, String8 version_string);
+10 -22
View File
@@ -5144,8 +5144,8 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
//
// CodeView
//
LNK_CodeViewInput input = lnk_make_code_view_input(tp, arena, config->io_flags, config->lib_dir_list, config->alt_pch_dirs, debug_info_objs_count, debug_info_objs);
LNK_MergedTypes merged_types = lnk_merge_types(tp, arena, &input);
LNK_CodeViewInput cv = lnk_make_code_view_input(tp, arena, config->io_flags, config->lib_dir_list, config->alt_pch_dirs, debug_info_objs_count, debug_info_objs);
LNK_MergedTypes cv_types = lnk_merge_types(tp, arena, &cv);
//
// RDI
@@ -5161,11 +5161,11 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
image_ctx.image_data,
debug_info_objs_count,
debug_info_objs,
input.debug_s_arr,
input.symbol_input_count,
input.symbol_inputs,
input.parsed_symbols,
merged_types);
cv.debug_s_arr,
cv.symbol_input_count,
cv.symbol_inputs,
(CV_SymbolListArray[]){0},
cv_types);
lnk_write_data_list_to_file_path(config->rad_debug_name, config->temp_rad_debug_name, rdi_data);
@@ -5183,26 +5183,14 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
if (config->pdb_hash_type_names != LNK_TypeNameHashMode_Null && config->pdb_hash_type_names != LNK_TypeNameHashMode_None) {
lnk_replace_type_names_with_hashes(tp,
arena,
merged_types.count[CV_TypeIndexSource_TPI],
merged_types.v [CV_TypeIndexSource_TPI],
cv_types.count[CV_TypeIndexSource_TPI],
cv_types.v [CV_TypeIndexSource_TPI],
config->pdb_hash_type_names,
config->pdb_hash_type_name_length,
config->pdb_hash_type_name_map);
}
String8List pdb_data = lnk_build_pdb(tp,
arena,
image_ctx.image_data,
config,
symtab,
debug_info_objs_count,
debug_info_objs,
input.debug_s_arr,
input.symbol_input_count,
input.symbol_inputs,
input.parsed_symbols,
merged_types);
String8List pdb_data = lnk_build_pdb(tp, arena, image_ctx.image_data, config, symtab, &cv, cv_types);
lnk_write_data_list_to_file_path(config->pdb_name, config->temp_pdb_name, pdb_data);
lnk_timer_end(LNK_Timer_Pdb);
}
File diff suppressed because it is too large Load Diff
+113 -212
View File
@@ -3,38 +3,8 @@
#pragma once
// --- Symbol Parsing Tasks ----------------------------------------------------
typedef struct
{
LNK_Obj **obj_arr;
String8List *sect_list_arr;
CV_DebugS *debug_s_arr;
} LNK_ParseDebugSTaskData;
typedef struct
{
LNK_Obj **obj_arr;
String8Array *data_arr_arr;
} LNK_CheckDebugTSigTaskData;
typedef struct
{
LNK_Obj **obj_arr;
String8Array *data_arr_arr;
CV_DebugT *debug_t_arr;
} LNK_ParseDebugTTaskData;
// --- Code View Input ---------------------------------------------------------
typedef struct LNK_SymbolInput
{
U64 obj_idx;
CV_DebugS *debug_s;
CV_SymbolList *symbol_list;
String8 raw_symbols;
} LNK_SymbolInput;
typedef struct
{
CV_TypeServerInfo ts_info;
@@ -43,8 +13,71 @@ typedef struct
U64List obj_indices;
} LNK_TypeServer;
typedef struct LNK_TypeServerNode { LNK_TypeServer v; struct LNK_TypeServerNode *next; } LNK_TypeServerNode;
typedef struct LNK_TypeServerList { U64 count; LNK_TypeServerNode *first; LNK_TypeServerNode *last; } LNK_TypeServerList;
typedef struct LNK_TypeServerArray { U64 count; LNK_TypeServer *v; } LNK_TypeServerArray;
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_IO_Flags io_flags;
U64 obj_count;
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;
String8List *debug_p_list_arr;
String8List *debug_t_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;
struct 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;
// --- Leaf Deduping Tasks -----------------------------------------------------
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 struct
{
@@ -53,71 +86,10 @@ typedef struct
U8 **v [CV_TypeIndexSource_COUNT];
} LNK_MergedTypes;
typedef struct
{
LNK_IO_Flags io_flags;
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;
CV_SymbolListArray *parsed_symbols; // [count]
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]
} LNK_CodeViewInput;
// --- Leaf Deduping Tasks -----------------------------------------------------
typedef struct
{
U32 obj_idx;
U32 leaf_idx;
} LNK_LeafRef;
typedef struct LNK_LeafRange
{
struct LNK_LeafRange *next;
Rng1U64 range;
CV_DebugT *debug_t;
} LNK_LeafRange;
typedef struct LNK_LeafRangeList
{
U64 count;
LNK_LeafRange *first;
LNK_LeafRange *last;
} LNK_LeafRangeList;
typedef struct
{
U64 count;
LNK_LeafRef **v;
} LNK_LeafRefArray;
typedef struct
{
U64 cap;
LNK_LeafRef **bucket_arr;
} LNK_LeafHashTable;
typedef struct
{
LNK_CodeViewInput *input;
CV_DebugS *debug_s_arr;
CV_SymbolList *symbol_list_arr;
LNK_LeafHashTable leaf_ht_arr[CV_TypeIndexSource_COUNT];
Arena **fixed_arenas;
CV_TypeIndexSource ti_source;
@@ -151,112 +123,63 @@ typedef struct
LNK_MergedTypes result;
} LNK_MergeTypes;
// --- Code View Processing Trasks ---------------------------------------------
// --- Build PDB ---------------------------------------------
typedef struct
{
String8List *data_list_arr;
} LNK_ProcessedCodeViewC11Data;
String8 image_data;
LNK_SymbolTable *symtab;
LNK_CodeViewInput *cv;
typedef struct
{
String8List *data_list_arr;
String8List *source_file_names_list_arr;
} LNK_ProcessedCodeViewC13Data;
PDB_Context *pdb;
PDB_DbiModule **mod_arr; // [obj_count]
typedef struct
{
LNK_SymbolInput *inputs;
} LNK_ParseCVSymbolsTaskData;
U64 total_symbol_count;
typedef struct
{
U64 symbol_input_count;
CV_SymbolListArray *parsed_symbols;
U64 *serialized_symbol_data_sizes;
// GSI symbol dedup
U64 bucket_cap;
void **buckets; // [bucket_count]
U64 *insert_count; // [worker_count]
LNK_SymbolInput *symbol_inputs;
PDB_DbiModule **mod_arr;
String8List *symbol_data_arr;
CV_SymbolList *gsi_list_arr;
} LNK_ProcessSymDataTaskData;
Rng1U64 *symbol_ranges; // [worker_count]
U64 symbol_count;
void **symbol_arr;
U32 *symbol_hashes; // [symbol_count]
typedef struct
{
CV_DebugS *debug_s_arr;
U64 *proc_ref_counts; // [worker_count]
U64 *proc_ref_sizes; // [worker_count]
U64 *proc_ref_hashes; // [total_proc_ref_count]
U64 *proc_ref_offs; // [worker_count]
String8 proc_refs;
U64 *public_symbol_node_counts; // [worker_count]
U64 *public_symbol_node_offsets; // [worker_count]
CV_SymbolNode *public_symbol_nodes; // [public_symbol_total_count]
CV_SymbolList *public_symbols; // [worker_count]
U32 **public_symbol_hashes; // [worker_count][public_symbol.count]
U64 *symbol_sizes; // [obj_count]
// process C13 data
String8List *source_file_names_list_arr;
U64 string_data_base_offset;
CV_StringHashTable string_ht;
} LNK_ProcessC13DataTask;
typedef struct
{
MSF_Context *msf;
PDB_DbiModule **mod_arr;
CV_DebugS *debug_s_arr;
U64 *serialized_symbol_data_sizes;
CV_SymbolListArray *parsed_symbols;
String8List *globrefs_arr;
U32 *mod_sizes;
} LNK_WriteModuleDataTask;
// build DBI modules
String8List *globrefs_arr; // [obj_count]
U32 *mod_sizes; // [obj_count]
U64 *serialized_symbol_data_sizes; // [obj_count]
typedef struct
{
LNK_Obj **obj_arr;
PDB_DbiModule **mod_arr;
PDB_DbiSectionContribList *sc_list;
String8 image_data;
// push DBI SC Map
PE_BinInfo pe;
COFF_SectionHeader **image_section_table;
U64 image_section_table_count;
Rng1U64Array image_section_file_ranges;
Rng1U64Array image_section_virt_ranges;
} LNK_PushDbiSecContribTaskData;
PDB_DbiSectionContribList *sc_list; // [obj_count]
typedef struct
{
U32Array *hash_arr_arr;
CV_SymbolList *list_arr;
} LNK_HashCVSymbolListTask;
typedef struct
{
U64 *hash_arr;
CV_SymbolNode **arr;
Rng1U64 *range_arr;
} LNK_CvSymbolPtrArrayHasher;
typedef struct
{
LNK_SymbolHashTrieChunkList *chunk_lists;
CV_SymbolList *pub_list_arr;
Rng1U64 *symbol_ranges;
PDB_GsiContext *gsi;
CV_SymbolPtrArray symbols;
U32 *hashes;
} LNK_BuildPublicSymbolsTask;
typedef struct
{
CV_TypeIndex ipi_min_type_index;
CV_DebugT ipi_types;
LNK_SymbolInput *symbol_inputs;
CV_SymbolListArray *parsed_symbols;
} LNK_PostProcessCvSymbolsTask;
typedef struct
{
Rng1U64 *range_arr;
CV_SymbolPtrNode **bucket_arr;
CV_SymbolPtrNode **out_arr;
U64 *out_count_arr;
} LNK_GsiDeduper;
typedef struct
{
Rng1U64 *range_arr;
CV_SymbolPtrNode **bucket_arr;
U64 *symbol_base_arr;
CV_SymbolNode **symbol_arr;
} LNK_GsiUnbucket;
// make public symbols
CV_SymbolList *pub_list_arr;
} LNK_BuildPdb;
typedef struct
{
@@ -350,8 +273,7 @@ typedef struct
CV_DebugS *debug_s_arr;
U64 leaf_arr_count_ipi;
U8 **leaf_arr_ipi;
LNK_SymbolInput *symbol_inputs;
CV_SymbolListArray *parsed_symbols;
LNK_SymbolInput *symbol_inputs;
Rng1U64 ipi_itype_range;
Rng1U64 tpi_itype_range;
RDIB_Type **tpi_itype_map;
@@ -387,11 +309,8 @@ typedef struct
// --- CodeView ----------------------------------------------------------------
internal CV_DebugS * lnk_parse_debug_s_sections(TP_Context *tp, TP_Arena *arena, U64 obj_count, LNK_Obj **obj_arr, String8List *sect_list_arr);
internal CV_DebugT * lnk_parse_debug_t_sections(TP_Context *tp, TP_Arena *arena, U64 obj_count, LNK_Obj **obj_arr, String8List *debug_t_list_arr);
internal LNK_CodeViewInput lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_flags, String8List lib_dir_list, String8List alt_pch_dirs, U64 objs_count, LNK_Obj **objs);
// type merging
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);
@@ -402,7 +321,11 @@ internal LNK_LeafRef * lnk_leaf_hash_table_search (LNK_LeafHashTable
internal LNK_MergedTypes lnk_merge_types (TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input);
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);
// --- RAD Debug info ----------------------------------------------------------
// --- 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);
// --- RDI ---------------------------------------------------------------------
internal U64 lnk_udt_name_hash_table_hash (String8 string);
internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_leaf_arr(TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, U64 *buckets_cap_out);
@@ -429,28 +352,6 @@ lnk_build_rad_debug_info(TP_Context *tp,
CV_SymbolListArray *parsed_symbols,
LNK_MergedTypes types);
// --- PDB ---------------------------------------------------------------------
internal U64 * lnk_hash_cv_symbol_ptr_arr(TP_Context *tp, Arena *arena, CV_SymbolPtrArray arr);
internal CV_SymbolPtrArray lnk_dedup_gsi_symbols (TP_Context *tp, Arena *arena, PDB_GsiContext *gsi, U64 obj_count, CV_SymbolList *symbol_list_arr);
internal void lnk_build_pdb_public_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, PDB_PsiContext *psi);
internal String8List lnk_build_pdb(TP_Context *tp,
TP_Arena *tp_arena,
String8 image_data,
LNK_Config *config,
LNK_SymbolTable *symtab,
U64 obj_count,
LNK_Obj **obj_arr,
CV_DebugS *debug_s_arr,
U64 symbol_input_count,
LNK_SymbolInput *symbol_inputs,
CV_SymbolListArray *parsed_symbols,
LNK_MergedTypes types);
// --- RAD Debug Info ----------------------------------------------------------
internal U64 lnk_udt_name_hash_table_hash (String8 string);
internal LNK_UDTNameBucket ** lnk_udt_name_hash_table_from_leaf_arr(TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, U64 *buckets_cap_out);
internal LNK_UDTNameBucket * lnk_udt_name_hash_table_lookup (LNK_UDTNameBucket **buckets, U64 cap, String8 name);
+15 -13
View File
@@ -3725,7 +3725,7 @@ pdb_get_guid(PDB_Context *pdb)
}
internal void
pdb_build(TP_Context *tp, TP_Arena *pool_temp, PDB_Context *pdb, CV_StringHashTable string_ht)
pdb_build(TP_Context *tp, TP_Arena *pool_temp, PDB_Context *pdb, CV_StringHashTable string_ht, B32 build_gsi)
{
ProfBeginFunction();
@@ -3735,26 +3735,28 @@ pdb_build(TP_Context *tp, TP_Arena *pool_temp, PDB_Context *pdb, CV_StringHashTa
PDB_TypeServer *tpi = pdb->type_servers[CV_TypeIndexSource_TPI];
PDB_TypeServer *ipi = pdb->type_servers[CV_TypeIndexSource_IPI];
if (dbi->globals_sn == MSF_INVALID_STREAM_NUMBER) {
dbi->globals_sn = msf_stream_alloc(pdb->msf);
}
if (dbi->publics_sn == MSF_INVALID_STREAM_NUMBER) {
dbi->publics_sn = msf_stream_alloc(pdb->msf);
}
if (dbi->symbols_sn == MSF_INVALID_STREAM_NUMBER) {
dbi->symbols_sn = msf_stream_alloc(pdb->msf);
}
pdb_type_server_build(tp, tpi, strtab, pdb->msf, PDB_FixedStream_Tpi);
if (info->flags & PDB_FeatureFlag_HAS_ID_STREAM) {
pdb_type_server_build(tp, ipi, strtab, pdb->msf, PDB_FixedStream_Ipi);
}
psi_build(tp, pdb->psi, pdb->msf, dbi->publics_sn, dbi->symbols_sn);
gsi_build(tp, pdb->gsi, pdb->msf, dbi->globals_sn, dbi->symbols_sn);
dbi_build(tp, pdb->dbi, pdb->msf, PDB_FixedStream_Dbi, string_ht);
pdb_info_build(pdb->info, pdb->msf, PDB_FixedStream_Info);
if (build_gsi) {
if (dbi->globals_sn == MSF_INVALID_STREAM_NUMBER) {
dbi->globals_sn = msf_stream_alloc(pdb->msf);
}
if (dbi->publics_sn == MSF_INVALID_STREAM_NUMBER) {
dbi->publics_sn = msf_stream_alloc(pdb->msf);
}
if (dbi->symbols_sn == MSF_INVALID_STREAM_NUMBER) {
dbi->symbols_sn = msf_stream_alloc(pdb->msf);
}
psi_build(tp, pdb->psi, pdb->msf, dbi->publics_sn, dbi->symbols_sn);
gsi_build(tp, pdb->gsi, pdb->msf, dbi->globals_sn, dbi->symbols_sn);
}
ProfEnd();
}
+1 -1
View File
@@ -351,7 +351,7 @@ typedef struct
internal PDB_Context * pdb_alloc(U64 page_size, COFF_MachineType machine, COFF_TimeStamp time_stamp, U32 age, Guid guid);
internal PDB_Context * pdb_open(String8 data);
internal void pdb_release(PDB_Context **pdb_ptr);
internal void pdb_build(TP_Context *tp, TP_Arena *pool_temp, PDB_Context *pdb, CV_StringHashTable string_ht);
internal void pdb_build(TP_Context *tp, TP_Arena *pool_temp, PDB_Context *pdb, CV_StringHashTable string_ht, B32 build_gsi);
internal void pdb_set_machine(PDB_Context *pdb, COFF_MachineType machine);
internal void pdb_set_guid(PDB_Context *pdb, Guid guid);
internal void pdb_set_time_stamp(PDB_Context *pdb, COFF_TimeStamp time_stamp);
+5 -3
View File
@@ -15,7 +15,7 @@ tp_run_tasks(TP_Context *pool, TP_Worker *worker)
// run task
Arena *arena = pool->task_arena ? pool->task_arena->v[worker->id] : 0;
U64 task_id = pool->task_count - (task_left+1);
pool->task_func(arena, worker->id, task_id, pool->task_data);
pool->task_func(arena, worker->id, task_id, pool->task_data, pool);
// cache task count so we dont touch pool memory after atomic inc
U64 task_count = pool->task_count;
@@ -85,6 +85,7 @@ tp_alloc(Arena *arena, U32 worker_count, U32 max_worker_count, String8 name)
pool->exec_semaphore = exec_semaphore;
pool->task_semaphore = task_semaphore;
pool->main_semaphore = main_semaphore;
pool->barrier = barrier_alloc(worker_count);
pool->is_live = 1;
pool->worker_count = worker_count;
pool->worker_arr = push_array(arena, TP_Worker, worker_count);
@@ -113,11 +114,11 @@ tp_release(TP_Context *pool)
B32 is_shared = pool->exec_semaphore.u64[0] != 0;
if (is_shared) {
for (U64 i = 0; i < pool->worker_count; ++i) {
for EachIndex(i, pool->worker_count) {
semaphore_drop(pool->exec_semaphore);
}
}
for (U64 i = 0; i < pool->worker_count; ++i) {
for EachIndex(i, pool->worker_count) {
semaphore_drop(pool->task_semaphore);
}
for (U64 i = 1; i < pool->worker_count; i += 1) {
@@ -126,6 +127,7 @@ tp_release(TP_Context *pool)
if (is_shared) {
semaphore_release(pool->exec_semaphore);
}
barrier_release(pool->barrier);
semaphore_release(pool->task_semaphore);
semaphore_release(pool->main_semaphore);
+2 -1
View File
@@ -3,7 +3,7 @@
#pragma once
#define THREAD_POOL_TASK_FUNC(name) void name(Arena *arena, U64 worker_id, U64 task_id, void *raw_task)
#define THREAD_POOL_TASK_FUNC(name) void name(Arena *arena, U64 worker_id, U64 task_id, void *raw_task, struct TP_Context *tp)
typedef THREAD_POOL_TASK_FUNC(TP_TaskFunc);
typedef struct TP_Arena
@@ -31,6 +31,7 @@ typedef struct TP_Context
Semaphore exec_semaphore;
Semaphore task_semaphore;
Semaphore main_semaphore;
Barrier barrier;
U32 worker_count;
TP_Worker *worker_arr;