From 307d3a7f4bdbdaa461c0e44d92a0f557739f9bc9 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Wed, 9 Apr 2025 15:18:40 -0700 Subject: [PATCH] check obj compatibility before initializing them --- src/linker/lnk.c | 34 ++++++++++++---------------------- src/linker/lnk_lib.c | 2 +- src/linker/lnk_obj.c | 30 ++++++++++++++++++++++++++---- src/linker/lnk_obj.h | 4 ++-- 4 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 1dea30a5..2e3f6eb0 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -189,8 +189,8 @@ lnk_input_import_is_before(void *raw_a, void *raw_b) int lnk_input_import_compar(const void *raw_a, const void *raw_b) { - const LNK_InputImport **a = (const LNK_InputImport **) raw_a; - const LNK_InputImport **b = (const LNK_InputImport **) raw_b; + LNK_InputImport * const *a = raw_a; + LNK_InputImport * const *b = raw_b; int cmp = str8_compar_ignore_case(&(*a)->import_header.dll_name, &(*b)->import_header.dll_name); if (cmp == 0) { cmp = str8_compar_case_sensitive(&(*a)->import_header.func_name, &(*b)->import_header.func_name); @@ -3761,29 +3761,19 @@ lnk_run(int argc, char **argv) } ProfEnd(); - LNK_ObjNodeArray obj_node_arr = lnk_obj_list_push_parallel(tp, tp_arena, &obj_list, sectab, config->function_pad_min, unique_obj_input_list.count, input_obj_arr); - - ProfBegin("Machine Compat Check"); - for (U64 obj_idx = 0; obj_idx < obj_node_arr.count; ++obj_idx) { - LNK_Obj *obj = &obj_node_arr.v[obj_idx].data; - - // derive machine from obj - if (config->machine == COFF_MachineType_Unknown) { - config->machine = obj->machine; - } else if (config->machine != COFF_MachineType_X64) { - lnk_error_with_loc(LNK_Error_UnsupportedMachine, obj->path, obj->lib_path, "%S machine is supported", coff_string_from_machine_type(obj->machine)); - } else { - // is obj machine compatible? - if (config->machine != obj->machine && - obj->machine != COFF_MachineType_Unknown) { // obj with unknown machine type is compatible with any other machine type - lnk_error_obj(LNK_Error_IncompatibleObj, obj, - "conflicting machine types expected %S but got %S", - coff_string_from_machine_type(config->machine), - coff_string_from_machine_type(obj->machine)); + LNK_ObjNodeArray obj_node_arr = lnk_obj_list_push_parallel(tp, tp_arena, &obj_list, sectab, config->function_pad_min, config->machine, unique_obj_input_list.count, input_obj_arr); + + // + // if the machine was omitted on the command line, derive machine from obj + // + if (config->machine == COFF_MachineType_Unknown) { + for (U64 obj_idx = 0; obj_idx < obj_node_arr.count; obj_idx += 1) { + if (obj_node_arr.v[obj_idx].data.machine != COFF_MachineType_Unknown) { + config->machine = obj_node_arr.v[obj_idx].data.machine; + break; } } } - ProfEnd(); ProfBegin("Collect Directives"); for (U64 i = 0; i < obj_node_arr.count; ++i) { diff --git a/src/linker/lnk_lib.c b/src/linker/lnk_lib.c index d02f4fac..d8b9c37b 100644 --- a/src/linker/lnk_lib.c +++ b/src/linker/lnk_lib.c @@ -941,7 +941,7 @@ lnk_build_import_lib(TP_Context *tp, TP_Arena *arena, COFF_MachineType machine, LNK_InputObj **inputs = lnk_array_from_input_obj_list(scratch.arena, input_obj_list); LNK_SectionTable *sectab = lnk_section_table_alloc(0,0,0); LNK_ObjList obj_list = {0}; - lnk_obj_list_push_parallel(tp, arena, &obj_list, sectab, 0, input_obj_list.count, inputs); + lnk_obj_list_push_parallel(tp, arena, &obj_list, sectab, 0, machine, input_obj_list.count, inputs); LNK_LibBuild import_lib = lnk_build_lib(scratch.arena, machine, time_stamp, dll_name, obj_list, exptab); B32 emit_second_member = 0; // MSVC linker refuses to link with lib that has the second member. diff --git a/src/linker/lnk_obj.c b/src/linker/lnk_obj.c index 877f720f..2c305ee7 100644 --- a/src/linker/lnk_obj.c +++ b/src/linker/lnk_obj.c @@ -399,10 +399,30 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) // // parse obj header // - COFF_FileHeaderInfo coff_info = coff_file_header_info_from_data(input->data); - String8 raw_coff_section_table = str8_substr(input->data, coff_info.section_table_range); - String8 raw_coff_symbol_table = str8_substr(input->data, coff_info.symbol_table_range); - String8 raw_coff_string_table = str8_substr(input->data, coff_info.string_table_range); + COFF_FileHeaderInfo coff_info = coff_file_header_info_from_data(input->data); + + // + // set & check machine compatibility + // + { + if (task->machine == COFF_MachineType_Unknown) { + ins_atomic_u32_eval_assign(&task->machine, coff_info.machine); + } + + if (coff_info.machine != COFF_MachineType_Unknown && task->machine != coff_info.machine) { + lnk_error_with_loc(LNK_Error_IncompatibleObj, input->path, input->lib_path, + "conflicting machine types expected %S but got %S", + coff_string_from_machine_type(task->machine), + coff_string_from_machine_type(coff_info.machine)); + } + } + + // + // extract COFF info + // + String8 raw_coff_section_table = str8_substr(input->data, coff_info.section_table_range); + String8 raw_coff_symbol_table = str8_substr(input->data, coff_info.symbol_table_range); + String8 raw_coff_string_table = str8_substr(input->data, coff_info.string_table_range); // // error check: section table / symbol table / string table @@ -714,6 +734,7 @@ lnk_obj_list_push_parallel(TP_Context *tp, LNK_ObjList *obj_list, LNK_SectionTable *sectab, U64 *function_pad_min, + COFF_MachineType machine, U64 input_count, LNK_InputObj **inputs) { @@ -730,6 +751,7 @@ lnk_obj_list_push_parallel(TP_Context *tp, task.obj_id_base = obj_id_base; task.obj_node_arr = obj_arr.v; task.function_pad_min = function_pad_min; + task.machine = machine; tp_for_parallel(tp, arena, input_count, lnk_obj_initer, &task); } ProfEnd(); diff --git a/src/linker/lnk_obj.h b/src/linker/lnk_obj.h index ec07d32e..f7790b54 100644 --- a/src/linker/lnk_obj.h +++ b/src/linker/lnk_obj.h @@ -54,7 +54,6 @@ typedef struct LNK_Obj String8 path; String8 lib_path; U64 input_idx; - U64 common_symbol_size; COFF_MachineType machine; U64 chunk_count; U64 sect_count; @@ -114,6 +113,7 @@ typedef struct LNK_SectDefnList *defn_arr; LNK_SectionTable *sectab; U64 *function_pad_min; + U32 machine; } LNK_ObjIniter; typedef struct @@ -198,7 +198,7 @@ internal LNK_InputObjList lnk_input_obj_list_from_string_list(Arena *arena, Stri internal LNK_Obj ** lnk_obj_arr_from_list(Arena *arena, LNK_ObjList list); internal LNK_ObjNodeArray lnk_obj_list_reserve(Arena *arena, LNK_ObjList *list, U64 count); internal LNK_ChunkList * lnk_collect_obj_chunks(TP_Context *tp, TP_Arena *arena, U64 obj_count, LNK_Obj **obj_arr, String8 name, String8 postfix, B32 collect_discarded); -internal LNK_ObjNodeArray lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *tp_arena, LNK_ObjList *obj_list, LNK_SectionTable *sectab, U64 *function_pad_min, U64 input_count, LNK_InputObj **inputs); +internal LNK_ObjNodeArray lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *tp_arena, LNK_ObjList *obj_list, LNK_SectionTable *sectab, U64 *function_pad_min, COFF_MachineType machine, U64 input_count, LNK_InputObj **inputs); internal LNK_Chunk * lnk_sect_chunk_array_from_coff(Arena *arena, U64 obj_id, String8 obj_path, String8 coff_data, U64 sect_count, COFF_SectionHeader *coff_sect_arr, String8 *sect_name_arr, String8 *sect_postfix_arr); internal LNK_SymbolArray lnk_symbol_array_from_coff(Arena *arena, LNK_Obj *obj, String8 obj_path, String8 lib_path, B32 is_big_obj, U64 function_pad_min, U64 sect_count, COFF_SectionHeader *section_table, U64 symbol_count, void *symbol_table, String8 string_table, LNK_ChunkPtr *chunk_table, LNK_Chunk *master_common_block);