WIP function pad min

This commit is contained in:
Nikita Smith
2025-06-10 19:38:43 -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;
}
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 *
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_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_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);
+138 -73
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_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 = &section_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, &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_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 = &section_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(&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
@@ -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 = &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 = &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");
+2
View File
@@ -16,6 +16,8 @@ typedef struct LNK_LinkContext
// -- Image --------------------------------------------------------------------
#define LNK_REMOVED_SECTION_NUMBER (U16)-3
typedef struct LNK_ImageContext
{
String8 image_data;
+3 -3
View File
@@ -1202,10 +1202,10 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
case LNK_CmdSwitch_FunctionPadMin: {
if (value_strings.node_count == 0) {
config->function_pad_min = 0;
config->function_pad_min = 0;
config->infer_function_pad_min = 1;
} 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;
} break;
+2 -1
View File
@@ -325,7 +325,8 @@ typedef struct LNK_Config
U64 max_worker_count;
String8 shared_thread_pool_name;
LNK_SwitchState do_function_pad_min;
U64 *function_pad_min;
B32 infer_function_pad_min;
U64 function_pad_min;
U64 *manifest_resource_id;
B32 no_default_libs;
Version link_ver;
+1
View File
@@ -40,6 +40,7 @@ typedef enum
LNK_Error_UnresolvedSymbol,
LNK_Error_AssociativeLoop,
LNK_Error_AlternateNameConflict,
LNK_Error_RelocationAgainstRemovedSection,
LNK_Error_StopLast,
LNK_Error_First,
+4
View File
@@ -299,6 +299,10 @@ THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table)
switch (interp) {
case COFF_SymbolValueInterp_Regular: {
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);
U64 hash = lnk_symbol_hash(symbol.name);
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) {
LNK_SectionContrib *sc = sc_chunk->v[sc_idx];
// assign offset and size
// assign offset
cursor = AlignPow2(cursor, sc->align);
sc->u.off = cursor;
+43
View File
@@ -3352,6 +3352,48 @@ exit:;
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
@@ -3405,6 +3447,7 @@ entry_point(CmdLine *cmdline)
{ "delay_import_user32", t_delay_import_user32 },
{ "empty_section", t_empty_section },
{ "removed_section", t_removed_section },
{ "function_pad_min", t_function_pad_min },
//{ "import_export", t_import_export },
};