|
|
|
@@ -179,7 +179,6 @@ lnk_config_from_argcv(Arena *arena, int argc, char **argv)
|
|
|
|
|
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_HighEntropyVa, "");
|
|
|
|
|
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_ManifestUac, "\"level='asInvoker' uiAccess='false'\"");
|
|
|
|
|
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_NxCompat, "");
|
|
|
|
|
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_FunctionPadMin, "0");
|
|
|
|
|
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_LargeAddressAware, "");
|
|
|
|
|
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_PdbAltPath, "%%_RAD_PDB_PATH%%");
|
|
|
|
|
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_PdbPageSize, "%u", KB(4));
|
|
|
|
@@ -1491,9 +1490,8 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|
|
|
|
if (obj_node_arr.v[obj_idx].data.header.machine != COFF_MachineType_Unknown) {
|
|
|
|
|
config->machine = obj_node_arr.v[obj_idx].data.header.machine;
|
|
|
|
|
|
|
|
|
|
if (config->do_function_pad_min == LNK_SwitchState_Yes && config->function_pad_min == 0) {
|
|
|
|
|
config->function_pad_min = push_array(tp_arena->v[0], U64, 1);
|
|
|
|
|
*config->function_pad_min = lnk_get_default_function_pad_min(config->machine);
|
|
|
|
|
if (config->infer_function_pad_min) {
|
|
|
|
|
config->function_pad_min = lnk_get_default_function_pad_min(config->machine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
@@ -2348,15 +2346,17 @@ THREAD_POOL_TASK_FUNC(lnk_gather_section_contribs_task)
|
|
|
|
|
|
|
|
|
|
ProfBeginV("Gather Section Contribs [%S]", obj->path);
|
|
|
|
|
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
|
|
|
|
|
LNK_SectionContrib *sc = &g_null_sc;
|
|
|
|
|
LNK_SectionContrib *sc = &g_null_sc;
|
|
|
|
|
COFF_SectionHeader *sect_header = §ion_table[sect_idx];
|
|
|
|
|
if (~sect_header->flags & COFF_SectionFlag_LnkRemove) {
|
|
|
|
|
Temp temp = temp_begin(scratch.arena);
|
|
|
|
|
|
|
|
|
|
String8 sect_name = coff_name_from_section_header(string_table, sect_header);
|
|
|
|
|
String8 sect_name_with_flags = lnk_make_name_with_flags(temp.arena, sect_name, sect_header->flags & ~COFF_SectionFlags_LnkFlags);
|
|
|
|
|
LNK_SectionContribChunk *sc_chunk = 0;
|
|
|
|
|
hash_table_search_string_raw(task->contribs_ht, sect_name_with_flags, &sc_chunk);
|
|
|
|
|
if (~sect_header->flags & COFF_SectionFlag_LnkRemove && sect_header->fsize > 0) {
|
|
|
|
|
LNK_SectionContribChunk *sc_chunk = 0;
|
|
|
|
|
{
|
|
|
|
|
Temp temp = temp_begin(scratch.arena);
|
|
|
|
|
String8 sect_name = coff_name_from_section_header(string_table, sect_header);
|
|
|
|
|
String8 sect_name_with_flags = lnk_make_name_with_flags(temp.arena, sect_name, sect_header->flags & ~COFF_SectionFlags_LnkFlags);
|
|
|
|
|
hash_table_search_string_raw(task->contribs_ht, sect_name_with_flags, &sc_chunk);
|
|
|
|
|
temp_end(temp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sc_chunk) {
|
|
|
|
|
U16 sc_align = coff_align_size_from_section_flags(sect_header->flags);
|
|
|
|
@@ -2368,8 +2368,6 @@ THREAD_POOL_TASK_FUNC(lnk_gather_section_contribs_task)
|
|
|
|
|
sc->u.obj_idx = obj_idx;
|
|
|
|
|
sc->u.obj_sect_idx = sect_idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
temp_end(temp);
|
|
|
|
|
}
|
|
|
|
|
task->sect_map[obj_idx][sect_idx] = sc;
|
|
|
|
|
}
|
|
|
|
@@ -2402,6 +2400,43 @@ THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_task)
|
|
|
|
|
ProfEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal
|
|
|
|
|
THREAD_POOL_TASK_FUNC(lnk_patch_comdats_task)
|
|
|
|
|
{
|
|
|
|
|
LNK_BuildImageTask *task = raw_task;
|
|
|
|
|
U64 obj_idx = task_id;
|
|
|
|
|
LNK_Obj *obj = task->objs[obj_idx];
|
|
|
|
|
|
|
|
|
|
ProfBeginV("Patch COMDATs [%S]", obj->path);
|
|
|
|
|
COFF_ParsedSymbol symbol;
|
|
|
|
|
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
|
|
|
|
|
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
|
|
|
|
|
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
|
|
|
|
if (interp == COFF_SymbolValueInterp_Regular && symbol.storage_class == COFF_SymStorageClass_External && symbol.value == 0) {
|
|
|
|
|
COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number);
|
|
|
|
|
if (sect_header->flags & COFF_SectionFlag_LnkCOMDAT) {
|
|
|
|
|
LNK_Symbol *defn = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Defined, symbol.name);
|
|
|
|
|
|
|
|
|
|
if (defn->u.defined.obj == obj && defn->u.defined.symbol_idx == symbol_idx) {
|
|
|
|
|
LNK_SectionContrib *sc = task->sect_map[obj_idx][symbol.section_number-1];
|
|
|
|
|
if (obj->header.is_big_obj) {
|
|
|
|
|
COFF_Symbol32 *symbol32 = symbol.raw_symbol;
|
|
|
|
|
symbol32->section_number = sc->u.sect_idx+1;
|
|
|
|
|
symbol32->value = safe_cast_u32(sc->u.off + symbol.value);
|
|
|
|
|
} else {
|
|
|
|
|
COFF_Symbol16 *symbol16 = symbol.raw_symbol;
|
|
|
|
|
symbol16->section_number = safe_cast_u16(sc->u.sect_idx+1);
|
|
|
|
|
symbol16->value = safe_cast_u32(sc->u.off + symbol.value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ProfEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal
|
|
|
|
|
THREAD_POOL_TASK_FUNC(lnk_split_func_contribs_task)
|
|
|
|
|
{
|
|
|
|
@@ -2414,6 +2449,7 @@ THREAD_POOL_TASK_FUNC(lnk_split_func_contribs_task)
|
|
|
|
|
|
|
|
|
|
ProfBeginV("%S", obj->path);
|
|
|
|
|
|
|
|
|
|
U64List func_list = {0};
|
|
|
|
|
COFF_ParsedSymbol symbol;
|
|
|
|
|
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
|
|
|
|
|
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
|
|
|
|
@@ -2471,24 +2507,22 @@ THREAD_POOL_TASK_FUNC(lnk_split_func_contribs_task)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u64_list_push(scratch.arena, &func_list, symbol_idx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
U64 *sect_offset_map_counts = push_array(scratch.arena, U64, obj->header.section_count_no_null);
|
|
|
|
|
PairU64 **sect_offset_map = push_array(scratch.arena, PairU64 *, obj->header.section_count_no_null);
|
|
|
|
|
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
|
|
|
|
|
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, sect_idx+1);
|
|
|
|
|
if (~section_header->flags & COFF_SectionFlag_CntCode) { continue; }
|
|
|
|
|
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);
|
|
|
|
|
LNK_SectionContrib *sc = task->sect_map[obj_idx][sect_idx];
|
|
|
|
|
LNK_SectionContrib *sc = task->sect_map[obj_idx][sect_idx];
|
|
|
|
|
|
|
|
|
|
U64 offset_map_count = 0;
|
|
|
|
|
for (String8Node *data_n = &sc->first_data_node; data_n != 0; data_n = data_n->next) {
|
|
|
|
|
offset_map_count += 1;
|
|
|
|
|
}
|
|
|
|
|
if (offset_map_count <= 1) { continue; }
|
|
|
|
|
|
|
|
|
|
Temp temp = temp_begin(scratch.arena);
|
|
|
|
|
PairU64 *offset_map = push_array(temp.arena, PairU64, offset_map_count);
|
|
|
|
|
PairU64 *offset_map = push_array(scratch.arena, PairU64, offset_map_count);
|
|
|
|
|
U64 data_node_idx = 0;
|
|
|
|
|
U64 prev_cursor_offset = 0;
|
|
|
|
|
U64 new_cursor_offset = 0;
|
|
|
|
@@ -2499,19 +2533,43 @@ THREAD_POOL_TASK_FUNC(lnk_split_func_contribs_task)
|
|
|
|
|
new_cursor_offset += Max(task->function_pad_min, data_n->string.size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (U64 reloc_idx = 0; reloc_idx < reloc_info.count; reloc_idx += 1) {
|
|
|
|
|
COFF_Reloc *reloc = &relocs[reloc_idx];
|
|
|
|
|
U64 offset_idx = pair_u64_nearest_v0(offset_map, offset_map_count, reloc->apply_off);
|
|
|
|
|
if (offset_idx < offset_map_count) {
|
|
|
|
|
reloc->apply_off = offset_map[offset_idx].v1 + (reloc->apply_off - offset_map[offset_idx].v0);
|
|
|
|
|
} else {
|
|
|
|
|
InvalidPath;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
temp_end(temp);
|
|
|
|
|
sect_offset_map_counts[sect_idx] = offset_map_count;
|
|
|
|
|
sect_offset_map[sect_idx] = offset_map;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: update symbols with new offsets
|
|
|
|
|
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
|
|
|
|
|
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, sect_idx+1);
|
|
|
|
|
if (section_header->flags & COFF_SectionFlag_CntCode) {
|
|
|
|
|
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);
|
|
|
|
|
LNK_SectionContrib *sc = task->sect_map[obj_idx][sect_idx];
|
|
|
|
|
U64 offset_map_count = sect_offset_map_counts[sect_idx];
|
|
|
|
|
PairU64 *offset_map = sect_offset_map[sect_idx];
|
|
|
|
|
if (offset_map_count > 0) {
|
|
|
|
|
for (U64 reloc_idx = 0; reloc_idx < reloc_info.count; reloc_idx += 1) {
|
|
|
|
|
COFF_Reloc *reloc = &relocs[reloc_idx];
|
|
|
|
|
U64 offset_idx = pair_u64_nearest_v0(offset_map, offset_map_count, reloc->apply_off);
|
|
|
|
|
if (offset_idx < offset_map_count) {
|
|
|
|
|
reloc->apply_off = offset_map[offset_idx].v1 + (reloc->apply_off - offset_map[offset_idx].v0);
|
|
|
|
|
} else {
|
|
|
|
|
InvalidPath;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (U64Node *func_n = func_list.first; func_n != 0; func_n = func_n->next) {
|
|
|
|
|
COFF_ParsedSymbol symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, func_n->data);
|
|
|
|
|
|
|
|
|
|
U64 offset_map_count = sect_offset_map_counts[symbol.section_number-1];
|
|
|
|
|
PairU64 *offset_map = sect_offset_map[symbol.section_number-1];
|
|
|
|
|
U64 offset_idx = pair_u64_nearest_v0(offset_map, offset_map_count, symbol.value);
|
|
|
|
|
AssertAlways(offset_idx < offset_map_count);
|
|
|
|
|
|
|
|
|
|
U32 *value_ptr = obj->header.is_big_obj ? &((COFF_Symbol32 *)symbol.raw_symbol)->value : &((COFF_Symbol16 *)symbol.raw_symbol)->value;
|
|
|
|
|
*value_ptr = offset_map[offset_idx].v1 + (*value_ptr - offset_map[offset_idx].v0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProfEnd();
|
|
|
|
|
|
|
|
|
@@ -2608,15 +2666,17 @@ THREAD_POOL_TASK_FUNC(lnk_patch_regular_symbols_task)
|
|
|
|
|
|
|
|
|
|
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
|
|
|
|
if (interp == COFF_SymbolValueInterp_Regular) {
|
|
|
|
|
U32 section_number = 0;
|
|
|
|
|
U32 value = 0;
|
|
|
|
|
{
|
|
|
|
|
COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number);
|
|
|
|
|
if (~sect_header->flags & COFF_SectionFlag_LnkRemove) {
|
|
|
|
|
LNK_SectionContrib *sc = task->sect_map[obj_idx][symbol.section_number-1];
|
|
|
|
|
section_number = safe_cast_u32(sc->u.sect_idx + 1);
|
|
|
|
|
value = sc->u.off + symbol.value;
|
|
|
|
|
}
|
|
|
|
|
COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number);
|
|
|
|
|
|
|
|
|
|
LNK_SectionContrib *sc = task->sect_map[obj_idx][symbol.section_number-1];
|
|
|
|
|
U16 section_number;
|
|
|
|
|
U32 value;
|
|
|
|
|
if (sc == &g_null_sc) {
|
|
|
|
|
section_number = LNK_REMOVED_SECTION_NUMBER;
|
|
|
|
|
value = max_U32;
|
|
|
|
|
} else {
|
|
|
|
|
section_number = safe_cast_u32(sc->u.sect_idx + 1);
|
|
|
|
|
value = sc->u.off + symbol.value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (obj->header.is_big_obj) {
|
|
|
|
@@ -3013,18 +3073,20 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher)
|
|
|
|
|
U32 symbol_secoff = 0;
|
|
|
|
|
S64 symbol_voff = 0;
|
|
|
|
|
{
|
|
|
|
|
COFF_ParsedSymbol symbol;
|
|
|
|
|
if (obj_header.is_big_obj) {
|
|
|
|
|
symbol = coff_parse_symbol32(string_table, (COFF_Symbol32 *)symbol_table.str + reloc->isymbol);
|
|
|
|
|
} else {
|
|
|
|
|
symbol = coff_parse_symbol16(string_table, (COFF_Symbol16 *)symbol_table.str + reloc->isymbol);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
COFF_ParsedSymbol symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, reloc->isymbol);
|
|
|
|
|
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
|
|
|
|
if (interp == COFF_SymbolValueInterp_Regular) {
|
|
|
|
|
if (symbol.section_number == LNK_REMOVED_SECTION_NUMBER) {
|
|
|
|
|
if (!lnk_is_coff_section_debug(obj, sect_idx)) {
|
|
|
|
|
String8 sect_name = coff_name_from_section_header(string_table, §ion_table[sect_idx]);
|
|
|
|
|
lnk_error_obj(LNK_Error_RelocationAgainstRemovedSection, obj, "relocating against symbol that is in a removed section (symbol: %S, reloc-section: %S 0x%llx, reloc: 0x%llx)", symbol.name, sect_name, sect_idx+1, reloc_idx);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
symbol_secnum = symbol.section_number;
|
|
|
|
|
symbol_secoff = symbol.value;
|
|
|
|
|
symbol_voff = safe_cast_u32((U64)task->image_section_table[symbol.section_number]->voff + (U64)symbol_secoff);
|
|
|
|
|
symbol_voff = safe_cast_u32((U64)task->image_section_table[symbol.section_number]->voff + (U64)symbol_secoff);
|
|
|
|
|
} else if (interp == COFF_SymbolValueInterp_Abs) {
|
|
|
|
|
// There aren't enough bits in COFF symbol to store full image base address,
|
|
|
|
|
// so we special case __ImageBase. A better solution would be to add
|
|
|
|
@@ -3035,7 +3097,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher)
|
|
|
|
|
|
|
|
|
|
symbol_secnum = 0;
|
|
|
|
|
symbol_secoff = 0;
|
|
|
|
|
symbol_voff = (S64)symbol.value - (S64)task->image_base;
|
|
|
|
|
symbol_voff = (S64)symbol.value - (S64)task->image_base;
|
|
|
|
|
} else if (interp == COFF_SymbolValueInterp_Weak) {
|
|
|
|
|
// unresolved weak
|
|
|
|
|
} else if (interp == COFF_SymbolValueInterp_Undefined) {
|
|
|
|
@@ -3540,7 +3602,7 @@ THREAD_POOL_TASK_FUNC(lnk_patch_file_offsets_and_sizes_in_obj_section_headers_ta
|
|
|
|
|
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) {
|
|
|
|
|
COFF_SectionHeader *sect_header = §ion_table[sect_idx];
|
|
|
|
|
B32 patch_section_header = (~sect_header->flags & COFF_SectionFlag_LnkRemove) &&
|
|
|
|
|
!lnk_is_coff_section_debug(obj, sect_idx);
|
|
|
|
|
!lnk_is_coff_section_debug(obj, sect_idx);
|
|
|
|
|
if (patch_section_header) {
|
|
|
|
|
LNK_SectionContrib *sc = task->sect_map[obj_idx][sect_idx];
|
|
|
|
|
LNK_Section *sect = task->image_sects.v[sc->u.sect_idx];
|
|
|
|
@@ -4007,7 +4069,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
|
|
|
|
|
LNK_BuildImageTask task = {0};
|
|
|
|
|
task.symtab = symtab;
|
|
|
|
|
task.sectab = sectab;
|
|
|
|
|
task.function_pad_min = *config->function_pad_min;
|
|
|
|
|
task.function_pad_min = config->function_pad_min;
|
|
|
|
|
task.default_align = coff_default_align_from_machine(config->machine);
|
|
|
|
|
task.objs_count = objs_count;
|
|
|
|
|
task.objs = objs;
|
|
|
|
@@ -4153,10 +4215,6 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
|
|
|
|
|
ProfEnd();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProfBegin("Set COMDAT Leaders");
|
|
|
|
|
tp_for_parallel(tp, 0, objs_count, lnk_set_comdat_leaders_task, &task);
|
|
|
|
|
ProfEnd();
|
|
|
|
|
|
|
|
|
|
// build common block
|
|
|
|
|
//
|
|
|
|
|
// TODO: build common block in .bss and merge with .data
|
|
|
|
@@ -4213,7 +4271,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
|
|
|
|
|
radsort(common_block_contribs, common_block_contribs_count, lnk_common_block_contrib_is_before);
|
|
|
|
|
|
|
|
|
|
// compute .bss virtual size - this marks start of the common block
|
|
|
|
|
lnk_finalize_section_layout(common_block_sect, config->file_align, *config->function_pad_min);
|
|
|
|
|
lnk_finalize_section_layout(common_block_sect, config->file_align, config->function_pad_min);
|
|
|
|
|
U64 common_block_cursor = common_block_sect->vsize;
|
|
|
|
|
|
|
|
|
|
// compute and assign offsets into the common block
|
|
|
|
@@ -4253,7 +4311,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
|
|
|
|
|
|
|
|
|
|
// assign contribs offsets, sizes, and section indices
|
|
|
|
|
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
|
|
|
|
|
lnk_finalize_section_layout(§_n->data, config->file_align, *config->function_pad_min);
|
|
|
|
|
lnk_finalize_section_layout(§_n->data, config->file_align, config->function_pad_min);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove empty sections
|
|
|
|
@@ -4277,16 +4335,15 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
|
|
|
|
|
|
|
|
|
|
// assing layout offsets and sizes to merged sections
|
|
|
|
|
for (LNK_SectionNode *sect_n = sectab->merge_list.first; sect_n != 0; sect_n = sect_n->next) {
|
|
|
|
|
LNK_Section *sect = §_n->data;
|
|
|
|
|
LNK_Section *final_sect = sect->merge_dst;
|
|
|
|
|
LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect);
|
|
|
|
|
LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect);
|
|
|
|
|
U64 last_sc_size = lnk_size_from_section_contrib(last_sc);
|
|
|
|
|
sect->voff = final_sect->voff + first_sc->u.off;
|
|
|
|
|
sect->vsize = (last_sc->u.off - first_sc->u.off) + last_sc_size;
|
|
|
|
|
sect->foff = final_sect->foff + first_sc->u.off;
|
|
|
|
|
sect->fsize = (last_sc->u.off - first_sc->u.off) + last_sc_size;
|
|
|
|
|
sect->sect_idx = final_sect->sect_idx;
|
|
|
|
|
LNK_Section *sect = §_n->data;
|
|
|
|
|
LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect);
|
|
|
|
|
LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect);
|
|
|
|
|
U64 last_sc_size = lnk_size_from_section_contrib(last_sc);
|
|
|
|
|
sect->voff = sect->merge_dst->voff + first_sc->u.off;
|
|
|
|
|
sect->vsize = (last_sc->u.off - first_sc->u.off) + last_sc_size;
|
|
|
|
|
sect->foff = sect->merge_dst->foff + first_sc->u.off;
|
|
|
|
|
sect->fsize = (last_sc->u.off - first_sc->u.off) + last_sc_size;
|
|
|
|
|
lnk_assign_section_index(sect, sect->merge_dst->sect_idx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProfEnd();
|
|
|
|
@@ -4309,6 +4366,14 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
|
|
|
|
|
task.u.patch_symtabs.common_block_contribs = common_block_contribs;
|
|
|
|
|
ProfEnd();
|
|
|
|
|
|
|
|
|
|
ProfBegin("Set COMDAT Leaders");
|
|
|
|
|
tp_for_parallel(tp, 0, objs_count, lnk_set_comdat_leaders_task, &task);
|
|
|
|
|
ProfEnd();
|
|
|
|
|
|
|
|
|
|
ProfBegin("Patch COMDAT Leaders");
|
|
|
|
|
tp_for_parallel(tp, 0, objs_count, lnk_patch_comdats_task, &task);
|
|
|
|
|
ProfEnd();
|
|
|
|
|
|
|
|
|
|
ProfBegin("Patch Common Block Leaders");
|
|
|
|
|
tp_for_parallel(tp, 0, tp->worker_count, lnk_patch_common_block_leaders_task, &task);
|
|
|
|
|
ProfEnd();
|
|
|
|
@@ -4369,10 +4434,10 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
|
|
|
|
|
LNK_SectionContrib *sc = lnk_section_contrib_chunk_push(first_sc_chunk, 1);
|
|
|
|
|
sc->first_data_node = *base_relocs_data.first;
|
|
|
|
|
sc->last_data_node = base_relocs_data.last;
|
|
|
|
|
sc->align = 1;
|
|
|
|
|
sc->u.obj_idx = max_U32;
|
|
|
|
|
sc->align = 1;
|
|
|
|
|
sc->u.obj_idx = max_U32;
|
|
|
|
|
|
|
|
|
|
lnk_finalize_section_layout(reloc, config->file_align, *config->function_pad_min);
|
|
|
|
|
lnk_finalize_section_layout(reloc, config->file_align, config->function_pad_min);
|
|
|
|
|
lnk_assign_section_virtual_space(reloc, config->sect_align, &voff_cursor);
|
|
|
|
|
lnk_assign_section_index(reloc, sectab->next_sect_idx++);
|
|
|
|
|
|
|
|
|
@@ -4404,7 +4469,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
|
|
|
|
|
image_header_sc->first_data_node = *image_header_data.first;
|
|
|
|
|
image_header_sc->last_data_node = image_header_data.last;
|
|
|
|
|
|
|
|
|
|
lnk_finalize_section_layout(image_header_sect, config->file_align, *config->function_pad_min);
|
|
|
|
|
lnk_finalize_section_layout(image_header_sect, config->file_align, config->function_pad_min);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ProfBegin("Patch Section Symbols");
|
|
|
|
|