diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 84b75ba1..bfb1a761 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -2199,7 +2199,7 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S // obj list -> array // U64 objs_count = obj_list.count; - LNK_Obj **objs = lnk_obj_arr_from_list(scratch.arena, obj_list); + LNK_Obj **objs = lnk_array_from_obj_list(scratch.arena, obj_list); ProfBegin("Remove Associatives"); { diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index 4bf717db..d4c1bd60 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -367,7 +367,7 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, String8List lib_dir // obj list -> array U64 obj_count = obj_list.count; - LNK_Obj **obj_arr = lnk_obj_arr_from_list(tp_arena->v[0], obj_list); + LNK_Obj **obj_arr = lnk_array_from_obj_list(tp_arena->v[0], obj_list); // gather debug info sections from objs ProfBegin("Collect CodeView"); diff --git a/src/linker/lnk_obj.c b/src/linker/lnk_obj.c index 3c8895f8..b84254f3 100644 --- a/src/linker/lnk_obj.c +++ b/src/linker/lnk_obj.c @@ -11,23 +11,14 @@ lnk_error_obj(LNK_ErrorCode code, LNK_Obj *obj, char *fmt, ...) va_end(args); } -//////////////////////////////// - -internal LNK_ObjNodeArray -lnk_obj_list_reserve(Arena *arena, LNK_ObjList *list, U64 count) +internal LNK_Obj ** +lnk_array_from_obj_list(Arena *arena, LNK_ObjList list) { - LNK_ObjNodeArray arr = {0}; - if (count) { - arr.count = count; - arr.v = push_array(arena, LNK_ObjNode, count); - for (LNK_ObjNode *ptr = arr.v, *opl = arr.v + arr.count; ptr < opl; ++ptr) { - SLLQueuePush(list->first, list->last, ptr); - } - list->count += count; - } else { - MemoryZeroStruct(&arr); + LNK_Obj **arr = push_array_no_zero(arena, LNK_Obj *, list.count); + U64 idx = 0; + for (LNK_ObjNode *node = list.first; node != 0; node = node->next, ++idx) { + arr[idx] = &node->data; } - return arr; } @@ -244,33 +235,131 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) internal LNK_ObjNodeArray lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *arena, - LNK_ObjList *obj_list, + LNK_ObjList *list, COFF_MachineType machine, U64 input_count, LNK_InputObj **inputs) { ProfBeginFunction(); + + // store base id + U64 obj_id_base = list->count; + + // reserve obj nodes + LNK_ObjNodeArray objs = {0}; + if (input_count > 0) { + objs.count = input_count; + objs.v = push_array(arena->v[0], LNK_ObjNode, input_count); + for (LNK_ObjNode *ptr = objs.v, *opl = objs.v + input_count; ptr < opl; ++ptr) { + SLLQueuePush(list->first, list->last, ptr); + } + list->count += input_count; + } + // fill out & run task LNK_ObjIniter task = {0}; task.inputs = inputs; - task.obj_id_base = obj_list->count; - task.objs = lnk_obj_list_reserve(arena->v[0], obj_list, input_count); + task.obj_id_base = obj_id_base; + task.objs = objs; task.machine = machine; tp_for_parallel(tp, arena, input_count, lnk_obj_initer, &task); ProfEnd(); - return task.objs; + return objs; } -internal LNK_Obj ** -lnk_obj_arr_from_list(Arena *arena, LNK_ObjList list) +internal +THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table) { - LNK_Obj **arr = push_array_no_zero(arena, LNK_Obj *, list.count); - U64 idx = 0; - for (LNK_ObjNode *node = list.first; node != 0; node = node->next, ++idx) { - arr[idx] = &node->data; + LNK_InputCoffSymbolTable *task = raw_task; + LNK_Obj *obj = &task->objs.v[task_id].data; + + // + // parse obj header + // + COFF_FileHeaderInfo header = coff_file_header_info_from_data(obj->data); + + // + // extract COFF info + // + String8 raw_coff_section_table = str8_substr(obj->data, header.section_table_range); + String8 raw_coff_symbol_table = str8_substr(obj->data, header.symbol_table_range); + String8 raw_coff_string_table = str8_substr(obj->data, header.string_table_range); + + COFF_ParsedSymbol symbol = {0}; + for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { + // read symbol + 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); + switch (interp) { + case COFF_SymbolValueInterp_Regular: { + if (symbol.storage_class == COFF_SymStorageClass_External) { + 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); + } + } break; + case COFF_SymbolValueInterp_Weak: { + 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); + + lnk_symbol_list_push(arena, &task->weak_lists[task_id], defn); + } break; + case COFF_SymbolValueInterp_Common: { + 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); + } break; + case COFF_SymbolValueInterp_Abs: { + if (symbol.storage_class == COFF_SymStorageClass_External) { + 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); + } + } break; + case COFF_SymbolValueInterp_Undefined: { + LNK_Symbol *s = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Defined, symbol.name); + if (s == 0) { + if (symbol.storage_class == COFF_SymStorageClass_External) { + LNK_Symbol *undef = lnk_make_undefined_symbol(arena, symbol.name, obj); + lnk_symbol_list_push(arena, &task->undef_lists[worker_id], undef); + } else if (symbol.storage_class == COFF_SymStorageClass_Section) { + // lookup is performed during image patching step + } else { + Assert(!"unexpected storage class on undefined symbol"); + } + } + } break; + case COFF_SymbolValueInterp_Debug: { + // not used + } break; + default: { InvalidPath; } break; + } } - return arr; +} + +internal LNK_SymbolInputResult +lnk_input_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, LNK_ObjNodeArray objs) +{ + ProfBeginFunction(); + Temp scratch = scratch_begin(arena->v, arena->count); + + LNK_InputCoffSymbolTable task = {0}; + task.symtab = symtab; + task.objs = objs; + task.weak_lists = push_array(scratch.arena, LNK_SymbolList, tp->worker_count); + task.undef_lists = push_array(scratch.arena, LNK_SymbolList, tp->worker_count); + tp_for_parallel(tp, arena, objs.count, lnk_input_coff_symbol_table, &task); + + LNK_SymbolInputResult result = {0}; + SLLConcatInPlaceArray(&result.weak_symbols, task.weak_lists, tp->worker_count); + SLLConcatInPlaceArray(&result.undef_symbols, task.undef_lists, tp->worker_count); + + scratch_end(scratch); + ProfEnd(); + return result; } internal COFF_ParsedSymbol @@ -441,97 +530,3 @@ lnk_parse_msvc_linker_directive(Arena *arena, LNK_Obj *obj, LNK_DirectiveInfo *d scratch_end(scratch); } -internal -THREAD_POOL_TASK_FUNC(lnk_input_coff_symbol_table) -{ - LNK_InputCoffSymbolTable *task = raw_task; - LNK_Obj *obj = &task->objs.v[task_id].data; - - // - // parse obj header - // - COFF_FileHeaderInfo header = coff_file_header_info_from_data(obj->data); - - // - // extract COFF info - // - String8 raw_coff_section_table = str8_substr(obj->data, header.section_table_range); - String8 raw_coff_symbol_table = str8_substr(obj->data, header.symbol_table_range); - String8 raw_coff_string_table = str8_substr(obj->data, header.string_table_range); - - COFF_ParsedSymbol symbol = {0}; - for (U64 symbol_idx = 0; symbol_idx < header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) { - // read symbol - 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); - switch (interp) { - case COFF_SymbolValueInterp_Regular: { - if (symbol.storage_class == COFF_SymStorageClass_External) { - 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); - } - } break; - case COFF_SymbolValueInterp_Weak: { - 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); - - lnk_symbol_list_push(arena, &task->weak_lists[task_id], defn); - } break; - case COFF_SymbolValueInterp_Common: { - 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); - } break; - case COFF_SymbolValueInterp_Abs: { - if (symbol.storage_class == COFF_SymStorageClass_External) { - 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); - } - } break; - case COFF_SymbolValueInterp_Undefined: { - LNK_Symbol *s = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Defined, symbol.name); - if (s == 0) { - if (symbol.storage_class == COFF_SymStorageClass_External) { - LNK_Symbol *undef = lnk_make_undefined_symbol(arena, symbol.name, obj); - lnk_symbol_list_push(arena, &task->undef_lists[worker_id], undef); - } else if (symbol.storage_class == COFF_SymStorageClass_Section) { - // lookup is performed during image patching step - } else { - Assert(!"unexpected storage class on undefined symbol"); - } - } - } break; - case COFF_SymbolValueInterp_Debug: { - // not used - } break; - default: { InvalidPath; } break; - } - } -} - -internal LNK_SymbolInputResult -lnk_input_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, LNK_ObjNodeArray objs) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(arena->v, arena->count); - - LNK_InputCoffSymbolTable task = {0}; - task.symtab = symtab; - task.objs = objs; - task.weak_lists = push_array(scratch.arena, LNK_SymbolList, tp->worker_count); - task.undef_lists = push_array(scratch.arena, LNK_SymbolList, tp->worker_count); - tp_for_parallel(tp, arena, objs.count, lnk_input_coff_symbol_table, &task); - - LNK_SymbolInputResult result = {0}; - SLLConcatInPlaceArray(&result.weak_symbols, task.weak_lists, tp->worker_count); - SLLConcatInPlaceArray(&result.undef_symbols, task.undef_lists, tp->worker_count); - - scratch_end(scratch); - ProfEnd(); - return result; -} - diff --git a/src/linker/lnk_obj.h b/src/linker/lnk_obj.h index 3f374609..dd025992 100644 --- a/src/linker/lnk_obj.h +++ b/src/linker/lnk_obj.h @@ -3,7 +3,7 @@ #pragma once -//////////////////////////////// +// --- Input ------------------------------------------------------------------- typedef struct LNK_Obj { @@ -34,7 +34,13 @@ typedef struct LNK_ObjNodeArray LNK_ObjNode *v; } LNK_ObjNodeArray; -//////////////////////////////// +typedef struct LNK_SymbolInputResult +{ + LNK_SymbolList weak_symbols; + LNK_SymbolList undef_symbols; +} LNK_SymbolInputResult; + +// --- Directive Parser -------------------------------------------------------- typedef struct LNK_Directive { @@ -55,15 +61,7 @@ typedef struct LNK_DirectiveInfo LNK_DirectiveList v[LNK_CmdSwitch_Count]; } LNK_DirectiveInfo; -//////////////////////////////// - -typedef struct LNK_SymbolInputResult -{ - LNK_SymbolList weak_symbols; - LNK_SymbolList undef_symbols; -} LNK_SymbolInputResult; - -//////////////////////////////// +// --- Workers Contexts -------------------------------------------------------- typedef struct { @@ -83,43 +81,39 @@ typedef struct typedef struct { - LNK_Obj **objs; - String8 name; - B32 collect_discarded; + LNK_Obj **objs; + String8 name; + B32 collect_discarded; String8List *out_lists; } LNK_SectionCollector; -//////////////////////////////// +// --- Error ------------------------------------------------------------------- internal void lnk_error_obj(LNK_ErrorCode code, LNK_Obj *obj, char *fmt, ...); -//////////////////////////////// +// --- Input ------------------------------------------------------------------- -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_ObjNodeArray lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *tp_arena, LNK_ObjList *obj_list, COFF_MachineType machine, U64 input_count, LNK_InputObj **inputs); +internal LNK_Obj ** lnk_array_from_obj_list(Arena *arena, LNK_ObjList list); +internal LNK_ObjNodeArray lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *tp_arena, LNK_ObjList *obj_list, COFF_MachineType machine, U64 input_count, LNK_InputObj **inputs); +internal LNK_SymbolInputResult lnk_input_obj_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, LNK_ObjNodeArray objs); -internal LNK_Obj ** lnk_obj_arr_from_list(Arena *arena, LNK_ObjList list); - -//////////////////////////////// +// --- Metadata ---------------------------------------------------------------- internal U32 lnk_obj_get_features(LNK_Obj *obj); internal U32 lnk_obj_get_comp_id(LNK_Obj *obj); internal U32 lnk_obj_get_vol_md(LNK_Obj *obj); -internal COFF_ParsedSymbol lnk_parsed_symbol_from_coff(LNK_Obj *obj, void *coff_symbol); -internal COFF_ParsedSymbol lnk_parsed_symbol_from_coff_symbol_idx(LNK_Obj *obj, U64 symbol_idx); +// --- Symbol & Section Helpers ------------------------------------------------ + +internal COFF_ParsedSymbol lnk_parsed_symbol_from_coff(LNK_Obj *obj, void *coff_symbol); +internal COFF_ParsedSymbol lnk_parsed_symbol_from_coff_symbol_idx(LNK_Obj *obj, U64 symbol_idx); internal COFF_SectionHeader * lnk_coff_section_header_from_section_number(LNK_Obj *obj, U64 section_number); -//////////////////////////////// +// --- Helpers ----------------------------------------------------------------- internal String8List * lnk_collect_obj_sections(TP_Context *tp, TP_Arena *arena, U64 objs_count, LNK_Obj **objs, String8 name, B32 collect_discarded); -//////////////////////////////// +// --- Directive Parser -------------------------------------------------------- internal void lnk_parse_msvc_linker_directive(Arena *arena, LNK_Obj *obj, LNK_DirectiveInfo *directive_info, String8 buffer); -//////////////////////////////// - -internal LNK_SymbolList lnk_run_symbol_collector(TP_Context *tp, TP_Arena *arena, LNK_ObjNodeArray arr, LNK_SymbolType symbol_type); -