centralize canonical COFF object data

This commit is contained in:
Nikita Smith committed 2026-08-24 22:27:20 -07:00
1 parent cf67aca7da
commit 646ff97b3c
6 files changed
+306 -253

No files matched your search

+96 -102
View File
@@ -1221,8 +1221,8 @@ lnk_load_objs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer *
// if machine type was unspecified on the command line, derive it from obj file
if (config->machine == COFF_MachineType_Unknown) {
for EachIndex(obj_idx, new_input_objs.count) {
if (new_objs[obj_idx].data.header.machine != COFF_MachineType_Unknown) {
config->machine = new_objs[obj_idx].data.header.machine;
if (new_objs[obj_idx].data.coff.header.machine != COFF_MachineType_Unknown) {
config->machine = new_objs[obj_idx].data.coff.header.machine;
break;
}
}
@@ -1335,7 +1335,6 @@ lnk_load_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
lnk_obj_list_push_node(&link->objs, include_obj);
}
}
ProfEnd();
}
@@ -2383,8 +2382,8 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
sect_filter |= COFF_SectionFlag_LnkRemove; // skip sections that are discarded from the output
if ( ! lnk_do_debug_info(config)) { sect_filter |= LNK_SECTION_FLAG_DEBUG; } // on /DEBUG:NONE linker never invokes the debug info machinery
for EachIndex(sect_idx, obj->header.section_count_no_null) {
if (obj->section_flags[sect_idx] & sect_filter) { continue; }
for EachIndex(sect_idx, obj->coff.sections.count) {
if (obj->coff.sections.flags[sect_idx] & sect_filter) { continue; }
// unpack section and relocations
COFF_SectionHeader *section_header = &section_table[sect_idx];
@@ -2524,7 +2523,7 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
//
if (lnk_get_log_status(LNK_Log_InputObj)) {
U64 total_input_size = 0;
for (LNK_ObjNode *obj_n = link->objs.first; obj_n != 0; obj_n = obj_n->next) { total_input_size += obj_n->data.data.size; }
for (LNK_ObjNode *obj_n = link->objs.first; obj_n != 0; obj_n = obj_n->next) { total_input_size += obj_n->data.coff.data.size; }
lnk_log(LNK_Log_InputObj, "[Total Obj Input Size %M]", total_input_size);
}
if (lnk_get_log_status(LNK_Log_InputLib)) {
@@ -2607,7 +2606,7 @@ lnk_obj_indices_from_section_counts(Arena *arena, U64 worker_count, LNK_Obj **ob
}
}
worker_section_counts[min_worker_idx] += objs[obj_idx]->header.section_count_no_null;
worker_section_counts[min_worker_idx] += objs[obj_idx]->coff.sections.count;
worker_obj_counts[min_worker_idx] += 1;
}
@@ -2629,7 +2628,7 @@ lnk_obj_indices_from_section_counts(Arena *arena, U64 worker_count, LNK_Obj **ob
U32Array *worker_obj_indices = &obj_indices[min_worker_idx];
worker_obj_indices->v[worker_obj_counts[min_worker_idx]++] = (U32)obj_idx;
worker_obj_indices->count += 1;
worker_section_counts[min_worker_idx] += objs[obj_idx]->header.section_count_no_null;
worker_section_counts[min_worker_idx] += objs[obj_idx]->coff.sections.count;
}
scratch_end(scratch);
@@ -2706,10 +2705,10 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task)
for EachIndex(obj_idx, objs_count) {
LNK_Obj *obj = objs[obj_idx];
is_live[obj_idx] = push_array(scratch.arena, U8, obj->header.section_count_no_null + 1);
is_live[obj_idx] = push_array(scratch.arena, U8, obj->coff.sections.count + 1);
for EachIndex(sect_idx, obj->header.section_count_no_null) {
is_live[obj_idx][sect_idx + 1] = !(obj->section_flags[sect_idx] & COFF_SectionFlag_LnkCOMDAT);
for EachIndex(sect_idx, obj->coff.sections.count) {
is_live[obj_idx][sect_idx + 1] = !(obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_LnkCOMDAT);
}
}
}
@@ -2740,9 +2739,9 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task)
for EachIndex(obj_idx, objs_count) {
LNK_Obj *obj = objs[obj_idx];
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
U32 section_number = sect_idx+1;
COFF_SectionFlags section_flags = obj->section_flags[sect_idx];
COFF_SectionFlags section_flags = obj->coff.sections.flags[sect_idx];
// is section eligible for walking?
if (section_flags & COFF_SectionFlag_LnkRemove) { continue; }
@@ -2807,7 +2806,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task)
for EachNode(section_n, U32Node, associated_sections.first) {
U32 section_number = section_n->data;
COFF_SectionFlags section_flags = ref_symbol.obj->section_flags[section_number-1];
COFF_SectionFlags section_flags = ref_symbol.obj->coff.sections.flags[section_number-1];
// on first section visit, set live flag and enqueue section
U8 was_visited = ins_atomic_u8_eval_assign(&is_live[ref_symbol.obj->input_idx][section_number], 1);
@@ -2874,11 +2873,11 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task)
for EachIndex(obj_idx, objs_count) {
LNK_Obj *obj = objs[obj_idx];
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
U32 section_number = sect_idx+1;
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number);
if ( ! is_live[obj->input_idx][section_number]) {
obj->section_flags[sect_idx] |= COFF_SectionFlag_LnkRemove;
obj->coff.sections.flags[sect_idx] |= COFF_SectionFlag_LnkRemove;
}
}
}
@@ -2891,24 +2890,24 @@ THREAD_POOL_TASK_FUNC(lnk_opt_ref_task)
for EachIndex(obj_idx, objs_count) {
LNK_Obj *obj = objs[obj_idx];
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
U32 section_number = sect_idx+1;
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number);
U64 stat_kind = Stat_Null;
if (obj->section_flags[sect_idx] & LNK_SECTION_FLAG_DEBUG) { stat_kind = Stat_Debug; }
else if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntCode) { stat_kind = Stat_Code; }
if (obj->coff.sections.flags[sect_idx] & LNK_SECTION_FLAG_DEBUG) { stat_kind = Stat_Debug; }
else if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntCode) { stat_kind = Stat_Code; }
else { stat_kind = Stat_Data; }
if (is_live[obj->input_idx][section_number]) {
stats[stat_kind].live_count += 1;
if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntUninitializedData) {
if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntUninitializedData) {
stats[stat_kind].live_vsize += section_header->vsize;
} else {
stats[stat_kind].live_fsize += section_header->fsize;
}
} else {
if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntUninitializedData) {
if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntUninitializedData) {
stats[stat_kind].vsize += section_header->vsize;
} else {
stats[stat_kind].fsize += section_header->fsize;
@@ -2979,16 +2978,16 @@ lnk_icf_scope_from_section(LNK_Obj *obj, U32 sect_idx)
// * section flags filter *
COFF_SectionFlags expected_flags = COFF_SectionFlag_LnkCOMDAT | COFF_SectionFlag_MemRead;
COFF_SectionFlags exclude_flags = COFF_SectionFlag_LnkRemove | COFF_SectionFlag_MemWrite | LNK_SECTION_FLAG_NOICF;
if ((obj->section_flags[sect_idx] & expected_flags) != expected_flags || (obj->section_flags[sect_idx] & exclude_flags) != 0) {
if ((obj->coff.sections.flags[sect_idx] & expected_flags) != expected_flags || (obj->coff.sections.flags[sect_idx] & exclude_flags) != 0) {
goto exit;
}
if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntCode) {
if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntCode) {
result = LNK_ICF_Scope_Code;
goto exit;
}
if (obj->section_flags[sect_idx] & COFF_SectionFlag_CntInitializedData) {
if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_CntInitializedData) {
U64 section_number = sect_idx + 1;
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number);
String8 section_name = str8_cstring_capped(section_header->name, section_header->name + sizeof(section_header->name));
@@ -3043,7 +3042,7 @@ lnk_icf_scope_from_section(LNK_Obj *obj, U32 sect_idx)
}
exit:;
Assert(result == LNK_ICF_Scope_Null || obj->comdats[sect_idx] != max_U32); // TODO: are symlinks on COMDATs optional?
Assert(result == LNK_ICF_Scope_Null || obj->coff.sections.comdats[sect_idx] != max_U32); // TODO: are symlinks on COMDATs optional?
return result;
}
@@ -3118,39 +3117,36 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task)
if (task->config->llvm_addrsig == LNK_SwitchState_Yes) {
ProfBegin("Flag significant sections");
// .llvm_addrsig is an array of ULEB128 symbol indices, which mark sections
// whose addresses are significant
for EachIndex(i, task->obj_indices[task_id].count) {
U64 obj_idx = task->obj_indices[task_id].v[i];
LNK_Obj *obj = task->objs[obj_idx];
if (obj->llvm_addrsig_sect_idx >= obj->header.section_count_no_null) { continue; }
String8 symbol_table = lnk_coff_symbol_table_from_obj(obj);
String8 string_table = lnk_coff_string_table_from_obj(obj);
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, obj->llvm_addrsig_sect_idx + 1);
String8 section_data = str8_substr(obj->data, r1u64s(section_header->foff, section_header->fsize));
if (obj->coff.llvm_addrsig_sect_idx >= obj->coff.sections.count) { continue; }
// parse symbol indices and mark selected sections with NOICF flag,
// the selected symbols maybe undefined/weak which need to be resolved
String8 section_data = lnk_obj_section_data_from_sect_idx(obj, obj->coff.llvm_addrsig_sect_idx);
for (U64 off = 0; off < section_data.size;) {
U64 symbol_off = off;
U64 symbol_idx = 0;
off += str8_deserial_read_uleb128(section_data, off, &symbol_idx);
if (symbol_off == off) { break; }
if (symbol_idx < obj->header.symbol_count) {
if (symbol_idx < obj->coff.header.symbol_count) {
LNK_ObjSymbolRef target_ref = { .obj = obj, .symbol_idx = symbol_idx };
B32 is_symbol_found = lnk_resolve_reloc_target_symbol(scratch.arena, task->symtab, target_ref, str8_lit("/OPT:ICF"), &target_ref);
if (is_symbol_found) {
COFF_ParsedSymbol symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(target_ref.obj, target_ref.symbol_idx);
if (coff_interp_from_parsed_symbol(symbol) == COFF_SymbolValueInterp_Regular) {
target_ref.obj->section_flags[symbol.section_number - 1] |= LNK_SECTION_FLAG_NOICF;
target_ref.obj->coff.sections.flags[symbol.section_number - 1] |= LNK_SECTION_FLAG_NOICF;
}
} else {
COFF_ParsedSymbol original_symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
if (coff_interp_from_parsed_symbol(original_symbol) == COFF_SymbolValueInterp_Regular) {
obj->section_flags[original_symbol.section_number - 1] |= LNK_SECTION_FLAG_NOICF;
obj->coff.sections.flags[original_symbol.section_number - 1] |= LNK_SECTION_FLAG_NOICF;
} else {
lnk_log(LNK_Log_Debug, "%S: .llvm_addrsig: contains an unresolved symbol index 0x%x at offset 0x%x", lnk_loc_from_obj(scratch.arena, obj), symbol_idx, symbol_off);
}
@@ -3179,7 +3175,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task)
for EachIndex(i, task->obj_indices[task_id].count) {
U64 obj_idx = task->obj_indices[task_id].v[i];
LNK_Obj *obj = objs[obj_idx];
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
if (lnk_icf_scope_from_section(obj, sect_idx)) {
contrib_counts[obj_idx] += 1;
}
@@ -3209,13 +3205,13 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task)
U64 noncontrib_count = 0;
for EachIndex(obj_idx, task->objs_count) {
shared.noncontrib_offsets[obj_idx] = noncontrib_count;
noncontrib_count += objs[obj_idx]->header.section_count_no_null - contrib_counts[obj_idx];
noncontrib_count += objs[obj_idx]->coff.sections.count - contrib_counts[obj_idx];
}
shared.color_map = push_array(scratch.arena, U64 *, task->objs_count);
for EachIndex(obj_idx, task->objs_count) {
LNK_Obj *obj = objs[obj_idx];
shared.color_map[obj_idx] = push_array(scratch.arena, U64, obj->header.section_count_no_null);
shared.color_map[obj_idx] = push_array(scratch.arena, U64, obj->coff.sections.count);
}
shared.contrib_offsets = offsets_from_counts_array_u64(scratch.arena, contrib_counts, task->objs_count);
@@ -3240,7 +3236,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task)
LNK_Obj *obj = objs[obj_idx];
U64 cursor = 0;
U64 noncontrib_cursor = 0;
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
LNK_ICF_Scope scope = lnk_icf_scope_from_section(obj, sect_idx);
if (scope == LNK_ICF_Scope_Null) {
// assign colors in object order to avoid a contended atomic allocator
@@ -3278,7 +3274,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task)
U64 reloc_cursor = 0;
for EachNode(associated_n, U32Node, associated_sections.first) {
COFF_SectionHeader *associated_header = lnk_coff_section_header_from_section_number(obj, associated_n->data);
String8 associated_data = str8_substr(obj->data, r1u64s(associated_header->foff, associated_header->fsize));
String8 associated_data = lnk_obj_section_data_from_sect_idx(obj, associated_n->data - 1);
COFF_RelocArray associated_relocs = lnk_coff_relocs_from_section_header(obj, associated_header);
lnk_hasher_update_string(&hasher, associated_data);
@@ -3306,12 +3302,12 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task)
U32 target_sect = target_symbol.section_number;
// use the selected COMDAT leader so equivalent targets hash alike
if (target_sect != 0 && target_sect <= target_obj->header.section_count_no_null &&
target_obj->section_flags[target_sect - 1] & COFF_SectionFlag_LnkCOMDAT) {
if (target_sect != 0 && target_sect <= target_obj->coff.sections.count &&
target_obj->coff.sections.flags[target_sect - 1] & COFF_SectionFlag_LnkCOMDAT) {
LNK_ObjSymbolRef leader_ref = {0};
if (lnk_obj_get_comdat_symlink(target_obj, target_sect, &leader_ref)) {
COFF_ParsedSymbol leader_symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(leader_ref.obj, leader_ref.symbol_idx);
if (leader_symbol.section_number != 0 && leader_symbol.section_number <= leader_ref.obj->header.section_count_no_null) {
if (leader_symbol.section_number != 0 && leader_symbol.section_number <= leader_ref.obj->coff.sections.count) {
target_obj = leader_ref.obj;
target_sect = leader_symbol.section_number;
}
@@ -3606,8 +3602,8 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task)
// TODO: double-check if discarded section headers should be updated with leaders' alignment,
// leaders at this point are resolved
U64 contrib_align = coff_align_size_from_section_flags(contrib_obj->section_flags[contrib->sect_idx]);
COFF_SectionFlags *leader_flags = &leader_obj->section_flags[leader->sect_idx];
U64 contrib_align = coff_align_size_from_section_flags(contrib_obj->coff.sections.flags[contrib->sect_idx]);
COFF_SectionFlags *leader_flags = &leader_obj->coff.sections.flags[leader->sect_idx];
for (COFF_SectionFlags old_flags = ins_atomic_u32_eval((U32 *)leader_flags);;) {
U64 leader_align = coff_align_size_from_section_flags(old_flags);
if (leader_align >= contrib_align) { break; }
@@ -3622,10 +3618,10 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task)
}
// remove folded section from the image
contrib_obj->section_flags[contrib->sect_idx] |= COFF_SectionFlag_LnkRemove;
contrib_obj->coff.sections.flags[contrib->sect_idx] |= COFF_SectionFlag_LnkRemove;
// update folded section COMDAT symlink to point to the leader section
contrib_obj->symlinks[contrib->sect_idx + 1] = (LNK_ObjSymbolRef){ leader_obj, leader_obj->comdats[leader->sect_idx] };
contrib_obj->symlinks[contrib->sect_idx + 1] = (LNK_ObjSymbolRef){ leader_obj, leader_obj->coff.sections.comdats[leader->sect_idx] };
#if LNK_PARANOID
String8 section_name = lnk_obj_section_name_from_section_number(contrib_obj, contrib->sect_idx+1);
@@ -3691,7 +3687,7 @@ THREAD_POOL_TASK_FUNC(lnk_opt_icf_task)
for EachIndex(i, task->obj_indices[task_id].count) {
U64 obj_idx = task->obj_indices[task_id].v[i];
LNK_Obj *obj = objs[obj_idx];
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
U64 section_number = sect_idx + 1;
LNK_ObjSymbolRef symlink_ref = {0};
@@ -3758,7 +3754,7 @@ lnk_section_definition_is_before(void *raw_a, void *raw_b)
internal B32
lnk_should_gather_section(LNK_Obj *obj, U64 sect_idx, COFF_SectionHeader *sect_header)
{
COFF_SectionFlags sect_flags = obj->section_flags[sect_idx];
COFF_SectionFlags sect_flags = obj->coff.sections.flags[sect_idx];
// removed sections were eliminated before image layout
if (sect_flags & COFF_SectionFlag_LnkRemove) {
@@ -3801,10 +3797,10 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task)
ProfBegin("Gather Section Definitions");
for EachInRange(obj_idx, range) {
LNK_Obj *obj = task->objs[obj_idx];
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str;
String8 string_table = str8_substr(obj->data, obj->header.string_table_range);
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->coff.data, obj->coff.header.section_table_range).str;
String8 string_table = str8_substr(obj->coff.data, obj->coff.header.string_table_range);
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
COFF_SectionHeader *sect_header = &section_table[sect_idx];
if ( ! lnk_should_gather_section(obj, sect_idx, sect_header)) { continue; }
@@ -3812,7 +3808,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task)
Temp temp = temp_begin(scratch.arena);
// was section defined?
COFF_SectionFlags image_sect_flags = obj->section_flags[sect_idx] & ~(COFF_SectionFlags_LnkFlags | COFF_SectionFlags_Reserved);
COFF_SectionFlags image_sect_flags = obj->coff.sections.flags[sect_idx] & ~(COFF_SectionFlags_LnkFlags | COFF_SectionFlags_Reserved);
String8 sect_name = coff_name_from_section_header(string_table, sect_header);
image_sect_flags = lnk_apply_section_directives_to_flags(task->config, sect_name, image_sect_flags);
String8 sect_name_with_flags = lnk_make_name_with_flags(temp.arena, sect_name, image_sect_flags);
@@ -3893,7 +3889,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task)
LNK_Obj *obj = sect_defn->obj;
U32 sect_number = sect_defn->obj_sect_idx + 1;
COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, sect_number);
String8 sect_name = coff_name_from_section_header(str8_substr(obj->data, obj->header.string_table_range), sect_header);
String8 sect_name = coff_name_from_section_header(str8_substr(obj->coff.data, obj->coff.header.string_table_range), sect_header);
String8 expected_flags_str = coff_string_from_section_flags(main_arena, sect_n->data.flags);
String8 current_flags_str = coff_string_from_section_flags(main_arena, sect_defn->flags);
lnk_error_obj(LNK_Warning_SectionFlagsConflict, sect_defn->obj, "detected section flags conflict in %S(No. %X); expected {%S} but got {%S}", sect_name, sect_number, expected_flags_str, current_flags_str);
@@ -3922,7 +3918,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task)
ProfBegin("Alloc Section Map");
task->sect_map = push_array(main_arena, LNK_SectionContrib **, task->objs_count);
for EachIndex(obj_idx, task->objs_count) { task->sect_map[obj_idx] = push_array(main_arena, LNK_SectionContrib *, task->objs[obj_idx]->header.section_count_no_null); }
for EachIndex(obj_idx, task->objs_count) { task->sect_map[obj_idx] = push_array(main_arena, LNK_SectionContrib *, task->objs[obj_idx]->coff.sections.count); }
ProfEnd();
}
@@ -3931,14 +3927,14 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task)
ProfBegin("Gather Section Contribs");
for EachInRange(obj_idx, range) {
LNK_Obj *obj = task->objs[obj_idx];
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->data, obj->header.section_table_range).str;
String8 string_table = str8_substr(obj->data, obj->header.string_table_range);
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(obj->coff.data, obj->coff.header.section_table_range).str;
String8 string_table = str8_substr(obj->coff.data, obj->coff.header.string_table_range);
ProfBeginV("Gather Section Contribs [%S]", obj->path);
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
LNK_SectionContrib *sc = task->null_sc;
COFF_SectionHeader *sect_header = &section_table[sect_idx];
COFF_SectionFlags sect_flags = obj->section_flags[sect_idx];
COFF_SectionFlags sect_flags = obj->coff.sections.flags[sect_idx];
task->sect_map[obj_idx][sect_idx] = sc;
if ( ! lnk_should_gather_section(obj, sect_idx, sect_header)) { continue; }
@@ -3959,7 +3955,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_sections_task)
if (sect_flags & COFF_SectionFlag_CntUninitializedData) {
data = str8(0, sect_header->fsize);
} else {
data = str8_substr(obj->data, rng_1u64(sect_header->foff, sect_header->foff + sect_header->fsize));
data = lnk_obj_section_data_from_sect_idx(obj, sect_idx);
}
U16 sc_align = coff_align_size_from_section_flags(sect_flags);
@@ -3988,10 +3984,10 @@ THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_contribs_task)
LNK_Obj *obj = task->objs[obj_idx];
ProfBeginV("Set COMDAT Section Contribs [%S]", obj->path);
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
U64 section_number = sect_idx+1;
if (~obj->section_flags[sect_idx] & COFF_SectionFlag_LnkCOMDAT) { continue; }
if (~obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_LnkCOMDAT) { continue; }
LNK_ObjSymbolRef symlink_ref = {0};
if ( ! lnk_obj_get_comdat_symlink(obj, section_number, &symlink_ref)) { continue; }
@@ -4010,11 +4006,11 @@ THREAD_POOL_TASK_FUNC(lnk_flag_debug_symbols_task)
LNK_Obj *obj = task->objs[obj_idx];
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular) {
if (obj->section_flags[symbol.section_number-1] & LNK_SECTION_FLAG_DEBUG) {
if (obj->coff.sections.flags[symbol.section_number-1] & LNK_SECTION_FLAG_DEBUG) {
task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx] = 1;
}
}
@@ -4030,7 +4026,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_comdat_leaders_task)
ProfBeginV("Patch COMDAT Offsets in %S", obj->path);
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol);
@@ -4050,7 +4046,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_comdat_leaders_task)
B32 should_patch = 0;
if (is_same_obj) {
B32 is_static_comdat_leader = symbol.storage_class == COFF_SymStorageClass_Static && obj->comdats[symbol.section_number-1] == symbol_idx;
B32 is_static_comdat_leader = symbol.storage_class == COFF_SymStorageClass_Static && obj->coff.sections.comdats[symbol.section_number-1] == symbol_idx;
if (is_external || is_static_comdat_leader) {
section_number = leader_symbol.section_number;
value = leader_symbol.value;
@@ -4256,7 +4252,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_common_block_symbols_task)
ProfBeginV("Patch Common Block Symbols [%S]", obj->path);
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Common) {
@@ -4283,7 +4279,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_regular_symbols_task)
ProfBeginV("Patch Regular Symbols [%S]", obj->path);
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
if (task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx]) { continue; }
@@ -4315,7 +4311,7 @@ lnk_patch_obj_symtab(LNK_SymbolTable *symtab, LNK_Obj *obj, B8 *was_symbol_patch
ProfBeginV("%S\n", obj->path);
COFF_ParsedSymbol fixup_dst;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + fixup_dst.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + fixup_dst.aux_symbol_count)) {
fixup_dst = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
if (was_symbol_patched[symbol_idx]) { continue; }
@@ -4422,7 +4418,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher)
LNK_ObjRelocPatcher *task = raw_task;
LNK_Obj *obj = task->objs[task_id];
COFF_FileHeaderInfo obj_header = obj->header;
COFF_FileHeaderInfo obj_header = obj->coff.header;
COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj);
String8 symbol_table = lnk_coff_symbol_table_from_obj(obj);
String8 string_table = lnk_coff_string_table_from_obj(obj);
@@ -4433,16 +4429,15 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher)
for EachIndex(sect_idx, obj_header.section_count_no_null) {
COFF_SectionHeader *section_header = &section_table[sect_idx];
COFF_SectionFlags section_flags = obj->section_flags[sect_idx];
COFF_SectionFlags section_flags = obj->coff.sections.flags[sect_idx];
if (section_flags & COFF_SectionFlag_LnkInfo) { continue; }
if (section_flags & COFF_SectionFlag_LnkRemove) { continue; }
if (section_flags & COFF_SectionFlag_CntUninitializedData) { continue; }
// get section bytes (special case debug info because it is not copied to the image)
String8 data = section_flags & LNK_SECTION_FLAG_DEBUG ? obj->data : task->image_data;
Rng1U64 section_frange = rng_1u64(section_header->foff, section_header->foff + section_header->fsize);
String8 section_data = str8_substr(data, section_frange);
String8 section_data = section_flags & LNK_SECTION_FLAG_DEBUG ? lnk_obj_section_data_from_sect_idx(obj, sect_idx) : str8_substr(task->image_data, section_frange);
// apply relocs
COFF_RelocArray relocs = lnk_coff_relocs_from_section_header(obj, section_header);
@@ -4450,12 +4445,12 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher)
COFF_Reloc *reloc = &relocs.v[reloc_idx];
// error check relocation
if (obj->header.machine == COFF_MachineType_X64) {
if (obj->coff.header.machine == COFF_MachineType_X64) {
if (reloc->type > COFF_Reloc_X64_Last) {
lnk_error_obj(LNK_Error_IllegalRelocation, obj, "unknown relocation type 0x%x", reloc->type);
}
} else if (obj->header.machine != COFF_MachineType_Unknown) {
lnk_not_implemented("relocation patching is not implemented for %S", coff_string_from_machine_type(obj->header.machine));
} else if (obj->coff.header.machine != COFF_MachineType_Unknown) {
lnk_not_implemented("relocation patching is not implemented for %S", coff_string_from_machine_type(obj->coff.header.machine));
continue;
}
@@ -4571,15 +4566,15 @@ THREAD_POOL_TASK_FUNC(lnk_flag_hotpatch_contribs_task)
U64 obj_idx = task_id;
LNK_Obj *obj = task->objs[obj_idx];
if (obj->hotpatch) {
if (obj->coff.hotpatch) {
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular && COFF_SymbolType_IsFunc(symbol.type)) {
LNK_SectionContrib *sc = task->sect_map[obj_idx][symbol.section_number-1];
if (sc != task->null_sc) {
sc->hotpatch = !!(obj->section_flags[symbol.section_number-1] & COFF_SectionFlag_CntCode);
sc->hotpatch = !!(obj->coff.sections.flags[symbol.section_number-1] & COFF_SectionFlag_CntCode);
}
}
}
@@ -4941,9 +4936,9 @@ THREAD_POOL_TASK_FUNC(lnk_patch_virtual_offsets_and_sizes_in_obj_section_headers
ProfBeginV("Patch Virtual Offset And Size In Section Headers [%S]", obj->path);
COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj);
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) {
COFF_SectionHeader *sect_header = &section_table[sect_idx];
if (~obj->section_flags[sect_idx] & COFF_SectionFlag_LnkRemove) {
if (~obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_LnkRemove) {
LNK_SectionContrib *sc = task->sect_map[obj_idx][sect_idx];
LNK_Section *sect = task->image_sects.v[sc->u.sect_idx];
sect_header->vsize = lnk_size_from_section_contrib(sc);
@@ -4962,9 +4957,9 @@ THREAD_POOL_TASK_FUNC(lnk_patch_file_offsets_and_sizes_in_obj_section_headers_ta
ProfBeginV("Patch File Offsets And Sizes In Obj Section Headers [%S]", obj->path);
COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj);
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) {
COFF_SectionHeader *sect_header = &section_table[sect_idx];
COFF_SectionFlags sect_flags = obj->section_flags[sect_idx];
COFF_SectionFlags sect_flags = obj->coff.sections.flags[sect_idx];
B32 patch_section_header = (~sect_flags & COFF_SectionFlag_LnkRemove) &&
(~sect_flags & LNK_SECTION_FLAG_DEBUG);
if (patch_section_header) {
@@ -4988,16 +4983,16 @@ THREAD_POOL_TASK_FUNC(lnk_patch_section_symbols_task)
ProfBegin("Patch Section Symbols [%S]", obj->path);
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Undefined) {
if (symbol.storage_class == COFF_SymStorageClass_Section) {
B32 is_referenced = 0;
COFF_SectionHeader *section_table = lnk_coff_section_table_from_obj(obj);
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
COFF_SectionHeader *section_header = &section_table[sect_idx];
COFF_SectionFlags section_flags = obj->section_flags[sect_idx];
COFF_SectionFlags section_flags = obj->coff.sections.flags[sect_idx];
if (section_flags & COFF_SectionFlag_LnkRemove) { continue; }
if (section_flags & COFF_SectionFlag_LnkInfo) { continue; }
if (section_flags & LNK_SECTION_FLAG_DEBUG) { continue; }
@@ -5061,9 +5056,9 @@ THREAD_POOL_TASK_FUNC(lnk_gather_base_reloc_pages_task)
COFF_SectionHeader *sect_table = lnk_coff_section_table_from_obj(obj);
ProfBeginV("%S", obj->path);
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
COFF_SectionHeader *sect_header = &sect_table[sect_idx];
if (obj->section_flags[sect_idx] & COFF_SectionFlag_LnkRemove) { continue; }
if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_LnkRemove) { continue; }
COFF_RelocArray relocs = lnk_coff_relocs_from_section_header(obj, sect_header);
for EachIndex(reloc_idx, relocs.count) {
@@ -5073,7 +5068,7 @@ THREAD_POOL_TASK_FUNC(lnk_gather_base_reloc_pages_task)
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol);
if (symbol_interp == COFF_SymbolValueInterp_Abs) { continue; }
U64 is_addr = coff_is_addr_reloc(obj->header.machine, r->type);
U64 is_addr = coff_is_addr_reloc(obj->coff.header.machine, r->type);
if (is_addr == 0) { continue; }
U64 reloc_voff = sect_header->voff + r->apply_off;
@@ -5759,7 +5754,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
task.u.patch_symtabs.common_block_ranges = tp_divide_work(temp.arena, common_block_contribs_count, tp->worker_count);
task.u.patch_symtabs.common_block_contribs = common_block_contribs;
task.u.patch_symtabs.was_symbol_patched = push_array(temp.arena, B8 *, objs_count);
for EachIndex(obj_idx, objs_count) { task.u.patch_symtabs.was_symbol_patched[obj_idx] = push_array(temp.arena, B8, objs[obj_idx]->header.symbol_count); }
for EachIndex(obj_idx, objs_count) { task.u.patch_symtabs.was_symbol_patched[obj_idx] = push_array(temp.arena, B8, objs[obj_idx]->coff.header.symbol_count); }
// flag debug symbols to prevent them from being patched in subsequent passes
tp_for_parallel_prof(tp, 0, objs_count, lnk_flag_debug_symbols_task, &task, "Flag Debug Symbols");
@@ -6139,15 +6134,15 @@ lnk_obj_sect_idx_from_section(Arena *arena, U64 objs_count, LNK_Obj **objs, LNK_
PairU32 *obj_sect_idxs = push_array(arena, PairU32, max_contribs);
for (U64 obj_idx = 0; obj_idx < objs_count; obj_idx += 1) {
LNK_Obj *obj = objs[obj_idx];
COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->data, obj->header.section_table_range.min, 0);
String8 string_table = str8_substr(obj->data, obj->header.string_table_range);
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->coff.data, obj->coff.header.section_table_range.min, 0);
String8 string_table = str8_substr(obj->coff.data, obj->coff.header.string_table_range);
for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) {
COFF_SectionHeader *section_header = &section_table[sect_idx];
String8 full_section_name = coff_name_from_section_header(string_table, section_header);
String8 section_name, section_postfix;
coff_parse_section_name(full_section_name, &section_name, &section_postfix);
if (obj->section_flags[sect_idx] & COFF_SectionFlag_LnkRemove) { continue; }
if (obj->coff.sections.flags[sect_idx] & COFF_SectionFlag_LnkRemove) { continue; }
if (section_header->fsize == 0) { continue; }
if (lnk_is_section_removed(config, section_name)) { continue; }
@@ -6172,7 +6167,7 @@ internal COFF_SectionHeader *
lnk_coff_section_header_from_obj_sect_idx_pair(LNK_Obj **objs, PairU32 p)
{
LNK_Obj *obj = objs[p.v0];
COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->data, obj->header.section_table_range.min, 0);
COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->coff.data, obj->coff.header.section_table_range.min, 0);
return &section_table[p.v1];
}
@@ -6287,7 +6282,7 @@ lnk_build_rad_map(Arena *arena, String8 image_data, LNK_Config *config, U64 objs
String8List source_list = {0};
if (obj) {
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, sect_idx+1);
String8 string_table = str8_substr(obj->data, obj->header.string_table_range);
String8 string_table = str8_substr(obj->coff.data, obj->coff.header.string_table_range);
String8 section_name = coff_name_from_section_header(string_table, section_header);
LNK_Lib *lib = lnk_obj_get_lib(obj);
if (lib) {
@@ -6315,10 +6310,10 @@ lnk_build_rad_map(Arena *arena, String8 image_data, LNK_Config *config, U64 objs
str8_list_pushf(arena, &map, "# DEBUG\n");
for (U64 obj_idx = 0; obj_idx < objs_count; obj_idx += 1) {
LNK_Obj *obj = objs[obj_idx];
COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->data, obj->header.section_table_range.min, 0);
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
COFF_SectionHeader *section_table = str8_deserial_get_raw_ptr(obj->coff.data, obj->coff.header.section_table_range.min, 0);
for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) {
COFF_SectionHeader *section_header = &section_table[sect_idx];
COFF_SectionFlags section_flags = obj->section_flags[sect_idx];
COFF_SectionFlags section_flags = obj->coff.sections.flags[sect_idx];
if (~section_flags & COFF_SectionFlag_LnkRemove && section_flags & LNK_SECTION_FLAG_DEBUG) {
LNK_Lib *lib = lnk_obj_get_lib(obj);
if (lib) {
@@ -6812,12 +6807,11 @@ lnk_run_type_server(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
if (obj->link_member) { continue; }
// does obj have debug types?
if (obj->debug_p_sect_idx < obj->header.section_count_no_null) {
if (obj->coff.debug_p_sect_idx < obj->coff.sections.count) {
u64_list_push(scratch.arena, &include_obj_list, obj_idx);
} else if (obj->debug_t_sect_idx < obj->header.section_count_no_null) {
} else if (obj->coff.debug_t_sect_idx < obj->coff.sections.count) {
// read first leaf
LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx);
String8 raw_debug_t = str8_substr(obj->data, section.frange);
String8 raw_debug_t = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_t_sect_idx);
CV_Leaf leaf = {0};
cv_read_leaf(raw_debug_t, 0, 1, &leaf);
+20 -23
View File
@@ -76,10 +76,8 @@ THREAD_POOL_TASK_FUNC(lnk_parse_debug_h_task)
LNK_CodeViewInput *task = raw_task;
LNK_Obj *obj = task->obj_arr[obj_idx];
if (obj->debug_h_sect_idx < obj->header.section_count_no_null) {
LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, obj->debug_h_sect_idx);
String8 raw_debug_h = str8_substr(obj->data, section.frange);
if (obj->coff.debug_h_sect_idx < obj->coff.sections.count) {
String8 raw_debug_h = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_h_sect_idx);
CV_DebugH *debug_h = &task->debug_h_arr[obj_idx];
LLVM_GHash ghash = {0};
U64 ghash_read_size = str8_deserial_read_struct(raw_debug_h, 0, &ghash);
@@ -599,6 +597,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
}
// unpack type data
type_data_raw = push_str8_copy(arena, type_data_raw);
String8 type_data[CV_TypeIndexSource_COUNT] = {0};
for EachIndex(ti_source, CV_TypeIndexSource_COUNT) {
type_data[ti_source] = str8_substr(type_data_raw, type_data_ranges[ti_source]);
@@ -700,9 +699,9 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config,
if (rrt->obj_time_stamps[rrt_obj_idx] != obj_file_props.modified) { continue; }
// invalidate debug section pointers
obj->debug_t_sect_idx = ~0;
obj->debug_p_sect_idx = ~0;
obj->debug_h_sect_idx = ~0;
obj->coff.debug_t_sect_idx = ~0;
obj->coff.debug_p_sect_idx = ~0;
obj->coff.debug_h_sect_idx = ~0;
// apply type index map
obj->ti_range = rrt->obj_ti_ranges[rrt_obj_idx];
@@ -734,15 +733,15 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config,
for EachNode(n, String8Node, input.debug_s_list_arr[obj_idx].first) { total_debug_s_size += n->string.size; }
if (obj->debug_t_sect_idx < obj->header.section_count_no_null) {
total_debug_t_size += lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx).header->fsize;
if (obj->coff.debug_t_sect_idx < obj->coff.sections.count) {
total_debug_t_size += lnk_obj_section_from_sect_idx(obj, obj->coff.debug_t_sect_idx).header->fsize;
}
if (obj->debug_p_sect_idx < obj->header.section_count_no_null) {
total_debug_p_size += lnk_obj_section_from_sect_idx(obj, obj->debug_p_sect_idx).header->fsize;
if (obj->coff.debug_p_sect_idx < obj->coff.sections.count) {
total_debug_p_size += lnk_obj_section_from_sect_idx(obj, obj->coff.debug_p_sect_idx).header->fsize;
}
if (config->ghash) {
if (obj->debug_h_sect_idx < obj->header.section_count_no_null) {
total_debug_h_size += lnk_obj_section_from_sect_idx(obj, obj->debug_h_sect_idx).header->fsize;
if (obj->coff.debug_h_sect_idx < obj->coff.sections.count) {
total_debug_h_size += lnk_obj_section_from_sect_idx(obj, obj->coff.debug_h_sect_idx).header->fsize;
}
}
}
@@ -784,18 +783,16 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config,
for EachIndex(obj_idx, obj_count) {
LNK_Obj *obj = obj_arr[obj_idx];
if (obj->debug_t_sect_idx < obj->header.section_count_no_null) {
LNK_ObjSection debug_t_sect = lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx);
if (obj->coff.debug_t_sect_idx < obj->coff.sections.count) {
raw_debug_t_arr[obj_idx].count = 1;
raw_debug_t_arr[obj_idx].v = push_array(scratch.arena, String8, 1);
raw_debug_t_arr[obj_idx].v[0] = str8_substr(obj->data, debug_t_sect.frange);
raw_debug_t_arr[obj_idx].v[0] = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_t_sect_idx);
}
if (obj->debug_p_sect_idx < obj->header.section_count_no_null) {
LNK_ObjSection debug_p_sect = lnk_obj_section_from_sect_idx(obj, obj->debug_p_sect_idx);
if (obj->coff.debug_p_sect_idx < obj->coff.sections.count) {
raw_debug_p_arr[obj_idx].count = 1;
raw_debug_p_arr[obj_idx].v = push_array(scratch.arena, String8, 1);
raw_debug_p_arr[obj_idx].v[0] = str8_substr(obj->data, debug_p_sect.frange);
raw_debug_p_arr[obj_idx].v[0] = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_p_sect_idx);
}
}
@@ -2852,13 +2849,13 @@ THREAD_POOL_TASK_FUNC(lnk_push_dbi_sec_contrib_task)
LNK_Obj *obj = task->cv->obj_arr[obj_idx];
PDB_DbiSCArray *sc_array = &task->sc_arrays[obj_idx];
sc_array->v = push_array_no_zero(arena, PDB_DbiSC, obj->header.section_count_no_null);
sc_array->cap = obj->header.section_count_no_null;
sc_array->v = push_array_no_zero(arena, PDB_DbiSC, obj->coff.sections.count);
sc_array->cap = obj->coff.sections.count;
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
// filter by section flags
if (obj->section_flags[sect_idx] & (COFF_SectionFlag_LnkInfo | COFF_SectionFlag_LnkRemove | LNK_SECTION_FLAG_DEBUG)) { continue; }
if (obj->coff.sections.flags[sect_idx] & (COFF_SectionFlag_LnkInfo | COFF_SectionFlag_LnkRemove | LNK_SECTION_FLAG_DEBUG)) { continue; }
// skip unwind info for the section contribution
String8 section_name = lnk_obj_section_name_from_sect_idx(obj, sect_idx);
+128 -86
View File
@@ -156,6 +156,13 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
}
}
String8 *section_data = push_array(arena, String8, header.section_count_no_null);
for EachIndex(sect_idx, header.section_count_no_null) {
COFF_SectionHeader *sect_header = &coff_section_table[sect_idx];
String8 data = str8_substr(input->data, r1u64s(sect_header->foff, sect_header->fsize));
section_data[sect_idx] = section_flags[sect_idx] & LNK_SECTION_FLAG_DEBUG ? push_str8_copy(arena, data) : data;
}
//
// error check symbol table and cache name lengths for primary symbols
//
@@ -168,38 +175,46 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
}
}
U64 symbol_block_count = CeilIntegerDiv(header.symbol_count, 64);
U64 symbol_block_count = CeilIntegerDiv(header.symbol_count, 64);
LNK_ObjSymbolArray symbols = {
.count = primary_symbol_count,
.primary_masks = push_array(arena, U64, symbol_block_count),
.block_bases = push_array_no_zero(arena, U32, symbol_block_count),
.values = push_array_no_zero(arena, U64, primary_symbol_count),
.section_numbers = push_array_no_zero(arena, U32, primary_symbol_count),
.types = push_array_no_zero(arena, COFF_SymbolType, primary_symbol_count),
.block_bases = push_array_no_zero(arena, U32, symbol_block_count),
.values = push_array_no_zero(arena, U64, primary_symbol_count),
.section_numbers = push_array_no_zero(arena, U32, primary_symbol_count),
.types = push_array_no_zero(arena, COFF_SymbolType, primary_symbol_count),
.storage_classes = push_array_no_zero(arena, COFF_SymStorageClass, primary_symbol_count),
.aux_counts = push_array_no_zero(arena, U8, primary_symbol_count),
.name_offsets = push_array_no_zero(arena, U32, primary_symbol_count),
.name_sizes = push_array_no_zero(arena, U32, primary_symbol_count),
.aux_counts = push_array_no_zero(arena, U8, primary_symbol_count),
.name_offsets = push_array_no_zero(arena, U32, primary_symbol_count),
.name_sizes = push_array_no_zero(arena, U32, primary_symbol_count),
};
{
U64 next_block = 0;
U64 next_block = 0;
U32 primary_idx = 0;
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = coff_parse_symbol(header, raw_coff_string_table, raw_coff_symbol_table, symbol_idx);
U64 block_idx = symbol_idx >> 6;
while (next_block <= block_idx) {
symbols.block_bases[next_block++] = primary_idx;
// copy out primary symbols
{
U64 block_idx = symbol_idx >> 6;
while (next_block <= block_idx) {
symbols.block_bases[next_block++] = primary_idx;
}
symbols.primary_masks[block_idx] |= 1ull << (symbol_idx & 63);
symbols.values [primary_idx] = symbol.value;
symbols.section_numbers[primary_idx] = symbol.section_number;
symbols.types [primary_idx] = symbol.type;
symbols.storage_classes[primary_idx] = symbol.storage_class;
symbols.aux_counts [primary_idx] = symbol.aux_symbol_count;
symbols.name_offsets [primary_idx] = symbol.name.size ? safe_cast_u32(symbol.name.str - input->data.str) : 0;
symbols.name_sizes [primary_idx] = safe_cast_u32(symbol.name.size);
primary_idx += 1;
}
symbols.primary_masks[block_idx] |= 1ull << (symbol_idx & 63);
symbols.values[primary_idx] = symbol.value;
symbols.section_numbers[primary_idx] = symbol.section_number;
symbols.types[primary_idx] = symbol.type;
symbols.storage_classes[primary_idx] = symbol.storage_class;
symbols.aux_counts[primary_idx] = symbol.aux_symbol_count;
symbols.name_offsets[primary_idx] = symbol.name.size ? safe_cast_u32(symbol.name.str - input->data.str) : 0;
symbols.name_sizes[primary_idx] = safe_cast_u32(symbol.name.size);
primary_idx += 1;
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular) {
if (symbol.section_number == 0 || symbol.section_number > header.section_count_no_null) {
@@ -381,22 +396,28 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
}
// fill out obj
obj->data = input->data;
obj->coff = (LNK_ObjCoff){
.data = input->data,
.header = header,
.sections = {
.count = header.section_count_no_null,
.headers = section_headers,
.flags = section_flags,
.data = section_data,
.comdats = comdats,
.associations = associated_sections,
},
.symbols = symbols,
.debug_t_sect_idx = debug_t_sect_idx,
.debug_p_sect_idx = debug_p_sect_idx,
.debug_h_sect_idx = debug_h_sect_idx,
.llvm_addrsig_sect_idx = llvm_addrsig_sect_idx,
.hotpatch = hotpatch,
};
obj->path = push_str8_copy(arena, input->path);
obj->header = header;
obj->section_headers = section_headers;
obj->section_flags = section_flags;
obj->symbols = symbols;
obj->comdats = comdats;
obj->exclude_from_debug_info = input->exclude_from_debug_info;
obj->hotpatch = hotpatch;
obj->associated_sections = associated_sections;
obj->self = &task->objs[task_id];
obj->link_member = input->link_member;
obj->debug_t_sect_idx = debug_t_sect_idx;
obj->debug_p_sect_idx = debug_p_sect_idx;
obj->debug_h_sect_idx = debug_h_sect_idx;
obj->llvm_addrsig_sect_idx = llvm_addrsig_sect_idx;
}
internal LNK_ObjNode *
@@ -447,7 +468,7 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
LNK_InputCoffSymbolTable *task = raw_task;
LNK_Obj *obj = task->objs[task_id];
COFF_ParsedSymbol symbol = {0};
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol);
LNK_SymbolSearchType search_type = lnk_symbol_search_type_from_coff(obj, symbol, interp);
@@ -493,14 +514,14 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
internal LNK_ObjSymbolRef *
lnk_symlinks_from_obj(Arena *arena, LNK_SymbolTable *symtab, LNK_Obj *obj)
{
LNK_ObjSymbolRef *symlinks = push_array(arena, LNK_ObjSymbolRef, obj->header.section_count_no_null + 1);
LNK_ObjSymbolRef *symlinks = push_array(arena, LNK_ObjSymbolRef, obj->coff.sections.count + 1);
COFF_ParsedSymbol symbol = {0};
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
COFF_SymbolValueInterpType interp = coff_interp_from_parsed_symbol(symbol);
if (interp != COFF_SymbolValueInterp_Regular) { continue; }
COFF_SectionFlags section_flags = obj->section_flags[symbol.section_number - 1];
COFF_SectionFlags section_flags = obj->coff.sections.flags[symbol.section_number - 1];
if (~section_flags & COFF_SectionFlag_LnkCOMDAT) { continue; }
LNK_ObjSymbolRef *symlink = &symlinks[symbol.section_number];
@@ -556,12 +577,12 @@ lnk_obj_collect_associated_sections(Arena *arena, LNK_Obj *obj, U32 root_section
// walk the complete descendant chain because associated COMDATs can nest
for EachNode(parent_n, U32Node, queue.first) {
for EachNode(associated_n, U32Node, obj->associated_sections[parent_n->data]) {
for EachNode(associated_n, U32Node, obj->coff.sections.associations[parent_n->data]) {
U32 child_section = associated_n->data;
if (child_section == 0) { continue; }
if (hash_map_search_u64_u64(&seen_hm, child_section)) { continue; }
if (obj->section_flags[child_section - 1] & skip_flags) { continue; }
if (obj->coff.sections.flags[child_section - 1] & skip_flags) { continue; }
hash_map_push_u64_u64(scratch.arena, &seen_hm, child_section, 1);
u32_list_push(arena, &queue, child_section);
@@ -610,7 +631,7 @@ internal COFF_ParsedSymbol
lnk_obj_match_symbol(LNK_Obj *obj, String8 match_name)
{
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
if (str8_match(symbol.name, match_name, 0)) {
return symbol;
@@ -657,7 +678,7 @@ lnk_obj_get_lib_path(LNK_Obj *obj)
internal U32
lnk_obj_get_removed_section_number(LNK_Obj *obj)
{
return obj->header.is_big_obj ? LNK_REMOVED_SECTION_NUMBER_32 : LNK_REMOVED_SECTION_NUMBER_16;
return obj->coff.header.is_big_obj ? LNK_REMOVED_SECTION_NUMBER_32 : LNK_REMOVED_SECTION_NUMBER_16;
}
internal B32
@@ -674,20 +695,42 @@ lnk_obj_get_comdat_symlink(LNK_Obj *obj, U64 section_number, LNK_ObjSymbolRef *s
internal COFF_SectionHeader *
lnk_coff_section_table_from_obj(LNK_Obj *obj)
{
return obj->section_headers;
return obj->coff.sections.headers;
}
internal String8
lnk_obj_section_data_from_sect_idx(LNK_Obj *obj, U64 sect_idx)
{
Assert(sect_idx < obj->coff.sections.count);
return obj->coff.sections.data[sect_idx];
}
internal U64
lnk_obj_foff_from_section_data_ptr(LNK_Obj *obj, void *ptr)
{
U64 ptr_v = IntFromPtr(ptr);
for EachIndex(sect_idx, obj->coff.sections.count) {
String8 data = obj->coff.sections.data[sect_idx];
U64 data_min = IntFromPtr(data.str);
if (data_min <= ptr_v && ptr_v < data_min + data.size) {
return obj->coff.sections.headers[sect_idx].foff + ptr_v - data_min;
}
}
InvalidPath;
return 0;
}
internal U64
lnk_obj_sect_idx_from_section_number(LNK_Obj *obj, U64 section_number)
{
Assert(1 <= section_number && section_number <= obj->header.section_count_no_null);
Assert(1 <= section_number && section_number <= obj->coff.sections.count);
return section_number-1;
}
internal U64
lnk_obj_section_number_from_sect_idx(LNK_Obj *obj, U64 sect_idx)
{
Assert(sect_idx < obj->header.section_count_no_null);
Assert(sect_idx < obj->coff.sections.count);
return sect_idx+1;
}
@@ -708,13 +751,13 @@ lnk_obj_section_name_from_section_number(LNK_Obj *obj, U64 section_number)
internal LNK_ObjSection
lnk_obj_section_from_sect_idx(LNK_Obj *obj, U64 sect_idx)
{
Assert(sect_idx < obj->header.section_count_no_null);
Assert(sect_idx < obj->coff.sections.count);
LNK_ObjSection section = {0};
section.obj = obj;
section.sect_idx = sect_idx;
section.section_number = sect_idx+1;
section.header = &lnk_coff_section_table_from_obj(obj)[sect_idx];
section.flags = &obj->section_flags[sect_idx];
section.flags = &obj->coff.sections.flags[sect_idx];
section.vrange = rng_1u64(section.header->voff, section.header->voff + section.header->vsize);
section.frange = rng_1u64(section.header->foff, section.header->foff + section.header->fsize);
section.reloc_count = section.header->reloc_count;
@@ -731,8 +774,8 @@ lnk_obj_section_from_section_number(LNK_Obj *obj, U64 section_number)
internal COFF_RelocArray
lnk_coff_relocs_from_section_header(LNK_Obj *obj, COFF_SectionHeader *section_header)
{
COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->data, section_header);
COFF_Reloc *relocs = (COFF_Reloc *)(obj->data.str + reloc_info.array_off);
COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->coff.data, section_header);
COFF_Reloc *relocs = (COFF_Reloc *)(obj->coff.data.str + reloc_info.array_off);
COFF_RelocArray result = { .count = reloc_info.count, .v = relocs };
return result;
}
@@ -740,21 +783,21 @@ lnk_coff_relocs_from_section_header(LNK_Obj *obj, COFF_SectionHeader *section_he
internal String8
lnk_coff_string_table_from_obj(LNK_Obj *obj)
{
return str8_substr(obj->data, obj->header.string_table_range);
return str8_substr(obj->coff.data, obj->coff.header.string_table_range);
}
internal String8
lnk_coff_symbol_table_from_obj(LNK_Obj *obj)
{
return str8_substr(obj->data, obj->header.symbol_table_range);
return str8_substr(obj->coff.data, obj->coff.header.symbol_table_range);
}
internal COFF_RelocArray
lnk_coff_reloc_info_from_section_number(LNK_Obj *obj, U64 section_number)
{
LNK_ObjSection section = lnk_obj_section_from_section_number(obj, section_number);
COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->data, section.header);
COFF_Reloc *relocs = str8_deserial_get_raw_ptr(obj->data, reloc_info.array_off, sizeof(*relocs)*reloc_info.count);
COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->coff.data, section.header);
COFF_Reloc *relocs = str8_deserial_get_raw_ptr(obj->coff.data, reloc_info.array_off, sizeof(*relocs)*reloc_info.count);
COFF_RelocArray result = { .count = reloc_info.count, .v = relocs };
return result;
}
@@ -763,10 +806,10 @@ internal B32
lnk_try_comdat_props_from_section_number(LNK_Obj *obj, U32 section_number, COFF_ComdatSelectType *select_out, U32 *section_number_out, U32 *section_length_out, U32 *check_sum_out)
{
Assert(section_number > 0);
U32 symbol_idx = obj->comdats[section_number-1];
U32 symbol_idx = obj->coff.sections.comdats[section_number-1];
if (symbol_idx != max_U32) {
COFF_ParsedSymbol secdef = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
coff_parse_secdef(secdef, obj->header.is_big_obj, select_out, section_number_out, section_length_out, check_sum_out);
coff_parse_secdef(secdef, obj->coff.header.is_big_obj, select_out, section_number_out, section_length_out, check_sum_out);
return 1;
}
return 0;
@@ -777,7 +820,7 @@ lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number)
{
Assert(section_number > 0);
U64 sect_idx = section_number - 1;
return &obj->section_headers[sect_idx];
return &obj->coff.sections.headers[sect_idx];
}
internal force_inline U64
@@ -785,22 +828,22 @@ lnk_obj_primary_symbol_idx_from_coff_symbol_idx(LNK_Obj *obj, U64 symbol_idx)
{
U64 block_idx = symbol_idx >> 6;
U64 bit = 1ull << (symbol_idx & 63);
U64 block_mask = obj->symbols.primary_masks[block_idx];
U64 block_mask = obj->coff.symbols.primary_masks[block_idx];
Assert(block_mask & bit);
return obj->symbols.block_bases[block_idx] + count_bits_set64(block_mask & (bit - 1));
return obj->coff.symbols.block_bases[block_idx] + count_bits_set64(block_mask & (bit - 1));
}
internal force_inline COFF_ParsedSymbol
lnk_parsed_symbol_from_coff_symbol_idx_no_name(LNK_Obj *obj, U64 symbol_idx)
{
U64 primary_idx = lnk_obj_primary_symbol_idx_from_coff_symbol_idx(obj, symbol_idx);
U64 symbol_size = obj->header.is_big_obj ? sizeof(COFF_Symbol32) : sizeof(COFF_Symbol16);
U64 symbol_size = obj->coff.header.is_big_obj ? sizeof(COFF_Symbol32) : sizeof(COFF_Symbol16);
COFF_ParsedSymbol result = {
.value = obj->symbols.values[primary_idx],
.section_number = obj->symbols.section_numbers[primary_idx],
.type = obj->symbols.types[primary_idx],
.storage_class = obj->symbols.storage_classes[primary_idx],
.aux_symbol_count = obj->symbols.aux_counts[primary_idx],
.value = obj->coff.symbols.values[primary_idx],
.section_number = obj->coff.symbols.section_numbers[primary_idx],
.type = obj->coff.symbols.types[primary_idx],
.storage_class = obj->coff.symbols.storage_classes[primary_idx],
.aux_symbol_count = obj->coff.symbols.aux_counts[primary_idx],
.raw_symbol = lnk_coff_symbol_table_from_obj(obj).str + symbol_idx * symbol_size,
};
return result;
@@ -810,7 +853,7 @@ internal force_inline String8
lnk_symbol_name_from_coff_symbol_idx(LNK_Obj *obj, U64 symbol_idx)
{
U64 primary_idx = lnk_obj_primary_symbol_idx_from_coff_symbol_idx(obj, symbol_idx);
return str8(obj->data.str + obj->symbols.name_offsets[primary_idx], obj->symbols.name_sizes[primary_idx]);
return str8(obj->coff.data.str + obj->coff.symbols.name_offsets[primary_idx], obj->coff.symbols.name_sizes[primary_idx]);
}
internal force_inline COFF_ParsedSymbol
@@ -826,13 +869,13 @@ lnk_obj_symbol_patch(LNK_Obj *obj, U64 symbol_idx, COFF_ParsedSymbol patch, LNK_
{
U64 primary_idx = lnk_obj_primary_symbol_idx_from_coff_symbol_idx(obj, symbol_idx);
if (flags & LNK_ObjSymbolPatch_Value) {
obj->symbols.values[primary_idx] = patch.value;
obj->coff.symbols.values[primary_idx] = patch.value;
}
if (flags & LNK_ObjSymbolPatch_Section) {
obj->symbols.section_numbers[primary_idx] = patch.section_number;
obj->coff.symbols.section_numbers[primary_idx] = patch.section_number;
}
if (flags & LNK_ObjSymbolPatch_StorageClass) {
obj->symbols.storage_classes[primary_idx] = patch.storage_class;
obj->coff.symbols.storage_classes[primary_idx] = patch.storage_class;
}
}
@@ -842,7 +885,7 @@ THREAD_POOL_TASK_FUNC(lnk_collect_obj_chunks_task)
LNK_SectionCollector *task = raw_task;
LNK_Obj *obj = task->objs[task_id];
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, sect_idx);
if (*section.flags & COFF_SectionFlag_LnkRemove && !task->collect_discarded) {
@@ -851,7 +894,7 @@ THREAD_POOL_TASK_FUNC(lnk_collect_obj_chunks_task)
String8 section_name = lnk_obj_section_name_from_sect_idx(obj, sect_idx);
if (str8_match(section_name, task->name, 0)) {
String8 section_data = str8_substr(obj->data, section.frange);
String8 section_data = lnk_obj_section_data_from_sect_idx(obj, sect_idx);
str8_list_push(arena, &task->out_lists[task_id], section_data);
}
}
@@ -927,7 +970,7 @@ internal String8List
lnk_raw_directives_from_obj(Arena *arena, LNK_Obj *obj)
{
String8List drectve_data = {0};
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
for (U64 sect_idx = 0; sect_idx < obj->coff.sections.count; sect_idx += 1) {
LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, sect_idx);
if (*section.flags & COFF_SectionFlag_LnkInfo) {
String8 section_name = lnk_obj_section_name_from_sect_idx(obj, sect_idx);
@@ -944,7 +987,7 @@ lnk_raw_directives_from_obj(Arena *arena, LNK_Obj *obj)
lnk_error_obj(LNK_Error_IllData, obj, ".drectve must not have relocations");
break;
}
str8_list_push(arena, &drectve_data, str8_substr(obj->data, section.frange));
str8_list_push(arena, &drectve_data, lnk_obj_section_data_from_sect_idx(obj, sect_idx));
}
}
}
@@ -977,7 +1020,7 @@ lnk_symbol_map_from_obj(Arena *arena, LNK_Obj *obj)
// count functions
U64 count = 0;
COFF_ParsedSymbol symbol;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += 1 + symbol.aux_symbol_count) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += 1 + symbol.aux_symbol_count) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
if (coff_interp_from_parsed_symbol(symbol) == COFF_SymbolValueInterp_Regular && COFF_SymbolType_IsFunc(symbol.type)) {
count += 1;
@@ -988,7 +1031,7 @@ lnk_symbol_map_from_obj(Arena *arena, LNK_Obj *obj)
map->v = push_array_no_zero(arena, LNK_SectionOffsetSymbol, count);
U64 map_idx = 0;
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += 1 + symbol.aux_symbol_count) {
for (U64 symbol_idx = 0; symbol_idx < obj->coff.header.symbol_count; symbol_idx += 1 + symbol.aux_symbol_count) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx_no_name(obj, symbol_idx);
if (coff_interp_from_parsed_symbol(symbol) == COFF_SymbolValueInterp_Regular && COFF_SymbolType_IsFunc(symbol.type)) {
LNK_SectionOffsetSymbol *entry = &map->v[map->count++];
@@ -1036,11 +1079,11 @@ lnk_debug_s_from_obj(Arena *arena, LNK_Obj *obj)
String8List raw_debug_s = {0};
{
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, sect_idx);
String8 section_name = lnk_obj_section_name_from_sect_idx(obj, sect_idx);
if (str8_match(section_name, str8_lit(".debug$S"), 0)) {
String8 debug_s = str8_substr(obj->data, section.frange);
String8 debug_s = lnk_obj_section_data_from_sect_idx(obj, sect_idx);
str8_list_push(scratch.arena, &raw_debug_s, debug_s);
}
}
@@ -1099,11 +1142,11 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj)
//
#define DebugRelocValueFromFileOffset(foff) hash_map_search_u64_u64(&debug_reloc_hm, foff)
HashMap debug_reloc_hm = {0};
for EachIndex(sect_idx, obj->header.section_count_no_null) {
for EachIndex(sect_idx, obj->coff.sections.count) {
LNK_ObjSection section = lnk_obj_section_from_sect_idx(obj, sect_idx);
if (!str8_match(lnk_obj_section_name_from_sect_idx(obj, sect_idx), str8_lit(".debug$S"), 0)) { continue; }
String8 section_data = str8_substr(obj->data, section.frange);
String8 section_data = lnk_obj_section_data_from_sect_idx(obj, sect_idx);
COFF_RelocArray relocs = lnk_coff_relocs_from_section_header(obj, section.header);
for EachIndex(reloc_idx, relocs.count) {
COFF_Reloc *reloc = &relocs.v[reloc_idx];
@@ -1112,12 +1155,12 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj)
U64 reloc_size = 0;
U64 reloc_value = 0;
if ((obj->header.machine == COFF_MachineType_X64 && reloc->type == COFF_Reloc_X64_Section) ||
(obj->header.machine == COFF_MachineType_X86 && reloc->type == COFF_Reloc_X86_Section)) {
if ((obj->coff.header.machine == COFF_MachineType_X64 && reloc->type == COFF_Reloc_X64_Section) ||
(obj->coff.header.machine == COFF_MachineType_X86 && reloc->type == COFF_Reloc_X86_Section)) {
reloc_size = sizeof(U16);
reloc_value = symbol.section_number;
} else if ((obj->header.machine == COFF_MachineType_X64 && reloc->type == COFF_Reloc_X64_SecRel) ||
(obj->header.machine == COFF_MachineType_X86 && reloc->type == COFF_Reloc_X86_SecRel)) {
} else if ((obj->coff.header.machine == COFF_MachineType_X64 && reloc->type == COFF_Reloc_X64_SecRel) ||
(obj->coff.header.machine == COFF_MachineType_X86 && reloc->type == COFF_Reloc_X86_SecRel)) {
reloc_size = sizeof(U32);
reloc_value = symbol.value;
}
@@ -1174,7 +1217,7 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj)
// resovle lines header
{
CV_C13LinesHeader *header = block->header;
U64 header_foff = (U64)(raw_lines.str - obj->data.str) + header->header_off;
U64 header_foff = lnk_obj_foff_from_section_data_ptr(obj, raw_lines.str) + header->header_off;
U64 *sec_off = DebugRelocValueFromFileOffset(header_foff + OffsetOf(CV_C13SubSecLinesHeader, sec_off));
if (sec_off) {
@@ -1223,9 +1266,8 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj)
// build inlinee id -> inlinee name
//
HashMap inlinee_hm = {0};
if (obj->debug_t_sect_idx < obj->header.section_count_no_null) {
LNK_ObjSection debug_t_section = lnk_obj_section_from_sect_idx(obj, obj->debug_t_sect_idx);
String8 raw_debug_t = str8_substr(obj->data, debug_t_section.frange);
if (obj->coff.debug_t_sect_idx < obj->coff.sections.count) {
String8 raw_debug_t = lnk_obj_section_data_from_sect_idx(obj, obj->coff.debug_t_sect_idx);
CV_Signature debug_t_sig = cv_signature_from_debug_s(raw_debug_t);
if (debug_t_sig == CV_Signature_C13) {
CV_DebugT debug_t = cv_debug_t_from_data(scratch.arena, str8_skip(raw_debug_t, sizeof(CV_Signature)), CV_LeafAlign);
@@ -1304,7 +1346,7 @@ lnk_line_map_from_obj(Arena *arena, LNK_Obj *obj)
if (CV_IsProc32(symbol.kind)) {
CV_SymProc32 *proc = str8_deserial_get_raw_ptr(symbol.data, 0, sizeof(*proc));
if (proc) {
U64 proc_foff = IntFromPtr(symbol.data.str - obj->data.str);
U64 proc_foff = lnk_obj_foff_from_section_data_ptr(obj, symbol.data.str);
U64 *off_reloc = DebugRelocValueFromFileOffset(proc_foff + OffsetOf(CV_SymProc32, off));
U64 *sec_reloc = DebugRelocValueFromFileOffset(proc_foff + OffsetOf(CV_SymProc32, sec));
proc_offset = off_reloc ? safe_cast_u32(*off_reloc) : proc->off;
+42 -32
View File
@@ -5,20 +5,6 @@
// --- Input -------------------------------------------------------------------
typedef struct LNK_ObjSymbolArray
{
U64 count;
U64 *primary_masks;
U32 *block_bases;
U64 *values;
U32 *section_numbers;
COFF_SymbolType *types;
COFF_SymStorageClass *storage_classes;
U8 *aux_counts;
U32 *name_offsets;
U32 *name_sizes;
} LNK_ObjSymbolArray;
typedef U32 LNK_ObjSymbolPatchFlags;
enum
{
@@ -27,39 +13,61 @@ enum
LNK_ObjSymbolPatch_StorageClass = (1 << 2),
};
typedef struct LNK_ObjSymbolArray
{
U64 count;
U64 *primary_masks;
U32 *block_bases;
U64 *values;
U32 *section_numbers;
COFF_SymbolType *types;
COFF_SymStorageClass *storage_classes;
U8 *aux_counts;
U32 *name_offsets;
U32 *name_sizes;
} LNK_ObjSymbolArray;
typedef struct LNK_ObjSectionArray
{
U64 count;
COFF_SectionHeader *headers;
COFF_SectionFlags *flags;
String8 *data;
U32 *comdats;
U32Node **associations;
} LNK_ObjSectionArray;
typedef struct LNK_ObjCoff
{
String8 data;
COFF_FileHeaderInfo header;
LNK_ObjSectionArray sections;
LNK_ObjSymbolArray symbols;
U32 debug_t_sect_idx;
U32 debug_p_sect_idx;
U32 debug_h_sect_idx;
U32 llvm_addrsig_sect_idx;
B8 hotpatch;
} LNK_ObjCoff;
typedef struct LNK_Obj
{
String8 path;
String8 data;
COFF_FileHeaderInfo header;
COFF_SectionHeader *section_headers;
COFF_SectionFlags *section_flags;
LNK_ObjSymbolArray symbols;
LNK_ObjCoff coff;
// flags
B8 hotpatch;
B8 exclude_from_debug_info;
U32 input_idx;
// COMDAT
U32 *comdats;
U32Node **associated_sections;
LNK_ObjSymbolRef *symlinks;
// link state
LNK_ObjSymbolRef *symlinks;
// link
struct LNK_LibMemberRef *link_member;
struct LNK_ObjNode *self;
// type info
U32 debug_t_sect_idx;
U32 debug_p_sect_idx;
U32 debug_h_sect_idx;
// ICF
U32 llvm_addrsig_sect_idx;
// @type_server
Rng1U64 ti_range;
CV_TypeIndex *ti_map;
@@ -242,6 +250,8 @@ internal force_inline String8 lnk_symbol_name_from_coff_symbol_idx(LNK
internal void lnk_obj_symbol_patch(LNK_Obj *obj, U64 symbol_idx, COFF_ParsedSymbol patch, LNK_ObjSymbolPatchFlags flags);
internal COFF_SectionHeader * lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number);
internal String8 lnk_obj_section_data_from_sect_idx(LNK_Obj *obj, U64 sect_idx);
internal U64 lnk_obj_foff_from_section_data_ptr(LNK_Obj *obj, void *ptr);
internal U64 lnk_obj_sect_idx_from_section_number(LNK_Obj *obj, U64 section_number);
internal U64 lnk_obj_section_number_from_sect_idx(LNK_Obj *obj, U64 sect_idx);
internal String8 lnk_obj_section_name_from_section_number(LNK_Obj *obj, U64 section_number);
+8 -8
View File
@@ -10,7 +10,7 @@ lnk_symbol_search_type_from_coff(LNK_Obj *obj, COFF_ParsedSymbol symbol, COFF_Sy
if (interp == COFF_SymbolValueInterp_Undefined) {
search_type = LNK_SymbolSearch_Undefined;
} else if (interp == COFF_SymbolValueInterp_Weak) {
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol, obj->header.is_big_obj);
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol, obj->coff.header.is_big_obj);
switch (weak_ext->characteristics) {
case COFF_WeakExt_SearchLibrary: search_type = LNK_SymbolSearch_WeakLibrary; break;
case COFF_WeakExt_AntiDependency: search_type = LNK_SymbolSearch_WeakAntiDependency; break;
@@ -179,7 +179,7 @@ lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src)
}
LNK_ObjSymbolRef weak_symbol_ref = lnk_ref_from_symbol(weak);
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(weak_parsed, weak_symbol_ref.obj->header.is_big_obj);
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(weak_parsed, weak_symbol_ref.obj->coff.header.is_big_obj);
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
// NOTE: MSVC does not let a weak symbol to replace an undefined one,
// but LLD links without errors or warnings, meaning undefined symbols
@@ -242,8 +242,8 @@ lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src)
}
// weak vs weak
else if (dst_interp == COFF_SymbolValueInterp_Weak && src_interp == COFF_SymbolValueInterp_Weak) {
COFF_SymbolWeakExt *dst_ext = coff_parse_weak_tag(dst_parsed, dst_ref.obj->header.is_big_obj);
COFF_SymbolWeakExt *src_ext = coff_parse_weak_tag(src_parsed, src_ref.obj->header.is_big_obj);
COFF_SymbolWeakExt *dst_ext = coff_parse_weak_tag(dst_parsed, dst_ref.obj->coff.header.is_big_obj);
COFF_SymbolWeakExt *src_ext = coff_parse_weak_tag(src_parsed, src_ref.obj->coff.header.is_big_obj);
if ((dst_ext->characteristics == COFF_WeakExt_SearchAlias && src_ext->characteristics != COFF_WeakExt_SearchAlias)) {
if (lnk_symbol_is_before(dst, src) || src_ext->characteristics == COFF_WeakExt_AntiDependency) {
can_replace = 0;
@@ -342,8 +342,8 @@ lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src)
case COFF_ComdatSelect_ExactMatch: {
LNK_ObjSection dst_section = lnk_obj_section_from_section_number(dst_obj, dst_parsed.section_number);
LNK_ObjSection src_section = lnk_obj_section_from_section_number(src_obj, src_parsed.section_number);
String8 dst_data = str8_substr(dst_obj->data, dst_section.frange);
String8 src_data = str8_substr(src_obj->data, src_section.frange);
String8 dst_data = lnk_obj_section_data_from_sect_idx(dst_obj, dst_section.sect_idx);
String8 src_data = lnk_obj_section_data_from_sect_idx(src_obj, src_section.sect_idx);
B32 is_exact_match = 0;
if (dst_check_sum != 0 && src_check_sum != 0) {
@@ -396,7 +396,7 @@ lnk_on_symbol_replace(LNK_Symbol *dst, LNK_Symbol *src)
*dst_section.flags |= COFF_SectionFlag_LnkRemove;
// remove associated sections from the output
for (U32Node *associated_section = dst_ref.obj->associated_sections[dst_parsed.section_number];
for (U32Node *associated_section = dst_ref.obj->coff.sections.associations[dst_parsed.section_number];
associated_section != 0;
associated_section = associated_section->next) {
LNK_ObjSection section = lnk_obj_section_from_section_number(dst_ref.obj, associated_section->data);
@@ -728,7 +728,7 @@ lnk_resolve_weak_symbol(LNK_SymbolTable *symtab, LNK_ObjSymbolRef symbol, LNK_Ob
break;
}
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(current_parsed, current_symbol.obj->header.is_big_obj);
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(current_parsed, current_symbol.obj->coff.header.is_big_obj);
// no definition -- fallback to default symbol
COFF_ParsedSymbol tag_parsed = lnk_parsed_symbol_from_coff_symbol_idx_no_name(current_symbol.obj, weak_ext->tag_index);
+12 -2
View File
@@ -5881,8 +5881,12 @@ TEST(debug_p_sig_mismatch)
T_Ok(t_write_file(str8_lit("b.obj"), b_obj));
T_Ok(t_write_entry_obj());
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:full a.obj b.obj entry.obj");
String8 a_obj_before = t_read_file(arena, str8_lit("a.obj"));
String8 b_obj_before = t_read_file(arena, str8_lit("b.obj"));
t_invoke_linkerf("/RAD_MEMORY_MAP_FILES:READ_WRITE /subsystem:console /entry:entry /out:a.exe /debug:full a.obj b.obj entry.obj");
T_Ok(g_last_exit_code == 0);
T_Ok(str8_match(a_obj_before, t_read_file(arena, str8_lit("a.obj")), 0));
T_Ok(str8_match(b_obj_before, t_read_file(arena, str8_lit("b.obj")), 0));
B32 found_error = 0;
String8 a_obj_path = t_make_file_path(arena, str8_lit("a.obj"));
@@ -6271,8 +6275,14 @@ TEST(gen_rrt)
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:full /rad_type_server:foo.rrt a.obj b.obj entry.obj");
T_Ok(g_last_exit_code == 0);
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /debug:ghash a.obj foo.rrt b.obj entry.obj");
String8 a_obj_before = t_read_file(arena, a_obj_file_path);
String8 b_obj_before = t_read_file(arena, b_obj_file_path);
String8 rrt_before = t_read_file(arena, str8_lit("foo.rrt"));
t_invoke_linkerf("/RAD_MEMORY_MAP_FILES:READ_WRITE /subsystem:console /entry:entry /out:a.exe /debug:ghash a.obj foo.rrt b.obj entry.obj");
T_Ok(g_last_exit_code == 0);
T_Ok(str8_match(a_obj_before, t_read_file(arena, a_obj_file_path), 0));
T_Ok(str8_match(b_obj_before, t_read_file(arena, b_obj_file_path), 0));
T_Ok(str8_match(rrt_before, t_read_file(arena, str8_lit("foo.rrt")), 0));
}
TEST(debug_p_and_debug_t_in_obj)