From bd830a60235a4d0f40a438906712e04017c16601 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Wed, 7 May 2025 15:47:45 -0700 Subject: [PATCH] test case for relocation to undefined section with base relocations --- src/linker/lnk.c | 34 +++++++----------- src/torture/torture.c | 82 +++++++++++++++++++++++++++++++++---------- 2 files changed, 75 insertions(+), 41 deletions(-) diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 2fa3e468..518cc8b9 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -119,6 +119,7 @@ #include "lnk_io.h" #include "lnk_cmd_line.h" #include "lnk_input.h" +#include "lnk_image_section_flags.h" #include "lnk_import_table.h" #include "lnk_export_table.h" #include "lnk_config.h" @@ -1818,7 +1819,7 @@ lnk_build_base_relocs(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config, U6 } internal String8List -lnk_build_win32_image_header(Arena *arena, LNK_SymbolTable *symtab, LNK_Config *config, LNK_SectionArray sects, U64 expected_image_header_size) +lnk_build_win32_header(Arena *arena, LNK_SymbolTable *symtab, LNK_Config *config, LNK_SectionArray sects, U64 expected_image_header_size) { ProfBeginFunction(); @@ -2700,21 +2701,6 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S } } - // report unresolved symbols - { - for (U64 obj_idx = 0; obj_idx < objs_count; obj_idx += 1) { - LNK_Obj *obj = objs[obj_idx]; - 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_Undefined || interp == COFF_SymbolValueInterp_Weak) { - lnk_error_obj(LNK_Error_UnresolvedSymbol, obj, "unresolved symbol %S", symbol.name); - } - } - } - } - ProfEnd(); } @@ -2789,7 +2775,7 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S LNK_SectionArray sects; { sects = lnk_section_array_from_list(scratch.arena, sectab->list); - String8List image_header_data = lnk_build_win32_image_header(scratch.arena, symtab, config, sects, AlignPow2(expected_image_header_size, config->file_align)); + String8List image_header_data = lnk_build_win32_header(scratch.arena, symtab, config, sects, AlignPow2(expected_image_header_size, config->file_align)); LNK_Section *image_header_sect = lnk_section_table_push(sectab, str8_lit(".rad_linker_image_header_section"), 0); LNK_SectionContribChunk *image_header_sc_chunk = lnk_section_contrib_chunk_list_push_chunk(sectab->arena, &image_header_sect->contribs, 1); @@ -3254,7 +3240,7 @@ THREAD_POOL_TASK_FUNC(lnk_weak_symbol_finder) internal LNK_SymbolFinderResult lnk_run_symbol_finder(TP_Context *tp, TP_Arena *arena, - PathStyle path_style, + LNK_Config *config, LNK_SymbolTable *symtab, LNK_SymbolList lookup_list, TP_TaskFunc *task_func) @@ -3264,7 +3250,7 @@ lnk_run_symbol_finder(TP_Context *tp, ProfBegin("Setup Task"); LNK_SymbolFinder task = {0}; - task.path_style = path_style; + task.path_style = config->path_style; task.symtab = symtab; task.lookup_node_arr = lnk_symbol_node_array_from_list(scratch.arena, lookup_list); task.result_arr = push_array(scratch.arena, LNK_SymbolFinderResult, tp->worker_count); @@ -4018,7 +4004,7 @@ lnk_run(int argc, char **argv) ProfEnd(); } break; case State_PushDllHelperUndefSymbol: { - ProfBegin("Puhs Dll Helper Undef Symbol"); + ProfBegin("Push Dll Helper Undef Symbol"); String8 delay_helper_name = str8_zero(); switch (config->machine) { @@ -4044,8 +4030,9 @@ lnk_run(int argc, char **argv) } break; case State_LookupUndef: { ProfBegin("Lookup Undefined Symbols"); + // search archives - LNK_SymbolFinderResult result = lnk_run_symbol_finder(tp, tp_arena, config->path_style, symtab, lookup_undef_list, lnk_undef_symbol_finder); // TODO: put these on temp arena + LNK_SymbolFinderResult result = lnk_run_symbol_finder(tp, tp_arena, config, symtab, lookup_undef_list, lnk_undef_symbol_finder); // TODO: put these on temp arena // new inputs found input_obj_list = result.input_obj_list; @@ -4056,12 +4043,14 @@ lnk_run(int argc, char **argv) // reset input MemoryZeroStruct(&lookup_undef_list); + ProfEnd(); } break; case State_LookupWeak: { ProfBegin("Lookup Weak Symbols"); + // search archives - LNK_SymbolFinderResult result = lnk_run_symbol_finder(tp, tp_arena, config->path_style, symtab, lookup_weak_list, lnk_weak_symbol_finder); // TODO: put these on temp arena + LNK_SymbolFinderResult result = lnk_run_symbol_finder(tp, tp_arena, config, symtab, lookup_weak_list, lnk_weak_symbol_finder); // TODO: put these on temp arena // schedule new inputs input_obj_list = result.input_obj_list; @@ -4072,6 +4061,7 @@ lnk_run(int argc, char **argv) // reset input MemoryZeroStruct(&lookup_weak_list); + ProfEnd(); } break; case State_LookupEntryPoint: { diff --git a/src/torture/torture.c b/src/torture/torture.c index 335cd9fa..9978a78f 100644 --- a/src/torture/torture.c +++ b/src/torture/torture.c @@ -40,6 +40,7 @@ #include "linker/lnk_cmd_line.h" #include "linker/lnk_cmd_line.c" #include "linker/lnk_error.h" +#include "linker/lnk_image_section_flags.h" //////////////////////////////// @@ -295,19 +296,19 @@ typedef enum internal COFF_ObjSection * t_push_text_section(COFF_ObjWriter *obj_writer, String8 data) { - return coff_obj_writer_push_section(obj_writer, str8_lit(".text"), COFF_SectionFlag_CntCode|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute|COFF_SectionFlag_Align1Bytes, data); + return coff_obj_writer_push_section(obj_writer, str8_lit(".text"), LNK_TEXT_SECTION_FLAGS, data); } internal COFF_ObjSection * t_push_data_section(COFF_ObjWriter *obj_writer, String8 data) { - return coff_obj_writer_push_section(obj_writer, str8_lit(".data"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite|COFF_SectionFlag_Align1Bytes, data); + return coff_obj_writer_push_section(obj_writer, str8_lit(".data"), LNK_DATA_SECTION_FLAGS, data); } internal COFF_ObjSection * t_push_rdata_section(COFF_ObjWriter *obj_writer, String8 data) { - return coff_obj_writer_push_section(obj_writer, str8_lit(".rdata"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_Align1Bytes, data); + return coff_obj_writer_push_section(obj_writer, str8_lit(".rdata"), LNK_RDATA_SECTION_FLAGS, data); } internal T_Result @@ -837,12 +838,12 @@ t_undef_section(void) COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); U8 data[] = { 0, 0, 0, 0 }; - COFF_ObjSection *data_section = coff_obj_writer_push_section(obj_writer, str8_lit(".data"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite, str8_array_fixed(data)); + COFF_ObjSection *data_section = t_push_data_section(obj_writer, str8_array_fixed(data)); COFF_ObjSymbol *foo = coff_obj_writer_push_symbol_undef_section(obj_writer, str8_lit(".mysect"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead); coff_obj_writer_section_push_reloc(obj_writer, data_section, 0, foo, COFF_Reloc_X64_Addr32Nb); U8 text[] = { 0xC3 }; - COFF_ObjSection *text_section = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), COFF_SectionFlag_CntCode|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemExecute, str8_array_fixed(text)); + COFF_ObjSection *text_section = t_push_text_section(obj_writer, str8_array_fixed(text)); coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_section); main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); @@ -880,6 +881,48 @@ t_undef_section(void) return result; } +internal T_Result +t_undef_reloc_section(void) +{ + Temp scratch = scratch_begin(0,0); + T_Result result = T_Result_Fail; + + String8 main_obj; + { + COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_X64); + + U8 data[] = { 0, 0, 0, 0 }; + COFF_ObjSection *data_section = t_push_data_section(obj_writer, str8_array_fixed(data)); + COFF_ObjSymbol *foo = coff_obj_writer_push_symbol_undef_section(obj_writer, str8_lit(".reloc"), LNK_RELOC_SECTION_FLAGS); + coff_obj_writer_section_push_reloc(obj_writer, data_section, 0, foo, COFF_Reloc_X64_Addr32Nb); + + U8 text[] = { 0xC3 }; + COFF_ObjSection *text_section = coff_obj_writer_push_section(obj_writer, str8_lit(".text"), LNK_TEXT_SECTION_FLAGS, str8_array_fixed(text)); + coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("my_entry"), 0, text_section); + + main_obj = coff_obj_writer_serialize(scratch.arena, obj_writer); + + coff_obj_writer_release(&obj_writer); + } + + U8 payload[] = { 1, 2, 3 }; + String8 sec_defn_obj = t_make_sec_defn_obj(scratch.arena, str8_array_fixed(payload)); + + t_write_file(str8_lit("main.obj"), main_obj); + t_write_file(str8_lit("sec_defn.obj"), sec_defn_obj); + + int linker_exit_code = t_invoke_linker(str8_lit("/subsystem:console /entry:my_entry /out:a.exe main.obj sec_defn.obj")); + if (linker_exit_code == 0) { + goto exit; + } + + result = T_Result_Pass; + + exit:; + scratch_end(scratch); + return result; +} + internal T_Result t_find_merged_pdata(void) { @@ -1043,7 +1086,7 @@ t_flag_conf(void) } } - int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe data.obj conf.obj entry.obj"); + int linker_exit_code = t_invoke_linkerf("/subsystem:console /entry:my_entry /out:a.exe conf.obj entry.obj"); if (linker_exit_code != 0) { goto exit; } @@ -1542,19 +1585,20 @@ entry_point(CmdLine *cmdline) char *label; T_Result (*r)(void); } target_array[] = { - { "simple_link_test", t_simple_link_test }, - { "undef_section", t_undef_section }, - { "abs_vs_weak", t_abs_vs_weak }, - { "abs_vs_regular", t_abs_vs_regular }, - { "abs_vs_common", t_abs_vs_common }, - { "undef_weak", t_undef_weak }, - { "weak_cycle", t_weak_cycle }, - { "weak_tag", t_weak_tag }, - { "find_merged_pdata", t_find_merged_pdata }, - { "section_sort", t_section_sort }, - { "flag_conf", t_flag_conf }, - { "invalid_bss", t_invalid_bss }, - { "common_block", t_common_block }, + { "simple_link_test", t_simple_link_test }, + { "undef_section", t_undef_section }, + { "undef_reloc_section", t_undef_reloc_section }, + { "abs_vs_weak", t_abs_vs_weak }, + { "abs_vs_regular", t_abs_vs_regular }, + { "abs_vs_common", t_abs_vs_common }, + { "undef_weak", t_undef_weak }, + { "weak_cycle", t_weak_cycle }, + { "weak_tag", t_weak_tag }, + { "find_merged_pdata", t_find_merged_pdata }, + { "section_sort", t_section_sort }, + { "flag_conf", t_flag_conf }, + { "invalid_bss", t_invalid_bss }, + { "common_block", t_common_block }, //{ "base_relocs", t_base_relocs }, { "simple_lib_test", t_simple_lib_test }, { "import_export", t_import_export },