WIP function pad min

This commit is contained in:
Nikita Smith
2025-06-25 10:53:24 -07:00
committed by Ryan Fleury
parent d7b8de5998
commit a5119e3b51
10 changed files with 204 additions and 78 deletions
+9
View File
@@ -283,6 +283,15 @@ coff_obj_writer_push_symbol_extern(COFF_ObjWriter *obj_writer, String8 name, U32
return s; return s;
} }
internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_extern_func(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section)
{
COFF_SymbolType type = { .u.msb = COFF_SymDType_Func };
COFF_SymbolLocation loc = { .type = COFF_SymbolLocation_Section, .u.section = section };
COFF_ObjSymbol *s = coff_obj_writer_push_symbol(obj_writer, name, value, loc, type, COFF_SymStorageClass_External);
return s;
}
internal COFF_ObjSymbol * internal COFF_ObjSymbol *
coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section) coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section)
{ {
+1
View File
@@ -102,6 +102,7 @@ internal String8 coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter
internal COFF_ObjSection * coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_SectionFlags flags, String8 data); internal COFF_ObjSection * coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_SectionFlags flags, String8 data);
internal COFF_ObjSymbol* coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymbolLocation loc, COFF_SymbolType type, COFF_SymStorageClass storage_class); internal COFF_ObjSymbol* coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymbolLocation loc, COFF_SymbolType type, COFF_SymStorageClass storage_class);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_extern_func(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_extern(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_extern(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_static(COFF_ObjWriter *obj_writer, String8 name, U32 off, COFF_ObjSection *section);
internal COFF_ObjSymbol * coff_obj_writer_push_symbol_secdef(COFF_ObjWriter *obj_writer, COFF_ObjSection *section, COFF_ComdatSelectType selection); internal COFF_ObjSymbol * coff_obj_writer_push_symbol_secdef(COFF_ObjWriter *obj_writer, COFF_ObjSection *section, COFF_ComdatSelectType selection);
+108 -43
View File
@@ -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_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_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_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_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_PdbAltPath, "%%_RAD_PDB_PATH%%");
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_PdbPageSize, "%u", KB(4)); 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) { if (obj_node_arr.v[obj_idx].data.header.machine != COFF_MachineType_Unknown) {
config->machine = obj_node_arr.v[obj_idx].data.header.machine; 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) { if (config->infer_function_pad_min) {
config->function_pad_min = push_array(tp_arena->v[0], U64, 1); config->function_pad_min = lnk_get_default_function_pad_min(config->machine);
*config->function_pad_min = lnk_get_default_function_pad_min(config->machine);
} }
break; break;
@@ -2350,13 +2348,15 @@ THREAD_POOL_TASK_FUNC(lnk_gather_section_contribs_task)
for (U64 sect_idx = 0; sect_idx < obj->header.section_count_no_null; sect_idx += 1) { 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 = &section_table[sect_idx]; COFF_SectionHeader *sect_header = &section_table[sect_idx];
if (~sect_header->flags & COFF_SectionFlag_LnkRemove) { if (~sect_header->flags & COFF_SectionFlag_LnkRemove && sect_header->fsize > 0) {
LNK_SectionContribChunk *sc_chunk = 0;
{
Temp temp = temp_begin(scratch.arena); Temp temp = temp_begin(scratch.arena);
String8 sect_name = coff_name_from_section_header(string_table, sect_header); 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); 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); hash_table_search_string_raw(task->contribs_ht, sect_name_with_flags, &sc_chunk);
temp_end(temp);
}
if (sc_chunk) { if (sc_chunk) {
U16 sc_align = coff_align_size_from_section_flags(sect_header->flags); 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_idx = obj_idx;
sc->u.obj_sect_idx = sect_idx; sc->u.obj_sect_idx = sect_idx;
} }
temp_end(temp);
} }
task->sect_map[obj_idx][sect_idx] = sc; task->sect_map[obj_idx][sect_idx] = sc;
} }
@@ -2402,6 +2400,43 @@ THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_task)
ProfEnd(); 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 internal
THREAD_POOL_TASK_FUNC(lnk_split_func_contribs_task) 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); ProfBeginV("%S", obj->path);
U64List func_list = {0};
COFF_ParsedSymbol symbol; 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->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx); 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) { 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; U64 offset_map_count = 0;
for (String8Node *data_n = &sc->first_data_node; data_n != 0; data_n = data_n->next) { for (String8Node *data_n = &sc->first_data_node; data_n != 0; data_n = data_n->next) {
offset_map_count += 1; offset_map_count += 1;
} }
if (offset_map_count <= 1) { continue; }
Temp temp = temp_begin(scratch.arena); PairU64 *offset_map = push_array(scratch.arena, PairU64, offset_map_count);
PairU64 *offset_map = push_array(temp.arena, PairU64, offset_map_count);
U64 data_node_idx = 0; U64 data_node_idx = 0;
U64 prev_cursor_offset = 0; U64 prev_cursor_offset = 0;
U64 new_cursor_offset = 0; U64 new_cursor_offset = 0;
@@ -2499,6 +2533,19 @@ THREAD_POOL_TASK_FUNC(lnk_split_func_contribs_task)
new_cursor_offset += Max(task->function_pad_min, data_n->string.size); new_cursor_offset += Max(task->function_pad_min, data_n->string.size);
} }
sect_offset_map_counts[sect_idx] = offset_map_count;
sect_offset_map[sect_idx] = offset_map;
}
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) { for (U64 reloc_idx = 0; reloc_idx < reloc_info.count; reloc_idx += 1) {
COFF_Reloc *reloc = &relocs[reloc_idx]; COFF_Reloc *reloc = &relocs[reloc_idx];
U64 offset_idx = pair_u64_nearest_v0(offset_map, offset_map_count, reloc->apply_off); U64 offset_idx = pair_u64_nearest_v0(offset_map, offset_map_count, reloc->apply_off);
@@ -2508,10 +2555,21 @@ THREAD_POOL_TASK_FUNC(lnk_split_func_contribs_task)
InvalidPath; InvalidPath;
} }
} }
temp_end(temp); }
}
} }
// TODO: update symbols with new offsets 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(); ProfEnd();
@@ -2608,16 +2666,18 @@ THREAD_POOL_TASK_FUNC(lnk_patch_regular_symbols_task)
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular) { 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); 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]; 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); section_number = safe_cast_u32(sc->u.sect_idx + 1);
value = sc->u.off + symbol.value; value = sc->u.off + symbol.value;
} }
}
if (obj->header.is_big_obj) { if (obj->header.is_big_obj) {
COFF_Symbol32 *symbol32 = symbol.raw_symbol; COFF_Symbol32 *symbol32 = symbol.raw_symbol;
@@ -3013,15 +3073,17 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher)
U32 symbol_secoff = 0; U32 symbol_secoff = 0;
S64 symbol_voff = 0; S64 symbol_voff = 0;
{ {
COFF_ParsedSymbol symbol; COFF_ParsedSymbol symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, reloc->isymbol);
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_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class); COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
if (interp == COFF_SymbolValueInterp_Regular) { 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, &section_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_secnum = symbol.section_number;
symbol_secoff = symbol.value; 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);
@@ -4007,7 +4069,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
LNK_BuildImageTask task = {0}; LNK_BuildImageTask task = {0};
task.symtab = symtab; task.symtab = symtab;
task.sectab = sectab; 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.default_align = coff_default_align_from_machine(config->machine);
task.objs_count = objs_count; task.objs_count = objs_count;
task.objs = objs; task.objs = objs;
@@ -4153,10 +4215,6 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
ProfEnd(); ProfEnd();
} }
ProfBegin("Set COMDAT Leaders");
tp_for_parallel(tp, 0, objs_count, lnk_set_comdat_leaders_task, &task);
ProfEnd();
// build common block // build common block
// //
// TODO: build common block in .bss and merge with .data // 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); 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 // 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; U64 common_block_cursor = common_block_sect->vsize;
// compute and assign offsets into the common block // 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 // assign contribs offsets, sizes, and section indices
for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) { for (LNK_SectionNode *sect_n = sectab->list.first; sect_n != 0; sect_n = sect_n->next) {
lnk_finalize_section_layout(&sect_n->data, config->file_align, *config->function_pad_min); lnk_finalize_section_layout(&sect_n->data, config->file_align, config->function_pad_min);
} }
// remove empty sections // remove empty sections
@@ -4278,15 +4336,14 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
// assing layout offsets and sizes to merged sections // 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) { for (LNK_SectionNode *sect_n = sectab->merge_list.first; sect_n != 0; sect_n = sect_n->next) {
LNK_Section *sect = &sect_n->data; LNK_Section *sect = &sect_n->data;
LNK_Section *final_sect = sect->merge_dst;
LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect); LNK_SectionContrib *first_sc = lnk_get_first_section_contrib(sect);
LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect); LNK_SectionContrib *last_sc = lnk_get_last_section_contrib(sect);
U64 last_sc_size = lnk_size_from_section_contrib(last_sc); U64 last_sc_size = lnk_size_from_section_contrib(last_sc);
sect->voff = final_sect->voff + first_sc->u.off; sect->voff = sect->merge_dst->voff + first_sc->u.off;
sect->vsize = (last_sc->u.off - first_sc->u.off) + last_sc_size; sect->vsize = (last_sc->u.off - first_sc->u.off) + last_sc_size;
sect->foff = final_sect->foff + first_sc->u.off; sect->foff = sect->merge_dst->foff + first_sc->u.off;
sect->fsize = (last_sc->u.off - first_sc->u.off) + last_sc_size; sect->fsize = (last_sc->u.off - first_sc->u.off) + last_sc_size;
sect->sect_idx = final_sect->sect_idx; lnk_assign_section_index(sect, sect->merge_dst->sect_idx);
} }
ProfEnd(); 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; task.u.patch_symtabs.common_block_contribs = common_block_contribs;
ProfEnd(); 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"); ProfBegin("Patch Common Block Leaders");
tp_for_parallel(tp, 0, tp->worker_count, lnk_patch_common_block_leaders_task, &task); tp_for_parallel(tp, 0, tp->worker_count, lnk_patch_common_block_leaders_task, &task);
ProfEnd(); ProfEnd();
@@ -4372,7 +4437,7 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolT
sc->align = 1; sc->align = 1;
sc->u.obj_idx = max_U32; 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_virtual_space(reloc, config->sect_align, &voff_cursor);
lnk_assign_section_index(reloc, sectab->next_sect_idx++); 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->first_data_node = *image_header_data.first;
image_header_sc->last_data_node = image_header_data.last; 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"); ProfBegin("Patch Section Symbols");
+2
View File
@@ -16,6 +16,8 @@ typedef struct LNK_LinkContext
// -- Image -------------------------------------------------------------------- // -- Image --------------------------------------------------------------------
#define LNK_REMOVED_SECTION_NUMBER (U16)-3
typedef struct LNK_ImageContext typedef struct LNK_ImageContext
{ {
String8 image_data; String8 image_data;
+2 -2
View File
@@ -1203,9 +1203,9 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
case LNK_CmdSwitch_FunctionPadMin: { case LNK_CmdSwitch_FunctionPadMin: {
if (value_strings.node_count == 0) { if (value_strings.node_count == 0) {
config->function_pad_min = 0; config->function_pad_min = 0;
config->infer_function_pad_min = 1;
} else { } else {
config->function_pad_min = push_array(arena, U64, 1); lnk_cmd_switch_parse_u64(obj_path, lib_path, cmd_switch, value_strings, &config->function_pad_min, LNK_ParseU64Flag_CheckUnder32bit);
lnk_cmd_switch_parse_u64(obj_path, lib_path, cmd_switch, value_strings, config->function_pad_min, LNK_ParseU64Flag_CheckUnder32bit);
} }
config->do_function_pad_min = LNK_SwitchState_Yes; config->do_function_pad_min = LNK_SwitchState_Yes;
} break; } break;
+2 -1
View File
@@ -325,7 +325,8 @@ typedef struct LNK_Config
U64 max_worker_count; U64 max_worker_count;
String8 shared_thread_pool_name; String8 shared_thread_pool_name;
LNK_SwitchState do_function_pad_min; LNK_SwitchState do_function_pad_min;
U64 *function_pad_min; B32 infer_function_pad_min;
U64 function_pad_min;
U64 *manifest_resource_id; U64 *manifest_resource_id;
B32 no_default_libs; B32 no_default_libs;
Version link_ver; Version link_ver;
+1
View File
@@ -40,6 +40,7 @@ typedef enum
LNK_Error_UnresolvedSymbol, LNK_Error_UnresolvedSymbol,
LNK_Error_AssociativeLoop, LNK_Error_AssociativeLoop,
LNK_Error_AlternateNameConflict, LNK_Error_AlternateNameConflict,
LNK_Error_RelocationAgainstRemovedSection,
LNK_Error_StopLast, LNK_Error_StopLast,
LNK_Error_First, LNK_Error_First,
+4
View File
@@ -299,6 +299,10 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
switch (interp) { switch (interp) {
case COFF_SymbolValueInterp_Regular: { case COFF_SymbolValueInterp_Regular: {
if (symbol.storage_class == COFF_SymStorageClass_External) { if (symbol.storage_class == COFF_SymStorageClass_External) {
COFF_SectionHeader *sect_header = lnk_coff_section_header_from_section_number(obj, symbol.section_number);
if (sect_header->flags & COFF_SectionFlag_LnkRemove) {
break;
}
LNK_Symbol *defn = lnk_make_defined_symbol(arena, symbol.name, obj, symbol_idx); LNK_Symbol *defn = lnk_make_defined_symbol(arena, symbol.name, obj, symbol_idx);
U64 hash = lnk_symbol_hash(symbol.name); U64 hash = lnk_symbol_hash(symbol.name);
lnk_symbol_table_push_(task->symtab, arena, worker_id, LNK_SymbolScope_Defined, hash, defn); lnk_symbol_table_push_(task->symtab, arena, worker_id, LNK_SymbolScope_Defined, hash, defn);
+1 -1
View File
@@ -347,7 +347,7 @@ lnk_finalize_section_layout(LNK_Section *sect, U64 file_align, U64 function_pad_
for (U64 sc_idx = 0; sc_idx < sc_chunk->count; sc_idx += 1) { for (U64 sc_idx = 0; sc_idx < sc_chunk->count; sc_idx += 1) {
LNK_SectionContrib *sc = sc_chunk->v[sc_idx]; LNK_SectionContrib *sc = sc_chunk->v[sc_idx];
// assign offset and size // assign offset
cursor = AlignPow2(cursor, sc->align); cursor = AlignPow2(cursor, sc->align);
sc->u.off = cursor; sc->u.off = cursor;
+43
View File
@@ -3352,6 +3352,48 @@ exit:;
return result; return result;
} }
internal T_Result
t_function_pad_min(void)
{
Temp scratch = scratch_begin(0,0);
T_Result result = T_Result_Fail;
{
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64);
U8 ret[] = { 0xc3, 0xc3, 0xc3 };
COFF_ObjSection *text_sect = t_push_text_section(obj_writer, str8_array_fixed(ret));
coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("A"), 0, text_sect);
coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("B"), 1, text_sect);
coff_obj_writer_push_symbol_extern_func(obj_writer, str8_lit("C"), 2, text_sect);
String8 obj = coff_obj_writer_serialize(scratch.arena, obj_writer);
coff_obj_writer_release(&obj_writer);
if (!t_write_file(str8_lit("funcs.obj"), obj)) { goto exit; }
}
int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:A /functionpadmin:8 /out:a.exe funcs.obj");
if (linker_exit_code != 0) { goto exit; }
String8 exe = t_read_file(scratch.arena, str8_lit("a.exe"));
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe);
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str;
String8 string_table = str8_substr(exe, pe.string_table_range);
COFF_SectionHeader *text_sect = t_coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".text"));
if (text_sect == 0) { goto exit; }
String8 text_data = str8_substr(exe, rng_1u64(text_sect->foff, text_sect->foff + text_sect->vsize));
U8 expected_text[] = {
0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc
};
if (!str8_match(text_data, str8_array_fixed(expected_text), 0)) { goto exit; }
result = T_Result_Pass;
exit:;
scratch_end(scratch);
return result;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
internal void internal void
@@ -3405,6 +3447,7 @@ entry_point(CmdLine *cmdline)
{ "delay_import_user32", t_delay_import_user32 }, { "delay_import_user32", t_delay_import_user32 },
{ "empty_section", t_empty_section }, { "empty_section", t_empty_section },
{ "removed_section", t_removed_section }, { "removed_section", t_removed_section },
{ "function_pad_min", t_function_pad_min },
//{ "import_export", t_import_export }, //{ "import_export", t_import_export },
}; };