WIP symbol plumbing

This commit is contained in:
Nikita Smith
2026-04-06 12:04:32 -07:00
parent 12a1e28fff
commit f7ac6767cf
4 changed files with 233 additions and 218 deletions
+21 -4
View File
@@ -457,6 +457,25 @@ cv_make_proc_refs(Arena *arena, CV_ModIndex imod, CV_SymbolList symbol_list)
return proc_ref_list; return proc_ref_list;
} }
internal B32
cv_is_lproc(CV_Symbol symbol)
{
return symbol.kind == CV_SymKind_LPROC32 ||
symbol.kind == CV_SymKind_LPROCMIPS ||
symbol.kind == CV_SymKind_LPROCIA64 ||
symbol.kind == CV_SymKind_LPROC32_ID ||
symbol.kind == CV_SymKind_LPROCMIPS_ID ||
symbol.kind == CV_SymKind_LPROCIA64_ID ||
symbol.kind == CV_SymKind_LPROC32_DPC ||
symbol.kind == CV_SymKind_LPROC32_DPC_ID ||
symbol.kind == CV_SymKind_LPROC16 ||
symbol.kind == CV_SymKind_LPROC32_16t ||
symbol.kind == CV_SymKind_LPROCMIPS_16t ||
symbol.kind == CV_SymKind_LPROC32_ST ||
symbol.kind == CV_SymKind_LPROCMIPS_ST ||
symbol.kind == CV_SymKind_LPROCIA64_ST;
}
internal B32 internal B32
cv_is_obj_info(CV_Symbol symbol) cv_is_obj_info(CV_Symbol symbol)
{ {
@@ -1020,7 +1039,7 @@ cv_symbol_deduper_insert_or_update(void **buckets, U64 bucket_cap, U64 hash, voi
U64 bucket_idx = best_idx; U64 bucket_idx = best_idx;
do { do {
retry:; retry:;
void *curr_ptr = buckets + bucket_idx; void *curr_ptr = buckets[bucket_idx];
Assert(curr_ptr != symbol_ptr); Assert(curr_ptr != symbol_ptr);
if (curr_ptr == 0) { if (curr_ptr == 0) {
@@ -1513,9 +1532,7 @@ cv_patch_symbol_tree_offsets_new(String8List raw_symbols, U64 base_offset, U64 a
for EachNode(n, String8Node, raw_symbols.first) { for EachNode(n, String8Node, raw_symbols.first) {
for (U64 cursor = 0, depth = 0; cursor + sizeof(CV_SymbolHeader) <= n->string.size; ) { for (U64 cursor = 0, depth = 0; cursor + sizeof(CV_SymbolHeader) <= n->string.size; ) {
CV_Symbol symbol = {0}; CV_Symbol symbol = {0};
U64 read_size = cv_read_symbol(n->string, cursor, CV_SymbolAlign, &symbol); TryReadBreak(cv_read_symbol(n->string, cursor, CV_SymbolAlign, &symbol), cursor);
if (read_size == 0) { break; }
cursor += read_size;
if (symbol.kind == CV_SymKind_SKIP) { continue; } if (symbol.kind == CV_SymKind_SKIP) { continue; }
+1
View File
@@ -408,6 +408,7 @@ internal CV_SymbolList cv_make_proc_refs(Arena *arena, CV_ModIndex imod, CV_Symb
internal U64 cv_read_symbol(String8 raw_data, U64 off, U64 align, CV_Symbol *symbol_out); internal U64 cv_read_symbol(String8 raw_data, U64 off, U64 align, CV_Symbol *symbol_out);
internal CV_Symbol cv_symbol_from_string(String8 raw_data); internal CV_Symbol cv_symbol_from_string(String8 raw_data);
internal B32 cv_is_lproc(CV_Symbol symbol);
internal B32 cv_is_obj_info(CV_Symbol symbol); internal B32 cv_is_obj_info(CV_Symbol symbol);
internal CV_ObjInfo cv_obj_info_from_symbol(CV_Symbol symbol); internal CV_ObjInfo cv_obj_info_from_symbol(CV_Symbol symbol);
+180 -195
View File
@@ -30,7 +30,6 @@ THREAD_POOL_TASK_FUNC(lnk_parse_debug_s_task)
U64 obj_idx = task_id; U64 obj_idx = task_id;
LNK_CodeViewInput *task = raw_task; LNK_CodeViewInput *task = raw_task;
LNK_Obj *obj = task->obj_arr [obj_idx];
String8List sect_list = task->debug_s_list_arr[obj_idx]; String8List sect_list = task->debug_s_list_arr[obj_idx];
CV_DebugS *debug_s = &task->debug_s_arr [obj_idx]; CV_DebugS *debug_s = &task->debug_s_arr [obj_idx];
@@ -43,14 +42,14 @@ THREAD_POOL_TASK_FUNC(lnk_parse_debug_s_task)
String8List string_data_list = cv_sub_section_from_debug_s(*debug_s, CV_C13SubSectionKind_StringTable); String8List string_data_list = cv_sub_section_from_debug_s(*debug_s, CV_C13SubSectionKind_StringTable);
if (string_data_list.node_count > 1) { if (string_data_list.node_count > 1) {
// TODO: print section index // TODO: print section index
lnk_error_obj(LNK_Warning_IllData, obj, ".debug$S has %u string table sub-sections defined, picking first sub-section", string_data_list.node_count); lnk_error_obj(LNK_Warning_IllData, task->obj_arr[obj_idx], ".debug$S has %u string table sub-sections defined, picking first sub-section", string_data_list.node_count);
} }
// make sure there is one file checksum table // make sure there is one file checksum table
String8List checksum_data_list = cv_sub_section_from_debug_s(*debug_s, CV_C13SubSectionKind_FileChksms); String8List checksum_data_list = cv_sub_section_from_debug_s(*debug_s, CV_C13SubSectionKind_FileChksms);
if (checksum_data_list.node_count > 1) { if (checksum_data_list.node_count > 1) {
// TODO: print section index // TODO: print section index
lnk_error_obj(LNK_Warning_IllData, obj, ".debug$S has %u file checksum sub-sections defined, picking first sub-section", checksum_data_list.node_count); lnk_error_obj(LNK_Warning_IllData, task->obj_arr[obj_idx], ".debug$S has %u file checksum sub-sections defined, picking first sub-section", checksum_data_list.node_count);
} }
} }
} }
@@ -244,14 +243,14 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_fla
debug_p_arr = push_array(tp_arena->v[0], CV_DebugT, obj_count); debug_p_arr = push_array(tp_arena->v[0], CV_DebugT, obj_count);
parse_types.raw_types = str8_array_from_list_arr(scratch.arena, input.debug_p_list_arr, obj_count); parse_types.raw_types = str8_array_from_list_arr(scratch.arena, input.debug_p_list_arr, obj_count);
parse_types.out_types = debug_p_arr; parse_types.out_types = debug_p_arr;
tp_for_parallel_prof(tp, 0, obj_count, lnk_strip_debug_t_sig_task, &parse_types, "Strip .debug$P"); tp_for_parallel_prof(tp, 0, obj_count, lnk_strip_debug_t_sig_task, &parse_types, "Strip .debug$P");
tp_for_parallel_prof(tp, 0, obj_count, lnk_parse_debug_t_task, &parse_types, "Parse .debug$P"); tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_t_task, &parse_types, "Parse .debug$P");
input.debug_t_arr = push_array(tp_arena->v[0], CV_DebugT, obj_count); input.debug_t_arr = push_array(tp_arena->v[0], CV_DebugT, obj_count);
parse_types.raw_types = str8_array_from_list_arr(scratch.arena, input.debug_t_list_arr, obj_count); parse_types.raw_types = str8_array_from_list_arr(scratch.arena, input.debug_t_list_arr, obj_count);
parse_types.out_types = input.debug_t_arr; parse_types.out_types = input.debug_t_arr;
tp_for_parallel_prof(tp, 0, obj_count, lnk_strip_debug_t_sig_task, &parse_types, "Strip .debug$T"); tp_for_parallel_prof(tp, 0, obj_count, lnk_strip_debug_t_sig_task, &parse_types, "Strip .debug$T");
tp_for_parallel_prof(tp, 0, obj_count, lnk_parse_debug_t_task, &parse_types, "Parse .debug$T"); tp_for_parallel_prof(tp, tp_arena, obj_count, lnk_parse_debug_t_task, &parse_types, "Parse .debug$T");
} }
ProfEnd(); ProfEnd();
@@ -482,29 +481,25 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_fla
} }
} }
// :zero_out_symbol_sub_section
ProfBegin("Zero-out Symbols Sub-sections");
for EachIndex(i, obj_count) { MemoryZeroStruct(cv_sub_section_ptr_from_debug_s(&input.debug_s_arr[i], CV_C13SubSectionKind_Symbols)); }
ProfEnd();
ProfBegin("Make Symbol Inputs"); ProfBegin("Make Symbol Inputs");
{ {
// count symbol blocks
for EachIndex(obj_idx, input.count) { for EachIndex(obj_idx, input.count) {
String8List s = cv_sub_section_from_debug_s(input.debug_s_arr[obj_idx], CV_C13SubSectionKind_Symbols); String8List s = cv_sub_section_from_debug_s(input.debug_s_arr[obj_idx], CV_C13SubSectionKind_Symbols);
input.symbol_input_count += s.node_count; input.symbol_input_count += s.node_count;
} }
// alloc block pointers
input.symbol_inputs = push_array_no_zero(tp_arena->v[0], LNK_SymbolInput, input.symbol_input_count); input.symbol_inputs = push_array_no_zero(tp_arena->v[0], LNK_SymbolInput, input.symbol_input_count);
U64 symbol_input_count = 0; U64 symbol_input_count = 0;
for EachIndex(obj_idx, input.count) { for EachIndex(obj_idx, input.count) {
String8List s = cv_sub_section_from_debug_s(input.debug_s_arr[obj_idx], CV_C13SubSectionKind_Symbols); String8List s = cv_sub_section_from_debug_s(input.debug_s_arr[obj_idx], CV_C13SubSectionKind_Symbols);
for EachNode(block_n, String8Node, s.first) { for EachNode(n, String8Node, s.first) {
Assert(symbol_input_count < input.symbol_input_count); Assert(symbol_input_count < input.symbol_input_count);
LNK_SymbolInput *in = input.symbol_inputs + symbol_input_count; LNK_SymbolInput *in = &input.symbol_inputs[symbol_input_count++];
in->obj_idx = obj_idx; in->obj_idx = obj_idx;
in->raw_symbols = block_n->string; in->raw_symbols = n->string;
symbol_input_count += 1;
} }
} }
@@ -1234,61 +1229,59 @@ THREAD_POOL_TASK_FUNC(lnk_fixup_symbols_task)
{ {
LNK_MergeTypes *task = raw_task; LNK_MergeTypes *task = raw_task;
U64 leaf_count_ipi = task->result.count [CV_TypeIndexSource_IPI]; LNK_SymbolInput symbols = task->input->symbol_inputs[task_id];
U8 **leaf_arr_ipi = task->result.v [CV_TypeIndexSource_IPI]; U64 leaf_count_ipi = task->result.count [CV_TypeIndexSource_IPI];
CV_TypeIndex min_ti_ipi = task->min_type_indices[CV_TypeIndexSource_IPI]; U8 **leaf_arr_ipi = task->result.v [CV_TypeIndexSource_IPI];
CV_TypeIndex min_ti_ipi = task->min_type_indices[CV_TypeIndexSource_IPI];
for EachInRange(i, task->input->symbol_input_ranges[task_id]) { for (U64 cursor = 0; cursor + sizeof(CV_SymbolHeader) <= symbols.raw_symbols.size; ) {
LNK_SymbolInput symbols = task->input->symbol_inputs[i]; CV_Symbol symbol = {0};
TryReadBreak(cv_read_symbol(symbols.raw_symbols, cursor, CV_SymbolAlign, &symbol), cursor);
for (U64 cursor = 0; cursor + sizeof(CV_SymbolHeader) <= symbols.raw_symbols.size; ) { // convert symbol to final type
CV_Symbol symbol = {0}; CV_SymKind *sym_kind_ptr = cv_kind_ptr_from_symbol(symbol);
TryReadBreak(cv_read_symbol(symbols.raw_symbols, cursor, CV_SymbolAlign, &symbol), cursor); switch (*sym_kind_ptr) {
case CV_SymKind_PROC_ID_END: *sym_kind_ptr = CV_SymKind_END; break;
// convert symbol to final type case CV_SymKind_LPROC32_ID: *sym_kind_ptr = CV_SymKind_LPROC32; goto fixup_id;
switch (symbol.kind) { case CV_SymKind_GPROC32_ID: *sym_kind_ptr = CV_SymKind_GPROC32; goto fixup_id;
case CV_SymKind_LPROC32_ID: symbol.kind = CV_SymKind_LPROC32; goto fixup_id; case CV_SymKind_LPROC32_DPC_ID: *sym_kind_ptr = CV_SymKind_LPROC32_DPC; goto fixup_id;
case CV_SymKind_GPROC32_ID: symbol.kind = CV_SymKind_GPROC32; goto fixup_id; case CV_SymKind_LPROCMIPS_ID: *sym_kind_ptr = CV_SymKind_LPROCMIPS; goto fixup_id;
case CV_SymKind_LPROC32_DPC_ID: symbol.kind = CV_SymKind_LPROC32_DPC; goto fixup_id; case CV_SymKind_GPROCMIPS_ID: *sym_kind_ptr = CV_SymKind_GPROCMIPS; goto fixup_id;
case CV_SymKind_LPROCMIPS_ID: symbol.kind = CV_SymKind_LPROCMIPS; goto fixup_id; case CV_SymKind_LPROCIA64_ID: *sym_kind_ptr = CV_SymKind_LPROCIA64; goto fixup_id;
case CV_SymKind_GPROCMIPS_ID: symbol.kind = CV_SymKind_GPROCMIPS; goto fixup_id; case CV_SymKind_GPROCIA64_ID: *sym_kind_ptr = CV_SymKind_GPROCIA64; goto fixup_id;
case CV_SymKind_LPROCIA64_ID: symbol.kind = CV_SymKind_LPROCIA64; goto fixup_id; fixup_id:; {
case CV_SymKind_GPROCIA64_ID: symbol.kind = CV_SymKind_GPROCIA64; goto fixup_id; CV_SymProc32 *proc32 = str8_deserial_get_raw_ptr(symbol.data, 0, sizeof(*proc32));
fixup_id:; { if (proc32->itype < min_ti_ipi) {
CV_SymProc32 *proc32 = (CV_SymProc32 *) symbol.data.str; // TODO: in some cases destructors don't have a type, need a repro
if (proc32->itype < min_ti_ipi) { break;
// TODO: in some cases destructors don't have a type, need a repro
break;
}
if ((proc32->itype - min_ti_ipi) > leaf_count_ipi) {
Assert("TODO: error handle corrupted type index");
break;
}
U64 leaf_idx = proc32->itype - min_ti_ipi;
String8 leaf_data = str8(leaf_arr_ipi[leaf_idx], max_U64);
CV_Leaf leaf;
cv_read_leaf(leaf_data, 0, 1, &leaf);
U64 min_leaf_size = cv_header_struct_size_from_leaf_kind(leaf.kind);
if (min_leaf_size > leaf.data.size) {
Assert(!"TODO: error handle corrupt leaf");
break;
}
if (leaf.kind == CV_LeafKind_FUNC_ID) {
proc32->itype = ((CV_LeafFuncId *) leaf.data.str)->itype;
} else if (leaf.kind == CV_LeafKind_MFUNC_ID) {
proc32->itype = ((CV_LeafMFuncId *) leaf.data.str)->itype;
} else {
Assert(!"TODO: erorr handle unexpected leaf type");
break;
}
} break;
case CV_SymKind_PROC_ID_END: symbol.kind = CV_SymKind_END; break;
} }
if ((proc32->itype - min_ti_ipi) > leaf_count_ipi) {
Assert(0 && "TODO: error handle corrupted type index");
break;
}
U64 leaf_idx = proc32->itype - min_ti_ipi;
String8 leaf_data = str8(leaf_arr_ipi[leaf_idx], max_U64);
CV_Leaf leaf;
if (cv_read_leaf(leaf_data, 0, 1, &leaf) == 0) { InvalidPath; }
U64 min_leaf_size = cv_header_struct_size_from_leaf_kind(leaf.kind);
if (min_leaf_size > leaf.data.size) { Assert(!"TODO: error handle corrupt leaf"); break; }
if (leaf.kind == CV_LeafKind_FUNC_ID) {
CV_LeafFuncId *func_id = str8_deserial_get_raw_ptr(leaf.data, 0, sizeof(*func_id));
proc32->itype = func_id->itype;
} else if (leaf.kind == CV_LeafKind_MFUNC_ID) {
CV_LeafMFuncId *mfunc_id = str8_deserial_get_raw_ptr(leaf.data, 0, sizeof(*mfunc_id));
proc32->itype = mfunc_id->itype;
} else {
Assert(!"TODO: erorr handle unexpected leaf type");
break;
}
} break;
} }
} }
} }
@@ -1486,30 +1479,30 @@ lnk_merge_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input)
ProfEnd(); ProfEnd();
ProfBegin("Assign type indices"); ProfBegin("Fixup Type Indices");
for EachIndex(ti_source, CV_TypeIndexSource_COUNT) {
task.ti_source = ti_source;
task.assigned_type_caps[ti_source] = (task.unique_leaf_refs_arr[ti_source].count * 13) / 10;
task.assigned_type_hts [ti_source] = push_array(scratch.arena, CV_TypeIndex, task.assigned_type_caps[ti_source]);
task.min_type_indices [ti_source] = CV_MinComplexTypeIndex;
task.ranges = tp_divide_work(scratch.arena, task.unique_leaf_refs_arr[ti_source].count, tp->worker_count);
tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_assign_type_indices_task, &task, "Assign Type Indices");
}
ProfEnd();
ProfBegin("Patch Type Indices");
{ {
ProfBegin("Assign type indices");
for EachIndex(ti_source, CV_TypeIndexSource_COUNT) {
task.ti_source = ti_source;
task.assigned_type_caps[ti_source] = (task.unique_leaf_refs_arr[ti_source].count * 13) / 10;
task.assigned_type_hts [ti_source] = push_array(scratch.arena, CV_TypeIndex, task.assigned_type_caps[ti_source]);
task.min_type_indices [ti_source] = CV_MinComplexTypeIndex;
task.ranges = tp_divide_work(scratch.arena, task.unique_leaf_refs_arr[ti_source].count, tp->worker_count);
tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_assign_type_indices_task, &task, "Assign Type Indices");
}
ProfEnd();
task.ranges = tp_divide_work(scratch.arena, input->symbol_input_count, tp->worker_count); task.ranges = tp_divide_work(scratch.arena, input->symbol_input_count, tp->worker_count);
tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_cv_patcher_symbols_task, &task, "Symbols"); tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_cv_patcher_symbols_task, &task, "Fixup Symbol Type Indices");
task.ranges = 0; task.ranges = 0;
task.debug_s_arr = input->debug_s_arr; task.debug_s_arr = input->debug_s_arr;
tp_for_parallel_prof(tp, 0, input->count, lnk_cv_patcher_inlines_task, &task, "Inlines"); tp_for_parallel_prof(tp, 0, input->count, lnk_cv_patcher_inlines_task, &task, "Fixup Inlines Type Indices");
for EachIndex(ti_source, CV_TypeIndexSource_COUNT) { for EachIndex(ti_source, CV_TypeIndexSource_COUNT) {
task.ti_source = ti_source; task.ti_source = ti_source;
task.ranges = tp_divide_work(scratch.arena, task.unique_leaf_refs_arr[ti_source].count, tp->worker_count); task.ranges = tp_divide_work(scratch.arena, task.unique_leaf_refs_arr[ti_source].count, tp->worker_count);
tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_cv_patcher_leaves_task, &task, "Leaves"); tp_for_parallel_prof(tp, 0, tp->worker_count, lnk_cv_patcher_leaves_task, &task, "Fixup Types Type Indices");
} }
} }
ProfEnd(); ProfEnd();
@@ -1523,7 +1516,7 @@ lnk_merge_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input)
tp_for_parallel(tp, 0, tp->worker_count, lnk_unbucket_raw_leaves_task, &task); tp_for_parallel(tp, 0, tp->worker_count, lnk_unbucket_raw_leaves_task, &task);
} }
tp_for_parallel_prof(tp, 0, input->symbol_input_count, lnk_fixup_symbols_task, &task, "fixup type indices in symbols"); tp_for_parallel_prof(tp, 0, input->symbol_input_count, lnk_fixup_symbols_task, &task, "Fixup ID Symbols");
MemoryCopyTyped(task.result.min_type_indices, input->min_type_indices, CV_TypeIndexSource_COUNT); MemoryCopyTyped(task.result.min_type_indices, input->min_type_indices, CV_TypeIndexSource_COUNT);
@@ -1736,7 +1729,7 @@ lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, U64 leaf_cou
} }
internal internal
THREAD_POOL_TASK_FUNC(lnk_process_and_populate_gsi_and_psi_task) THREAD_POOL_TASK_FUNC(lnk_build_gsi_psi)
{ {
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
@@ -1757,9 +1750,7 @@ THREAD_POOL_TASK_FUNC(lnk_process_and_populate_gsi_and_psi_task)
LNK_SymbolInput symbols = task->cv->symbol_inputs[i]; LNK_SymbolInput symbols = task->cv->symbol_inputs[i];
for (U64 cursor = 0, depth = 0; cursor + sizeof(CV_SymbolHeader) <= symbols.raw_symbols.size; ) { for (U64 cursor = 0, depth = 0; cursor + sizeof(CV_SymbolHeader) <= symbols.raw_symbols.size; ) {
CV_Symbol symbol = {0}; CV_Symbol symbol = {0};
U64 symbol_read_size = cv_read_symbol(symbols.raw_symbols, cursor, CV_SymbolAlign, &symbol); TryReadBreak(cv_read_symbol(symbols.raw_symbols, cursor, CV_SymbolAlign, &symbol), cursor);
if (symbol_read_size == 0) { break; }
cursor += symbol_read_size;
if (cv_is_global_symbol(symbol.kind)) { if (cv_is_global_symbol(symbol.kind)) {
void *ptr = cv_ptr_from_symbol(symbol); void *ptr = cv_ptr_from_symbol(symbol);
@@ -1774,7 +1765,10 @@ THREAD_POOL_TASK_FUNC(lnk_process_and_populate_gsi_and_psi_task)
*kind_ptr = CV_SymKind_SKIP; *kind_ptr = CV_SymKind_SKIP;
} else if (symbol.kind == CV_SymKind_GPROC32 || symbol.kind == CV_SymKind_LPROC32) { } else if (symbol.kind == CV_SymKind_GPROC32 || symbol.kind == CV_SymKind_LPROC32) {
String8 name = cv_name_from_symbol(symbol.kind, symbol.data); String8 name = cv_name_from_symbol(symbol.kind, symbol.data);
task->proc_ref_sizes[task_id] += sizeof(CV_SymRef2) + name.size + 1; task->proc_ref_sizes[task_id] += sizeof(CV_SymbolHeader);
task->proc_ref_sizes[task_id] += sizeof(CV_SymRef2);
task->proc_ref_sizes[task_id] += name.size + 1;
task->proc_ref_sizes[task_id] = AlignPow2(task->proc_ref_sizes[task_id], sizeof(void *));
task->proc_ref_counts[task_id] += 1; task->proc_ref_counts[task_id] += 1;
} }
@@ -1786,11 +1780,11 @@ THREAD_POOL_TASK_FUNC(lnk_process_and_populate_gsi_and_psi_task)
} }
} }
} }
ins_atomic_u64_add_eval(&task->total_symbol_count, global_symbols.count); ins_atomic_u64_add_eval(&task->global_symbol_count, global_symbols.count);
barrier_wait(tp->barrier); barrier_wait(tp->barrier);
if (task_id == 0) { if (task_id == 0) {
task->bucket_cap = (U64)((F64)task->total_symbol_count * 1.3); task->bucket_cap = (U64)((F64)task->global_symbol_count * 1.3);
task->buckets = push_array(scratch.arena, void *, task->bucket_cap); task->buckets = push_array(scratch.arena, void *, task->bucket_cap);
task->insert_count = push_array(scratch.arena, U64, tp->worker_count); task->insert_count = push_array(scratch.arena, U64, tp->worker_count);
} }
@@ -1838,21 +1832,18 @@ THREAD_POOL_TASK_FUNC(lnk_process_and_populate_gsi_and_psi_task)
barrier_wait(tp->barrier); barrier_wait(tp->barrier);
if (task_id == 0) { if (task_id == 0) {
// prealloc symbol nodes // take into account arena header
CV_SymbolNode *nodes = push_array_no_zero(gsi->arena, CV_SymbolNode, task->symbol_count); for EachIndex(i, tp->worker_count) { task->proc_ref_sizes[i] += ARENA_HEADER_SIZE; }
// push symbols to GSI
for EachIndex(i, task->symbol_count) {
CV_SymbolNode *n = &nodes[i];
n->prev = n->next = 0;
n->data = cv_symbol_from_ptr(task->symbol_arr[i]);
gsi_push_(gsi, task->symbol_hashes[i], n);
}
U64 total_proc_ref_count = sum_array_u64(tp->worker_count, task->proc_ref_counts);
// prealloc output buffer for the proc refs // prealloc output buffer for the proc refs
task->proc_refs.size = sum_array_u64(tp->worker_count, task->proc_ref_sizes); task->proc_refs.size = sum_array_u64(tp->worker_count, task->proc_ref_sizes);
task->proc_refs.str = push_array(gsi->arena, U8, task->proc_refs.size); task->proc_refs.str = push_array(gsi->arena, U8, task->proc_refs.size);
task->proc_ref_offs = offsets_from_counts_array_u64(scratch.arena, task->proc_ref_sizes, tp->worker_count); task->proc_ref_hashes = push_array(scratch.arena, U64, total_proc_ref_count);
task->proc_ref_offs = offsets_from_counts_array_u64(scratch.arena, task->proc_ref_sizes, tp->worker_count);
task->proc_ref_count = sum_array_u64(tp->worker_count, task->proc_ref_counts);
task->proc_ref_nodes = push_array(gsi->arena, CV_SymbolNode, task->proc_ref_count);
} }
barrier_wait(tp->barrier); barrier_wait(tp->barrier);
@@ -1860,61 +1851,100 @@ THREAD_POOL_TASK_FUNC(lnk_process_and_populate_gsi_and_psi_task)
U64 proc_refs_size = task->proc_ref_sizes[task_id]; U64 proc_refs_size = task->proc_ref_sizes[task_id];
U64 proc_refs_off = task->proc_ref_offs[task_id]; U64 proc_refs_off = task->proc_ref_offs[task_id];
U8 *proc_refs = task->proc_refs.str + proc_refs_off; U8 *proc_refs = task->proc_refs.str + proc_refs_off;
Arena *proc_ref_arena = arena_alloc_(&(ArenaParams){ .optional_backing_buffer = proc_refs, Arena *proc_ref_arena = arena_alloc_(&(ArenaParams){ .flags = ArenaFlag_NoChain, .optional_backing_buffer = proc_refs, .reserve_size = proc_refs_size, .commit_size = proc_refs_size });
.reserve_size = proc_refs_size,
.commit_size = proc_refs_size U64 proc_ref_idx = task->proc_ref_offs[task_id];
});
U64 hash_idx = 0;
for EachInRange(i, task->cv->symbol_input_ranges[task_id]) { for EachInRange(i, task->cv->symbol_input_ranges[task_id]) {
LNK_SymbolInput *in = &task->cv->symbol_inputs[i]; LNK_SymbolInput *in = &task->cv->symbol_inputs[i];
String8 raw_symbols = in->raw_symbols; String8 raw_symbols = in->raw_symbols;
CV_ModIndex imod = task->mod_arr[in->obj_idx]->imod; CV_ModIndex imod = task->mod_arr[in->obj_idx]->imod;
for (U64 cursor = 0, depth = 0; cursor + sizeof(CV_SymbolHeader) <= raw_symbols.size; ) { for (U64 cursor = 0; cursor + sizeof(CV_SymbolHeader) <= raw_symbols.size; ) {
CV_Symbol symbol = {0}; CV_Symbol symbol = {0};
U64 read_size = cv_read_symbol(raw_symbols, cursor, CV_SymbolAlign, &symbol); TryReadBreak(cv_read_symbol(raw_symbols, cursor, CV_SymbolAlign, &symbol), cursor);
if (read_size == 0) { break; }
cursor += read_size;
if (symbol.kind == CV_SymKind_GPROC32 || symbol.kind == CV_SymKind_LPROC32) { if (symbol.kind == CV_SymKind_GPROC32 || symbol.kind == CV_SymKind_LPROC32) {
String8 name = cv_name_from_symbol(symbol.kind, symbol.data); Temp temp = temp_begin(task->fixed_arenas[task_id]);
CV_Symbol proc_ref = cv_make_proc_ref(proc_ref_arena, imod, safe_cast_u32(symbol.offset), name, /* is_local */ 1);
task->proc_ref_hashes[hash_idx] = hash_from_cv_symbol(&proc_ref); String8 name = cv_name_from_symbol(symbol.kind, symbol.data);
hash_idx += 1; CV_Symbol proc_ref_symbol = cv_make_proc_ref(temp.arena, imod, safe_cast_u32(symbol.offset), name, cv_is_lproc(symbol));
String8 proc_ref_raw = cv_data_from_symbol(proc_ref_arena, &proc_ref_symbol, 1);
CV_SymbolNode *n = &task->proc_ref_nodes[proc_ref_idx++];
n->data = cv_symbol_from_ptr(proc_ref_raw.str);
task->proc_ref_hashes[proc_ref_idx] = hash_from_cv_symbol(&n->data);
temp_end(temp);
} }
} }
} }
barrier_wait(tp->barrier); barrier_wait(tp->barrier);
if (task_id == 0) { if (task_id == 0) {
U64 *offsets = offsets_from_counts_array_u64(scratch.arena, task->proc_ref_sizes, tp->worker_count); // push global symbols
for EachIndex(i, tp->worker_count) { {
CV_SymbolNode *nodes = push_array(gsi->arena, CV_SymbolNode, task->proc_ref_counts[i]); CV_SymbolNode *nodes = push_array_no_zero(gsi->arena, CV_SymbolNode, task->symbol_count);
U64 node_idx = 0; for EachIndex(i, task->symbol_count) {
for (U64 cursor = offsets[i]; cursor < offsets[i+1]; ) { CV_SymbolNode *n = &nodes[i];
U64 read_size = cv_read_symbol(task->proc_refs, cursor, PDB_SYMBOL_ALIGN, &nodes[node_idx].data); n->prev = n->next = 0;
if (read_size == 0) { break; } n->data = cv_symbol_from_ptr(task->symbol_arr[i]);
cursor += read_size; gsi_push_(gsi, task->symbol_hashes[i], n);
gsi_push_(gsi, task->proc_ref_hashes[node_idx], &nodes[node_idx]);
} }
} }
// push proc refs
for EachIndex(i, task->proc_ref_count) {
gsi_push_(gsi, task->proc_ref_hashes[i], &task->proc_ref_nodes[i]);
}
} }
barrier_wait(tp->barrier); barrier_wait(tp->barrier);
} }
{ {
if (task_id == 0) {
task->public_symbol_sizes = push_array(scratch.arena, U64, tp->worker_count);
task->public_symbol_node_counts = push_array(scratch.arena, U64, tp->worker_count);
}
barrier_wait(tp->barrier);
// compute buffer size for CV public symbols
for EachNode(chunk, LNK_SymbolHashTrieChunk, task->symtab->chunks[task_id].first) { for EachNode(chunk, LNK_SymbolHashTrieChunk, task->symtab->chunks[task_id].first) {
task->public_symbol_node_counts[task_id] += chunk->count; for EachIndex(i, chunk->count) {
LNK_Symbol *symbol = chunk->v[i].symbol;
LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol);
COFF_ParsedSymbol symbol_parsed = lnk_parsed_from_symbol(symbol);
if (symbol_parsed.section_number == lnk_obj_get_removed_section_number(symbol_ref.obj)) { continue; }
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
if (symbol_interp != COFF_SymbolValueInterp_Regular) { continue; }
task->public_symbol_sizes[task_id] += sizeof(CV_SymbolHeader);
task->public_symbol_sizes[task_id] += sizeof(CV_SymPub32);
task->public_symbol_sizes[task_id] += symbol->name.size + 1;
task->public_symbol_sizes[task_id] = AlignPow2(task->public_symbol_sizes[task_id], sizeof(void *));
task->public_symbol_node_counts[task_id] += 1;
}
} }
barrier_wait(tp->barrier); barrier_wait(tp->barrier);
if (task_id == 0) { if (task_id == 0) {
for EachIndex(i, tp->worker_count) { task->public_symbol_sizes[i] += ARENA_HEADER_SIZE; }
U64 public_symbol_buffer_size = sum_array_u64(tp->worker_count, task->public_symbol_sizes);
task->public_symbol_offs = offsets_from_counts_array_u64(scratch.arena, task->public_symbol_sizes, tp->worker_count);
task->public_symbol_buffer = push_array(task->pdb->psi->arena, U8, public_symbol_buffer_size);
U64 public_symbol_total_count = sum_array_u64(tp->worker_count, task->public_symbol_node_counts);
task->public_symbol_node_offsets = offsets_from_counts_array_u64(scratch.arena, task->public_symbol_node_counts, tp->worker_count); task->public_symbol_node_offsets = offsets_from_counts_array_u64(scratch.arena, task->public_symbol_node_counts, tp->worker_count);
U64 public_symbol_total_count = sum_array_u64(tp->worker_count, task->public_symbol_node_offsets);
task->public_symbol_nodes = push_array(psi->gsi->arena, CV_SymbolNode, public_symbol_total_count); task->public_symbol_nodes = push_array(psi->gsi->arena, CV_SymbolNode, public_symbol_total_count);
task->public_symbols = push_array(scratch.arena, CV_SymbolList, tp->worker_count); task->public_symbols = push_array(scratch.arena, CV_SymbolList, tp->worker_count);
task->public_symbols = push_array(scratch.arena, CV_SymbolList, tp->worker_count); task->public_symbol_hashes = push_array(scratch.arena, U32 *, tp->worker_count);
} }
barrier_wait(tp->barrier); barrier_wait(tp->barrier);
// make CV public symbols
U64 public_symbol_buffer_chunk_size = task->public_symbol_sizes[task_id];
U8 *public_symbol_buffer_chunk = task->public_symbol_buffer + task->public_symbol_offs[task_id];
Arena *public_symbol_arena = arena_alloc_(&(ArenaParams){ .flags = ArenaFlag_NoChain, .optional_backing_buffer = public_symbol_buffer_chunk, .reserve_size = public_symbol_buffer_chunk_size, .commit_size = public_symbol_buffer_chunk_size });
for EachNode(chunk, LNK_SymbolHashTrieChunk, task->symtab->chunks[task_id].first) { for EachNode(chunk, LNK_SymbolHashTrieChunk, task->symtab->chunks[task_id].first) {
U64 node_idx = task->public_symbol_node_offsets[task_id]; U64 node_idx = task->public_symbol_node_offsets[task_id];
for EachIndex(i, chunk->count) { for EachIndex(i, chunk->count) {
@@ -1922,47 +1952,46 @@ THREAD_POOL_TASK_FUNC(lnk_process_and_populate_gsi_and_psi_task)
LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol); LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol);
COFF_ParsedSymbol symbol_parsed = lnk_parsed_from_symbol(symbol); COFF_ParsedSymbol symbol_parsed = lnk_parsed_from_symbol(symbol);
// discard removed and non-section symbols
if (symbol_parsed.section_number == lnk_obj_get_removed_section_number(symbol_ref.obj)) { continue; } if (symbol_parsed.section_number == lnk_obj_get_removed_section_number(symbol_ref.obj)) { continue; }
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed); COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
if (symbol_interp != COFF_SymbolValueInterp_Regular) { continue; } if (symbol_interp != COFF_SymbolValueInterp_Regular) { continue; }
CV_Pub32Flags flags = 0; Temp temp = temp_begin(task->fixed_arenas[task_id]);
if (COFF_SymbolType_IsFunc(symbol_parsed.type)) { flags |= CV_Pub32Flag_Function; }
ISectOff sc = lnk_sc_from_symbol(symbol); CV_Pub32Flags flags = COFF_SymbolType_IsFunc(symbol_parsed.type) ? CV_Pub32Flag_Function : 0;
U16 symbol_isect16 = safe_cast_u16(sc.isect); ISectOff sc = lnk_sc_from_symbol(symbol);
U32 symbol_off32 = safe_cast_u32(sc.off); CV_Symbol pub_symbol = cv_make_pub32(temp.arena, flags, safe_cast_u32(sc.off), safe_cast_u16(sc.isect), symbol->name);
String8 pub_raw = cv_data_from_symbol(public_symbol_arena, &pub_symbol, 1);
task->public_symbol_nodes[node_idx].data = cv_make_pub32(arena, flags, symbol_off32, symbol_isect16, symbol->name); task->public_symbol_nodes[node_idx].data = cv_symbol_from_ptr(pub_raw.str);
cv_symbol_list_push_node(&task->public_symbols[task_id], &task->public_symbol_nodes[node_idx]); cv_symbol_list_push_node(&task->public_symbols[task_id], &task->public_symbol_nodes[node_idx]);
node_idx += 1; node_idx += 1;
temp_end(temp);
} }
} }
barrier_wait(tp->barrier); barrier_wait(tp->barrier);
if (task_id == 0) { // hash public symbols
task->public_symbol_hashes = push_array(scratch.arena, U32 *, tp->worker_count);
}
barrier_wait(tp->barrier);
{ {
U64 n_idx = 0; U64 n_idx = 0;
task->public_symbol_hashes[task_id] = push_array(scratch.arena, U32, task->public_symbols[task_id].count); task->public_symbol_hashes[task_id] = push_array(scratch.arena, U32, task->public_symbols[task_id].count);
for EachNode(n, CV_SymbolNode, task->public_symbols[task_id].first) { for EachNode(n, CV_SymbolNode, task->public_symbols[task_id].first) {
String8 name = cv_name_from_symbol(n->data.kind, n->data.data); String8 name = cv_name_from_symbol(n->data.kind, n->data.data);
task->public_symbol_hashes[task_id][n_idx] = gsi_hash(gsi, name); task->public_symbol_hashes[task_id][n_idx++] = gsi_hash(gsi, name);
n += 1;
} }
} }
barrier_wait(tp->barrier); barrier_wait(tp->barrier);
// insert public symbols into PSI
if (task_id == 0) { if (task_id == 0) {
for EachIndex(i, tp->worker_count) { for EachIndex(i, tp->worker_count) {
U64 curr_idx = 0; U64 curr_idx = 0;
for (CV_SymbolNode *curr = task->public_symbols[i].first, *next = 0; curr != 0; curr = next, curr_idx += 1) { for (CV_SymbolNode *curr = task->public_symbols[i].first, *next = 0; curr != 0; curr = next) {
next = curr->next; next = curr->next;
gsi_push_(psi->gsi, task->public_symbol_hashes[i][curr_idx], curr); gsi_push_(psi->gsi, task->public_symbol_hashes[i][curr_idx], curr);
curr_idx += 1;
} }
} }
} }
@@ -2043,6 +2072,8 @@ THREAD_POOL_TASK_FUNC(lnk_write_pdb_module_stream)
CV_Symbol symbol = {0}; CV_Symbol symbol = {0};
TryReadBreak(cv_read_symbol(n->string, cursor, CV_SymbolAlign, &symbol), cursor); TryReadBreak(cv_read_symbol(n->string, cursor, CV_SymbolAlign, &symbol), cursor);
if (symbol.kind == CV_SymKind_SKIP) { continue; }
U64 symbol_size = cv_size_from_symbol(&symbol, PDB_SYMBOL_ALIGN); U64 symbol_size = cv_size_from_symbol(&symbol, PDB_SYMBOL_ALIGN);
// flush temp to MSF // flush temp to MSF
@@ -2194,41 +2225,6 @@ THREAD_POOL_TASK_FUNC(lnk_push_dbi_sec_contrib_task)
} }
} }
internal
THREAD_POOL_TASK_FUNC(lnk_build_pdb_public_symbols_defined_task)
{
ProfBeginFunction();
LNK_BuildPdb *task = raw_task;
for EachNode(chunk, LNK_SymbolHashTrieChunk, task->symtab->chunks[task_id].first) {
CV_SymbolNode *nodes = push_array_no_zero(arena, CV_SymbolNode, chunk->count);
U64 node_idx = 0;
for EachIndex(i, chunk->count) {
LNK_Symbol *symbol = chunk->v[i].symbol;
LNK_ObjSymbolRef symbol_ref = lnk_ref_from_symbol(symbol);
COFF_ParsedSymbol symbol_parsed = lnk_parsed_from_symbol(symbol);
if (symbol_parsed.section_number == lnk_obj_get_removed_section_number(symbol_ref.obj)) { continue; }
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
if (symbol_interp != COFF_SymbolValueInterp_Regular) { continue; }
CV_Pub32Flags flags = 0;
if (COFF_SymbolType_IsFunc(symbol_parsed.type)) { flags |= CV_Pub32Flag_Function; }
ISectOff sc = lnk_sc_from_symbol(symbol);
U16 symbol_isect16 = safe_cast_u16(sc.isect);
U32 symbol_off32 = safe_cast_u32(sc.off);
nodes[node_idx].data = cv_make_pub32(arena, flags, symbol_off32, symbol_isect16, symbol->name);
cv_symbol_list_push_node(&task->pub_list_arr[task_id], &nodes[node_idx]);
node_idx += 1;
}
}
ProfEnd();
}
internal String8List 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_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)
{ {
@@ -2240,10 +2236,11 @@ lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config
U64 obj_count = cv->obj_count; U64 obj_count = cv->obj_count;
LNK_BuildPdb task = { LNK_BuildPdb task = {
.image_data = image_data, .image_data = image_data,
.symtab = symtab, .symtab = symtab,
.cv = cv, .cv = cv,
.pdb = pdb_alloc_(huge_arena_temp.arena, config->pdb_page_size, config->machine, config->time_stamp, config->age, config->guid), .pdb = pdb_alloc_(huge_arena_temp.arena, config->pdb_page_size, config->machine, config->time_stamp, config->age, config->guid),
.fixed_arenas = alloc_fixed_size_arena_array(scratch.arena, tp->worker_count, max_U16, max_U16),
}; };
// set min type indices // set min type indices
@@ -2263,7 +2260,7 @@ lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config
task.serialized_symbol_data_sizes = push_array(scratch.arena, U64, obj_count); task.serialized_symbol_data_sizes = push_array(scratch.arena, U64, obj_count);
ProfScope("Make GSI/PSI") ProfScope("Make GSI/PSI")
{ {
ProfScope("Process & Populate GSI/PSI") tp_for_parallel(tp, 0, tp->worker_count, lnk_process_and_populate_gsi_and_psi_task, &task); ProfScope("Process & Populate GSI/PSI") tp_for_parallel(tp, 0, tp->worker_count, lnk_build_gsi_psi, &task);
ProfBegin("Build and write GSI/PSI"); ProfBegin("Build and write GSI/PSI");
PDB_Context *pdb = task.pdb; PDB_Context *pdb = task.pdb;
@@ -2370,18 +2367,6 @@ lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, String8 image_data, LNK_Config
} }
ProfEnd(); ProfEnd();
ProfBegin("Make Public Symbols");
{
task.pub_list_arr = push_array(scratch.arena, CV_SymbolList, tp->worker_count);
tp_for_parallel_prof(tp, tp_arena, tp->worker_count, lnk_build_pdb_public_symbols_defined_task, &task, "Defined");
ProfBegin("GSI Push");
CV_SymbolPtrArray symbols = cv_symbol_ptr_array_from_list(scratch.arena, tp, tp->worker_count, task.pub_list_arr);
gsi_push_many_arr(tp, task.pdb->psi->gsi, symbols.count, symbols.v);
ProfEnd();
}
ProfEnd();
ProfBegin("Build NatVis"); ProfBegin("Build NatVis");
{ {
String8Array natvis_file_path_arr = str8_array_from_list(scratch.arena, &config->natvis_list); String8Array natvis_file_path_arr = str8_array_from_list(scratch.arena, &config->natvis_list);
+30 -18
View File
@@ -3,7 +3,8 @@
#pragma once #pragma once
// --- Code View Input --------------------------------------------------------- ////////////////////////////////
// CodeView
typedef struct typedef struct
{ {
@@ -48,9 +49,9 @@ typedef struct
B32 *is_type_server_discarded; // [ts_arr.count] B32 *is_type_server_discarded; // [ts_arr.count]
CV_TypeIndex min_type_indices[CV_TypeIndexSource_COUNT]; CV_TypeIndex min_type_indices[CV_TypeIndexSource_COUNT];
U64 symbol_input_count; U64 symbol_input_count;
struct LNK_SymbolInput *symbol_inputs; // [symbol_input_count] LNK_SymbolInput *symbol_inputs; // [symbol_input_count]
Rng1U64 *symbol_input_ranges; // [worker_count] Rng1U64 *symbol_input_ranges; // [worker_count]
} LNK_CodeViewInput; } LNK_CodeViewInput;
typedef struct typedef struct
@@ -60,7 +61,8 @@ typedef struct
CV_DebugT *out_types; // [obj_count] CV_DebugT *out_types; // [obj_count]
} LNK_ParseCvTypes; } LNK_ParseCvTypes;
// --- Leaf Deduping Tasks ----------------------------------------------------- ////////////////////////////////
// Type Merging
typedef struct { U32 obj_idx; U32 leaf_idx; } LNK_LeafRef; typedef struct { U32 obj_idx; U32 leaf_idx; } LNK_LeafRef;
typedef struct { U64 count; LNK_LeafRef **v; } LNK_LeafRefArray; typedef struct { U64 count; LNK_LeafRef **v; } LNK_LeafRefArray;
@@ -123,7 +125,8 @@ typedef struct
LNK_MergedTypes result; LNK_MergedTypes result;
} LNK_MergeTypes; } LNK_MergeTypes;
// --- Build PDB --------------------------------------------- ////////////////////////////////
// PDB
typedef struct typedef struct
{ {
@@ -134,9 +137,10 @@ typedef struct
PDB_Context *pdb; PDB_Context *pdb;
PDB_DbiModule **mod_arr; // [obj_count] PDB_DbiModule **mod_arr; // [obj_count]
U64 total_symbol_count; Arena **fixed_arenas;
// GSI symbol dedup // GSI symbol dedup
U64 global_symbol_count;
U64 bucket_cap; U64 bucket_cap;
void **buckets; // [bucket_count] void **buckets; // [bucket_count]
U64 *insert_count; // [worker_count] U64 *insert_count; // [worker_count]
@@ -146,12 +150,18 @@ typedef struct
void **symbol_arr; void **symbol_arr;
U32 *symbol_hashes; // [symbol_count] U32 *symbol_hashes; // [symbol_count]
U64 *proc_ref_counts; // [worker_count] U64 *proc_ref_counts; // [worker_count]
U64 *proc_ref_sizes; // [worker_count] U64 *proc_ref_sizes; // [worker_count]
U64 *proc_ref_hashes; // [total_proc_ref_count] U64 *proc_ref_hashes; // [total_proc_ref_count]
U64 *proc_ref_offs; // [worker_count] U64 *proc_ref_offs; // [worker_count]
String8 proc_refs; String8 proc_refs;
U64 proc_ref_count;
CV_SymbolNode *proc_ref_nodes; // [proc_ref_count]
Arena *proc_ref_arena;
U64 *public_symbol_sizes; // [worker_count]
U64 *public_symbol_offs; // [worker_count]
U8 *public_symbol_buffer;
U64 *public_symbol_node_counts; // [worker_count] U64 *public_symbol_node_counts; // [worker_count]
U64 *public_symbol_node_offsets; // [worker_count] U64 *public_symbol_node_offsets; // [worker_count]
CV_SymbolNode *public_symbol_nodes; // [public_symbol_total_count] CV_SymbolNode *public_symbol_nodes; // [public_symbol_total_count]
@@ -192,7 +202,8 @@ typedef struct
String8List *maps; String8List *maps;
} LNK_TypeNameReplacer; } LNK_TypeNameReplacer;
// --- RAD Debug Info ---------------------------------------------------------- ////////////////////////////////
// RDI
typedef struct typedef struct
{ {
@@ -219,8 +230,6 @@ typedef struct
CV_TypeIndex *fwdmap; CV_TypeIndex *fwdmap;
} LNK_BuildUDTFwdMapTask; } LNK_BuildUDTFwdMapTask;
// --- RDI Conversion Tasks ----------------------------------------------------
typedef struct typedef struct
{ {
U64 leaf_count[CV_TypeIndexSource_COUNT]; U64 leaf_count[CV_TypeIndexSource_COUNT];
@@ -307,7 +316,8 @@ typedef struct
RDIB_LineTableChunkList *line_tables; RDIB_LineTableChunkList *line_tables;
} LNK_ConvertUnitToRDITask; } LNK_ConvertUnitToRDITask;
// --- CodeView ---------------------------------------------------------------- ////////////////////////////////
// CodeView
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); 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);
@@ -321,11 +331,13 @@ 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 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); 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 --------------------------------------------------------------------- ////////////////////////////////
// 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); 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 --------------------------------------------------------------------- ////////////////////////////////
// RDI
internal U64 lnk_udt_name_hash_table_hash (String8 string); 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_from_leaf_arr(TP_Context *tp, TP_Arena *arena, U64 leaf_count, U8 **leaf_arr, U64 *buckets_cap_out);