diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 16c81df0..8987158e 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -258,6 +258,7 @@ lnk_make_linker_manifest(Arena *arena, "\n")); if (manifest_uac) { +#if 1 String8 uac = push_str8f(scratch.arena, " \n" " \n" @@ -268,6 +269,17 @@ lnk_make_linker_manifest(Arena *arena, " \n", manifest_level, manifest_ui_access); +#else + String8 uac = push_str8f(scratch.arena, + "\n" + "" + "" + "" + "" + "" + "" + "", manifest_level, manifest_ui_access); +#endif str8_serial_push_string(scratch.arena, &srl, uac); } for (String8Node *node = manifest_dependency_list.first; node != 0; node = node->next) { @@ -448,8 +460,8 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE PE_Resource *res = &stack->res_arr[stack->arr_idx].v[stack->res_idx[stack->arr_idx]]; ++stack->res_idx[stack->arr_idx]; - String8 flag_name = push_str8f(symtab->arena, "flag_%u", total_res_count); - String8 offset_name = push_str8f(symtab->arena, "offset_%u", total_res_count); + String8 flag_name = push_str8f(symtab->arena->v[0], "flag_%u", total_res_count); + String8 offset_name = push_str8f(symtab->arena->v[0], "offset_%u", total_res_count); ++total_res_count; if (stack->coff_entry_array_chunk) { @@ -471,7 +483,7 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE // make chunk and symbol String8 res_name = coff_resource_string_from_str8(dir_sect->arena, res->id.u.string); LNK_Chunk *name_chunk = lnk_section_push_chunk_data(dir_sect, dir_string_chunk, res_name, str8_zero()); - LNK_Symbol *name_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("COFF_RESOURCE_ID_STRING"), LNK_DefinedSymbolVisibility_Static, 0, name_chunk, 0, 0, 0); + LNK_Symbol *name_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], str8_lit("COFF_RESOURCE_ID_STRING"), LNK_DefinedSymbolVisibility_Static, 0, name_chunk, 0, 0, 0); // patch COFF_ResourceDirEntry.name.offset lnk_section_push_reloc(dir_sect, stack->coff_entry_chunk, LNK_Reloc_SECT_REL, OffsetOf(COFF_ResourceDirEntry, name.offset), name_symbol); @@ -503,8 +515,8 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE lnk_chunk_set_debugf(dir_sect->arena, entry_array_chunk, "DIR_ENTRY_ARRAY_CHUNK"); // push symbols to patch coff entry - LNK_Symbol *flag_symbol = lnk_make_defined_symbol_va(symtab->arena, flag_name, LNK_DefinedSymbolVisibility_Internal, 0, COFF_RESOURCE_SUB_DIR_FLAG); - LNK_Symbol *offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena, offset_name, LNK_DefinedSymbolVisibility_Internal, 0, dir_header_chunk, 0, 0, 0); + LNK_Symbol *flag_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], flag_name, LNK_DefinedSymbolVisibility_Internal, 0, COFF_RESOURCE_SUB_DIR_FLAG); + LNK_Symbol *offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], offset_name, LNK_DefinedSymbolVisibility_Internal, 0, dir_header_chunk, 0, 0, 0); lnk_symbol_table_push(symtab, flag_symbol); // set high bit to indicate directory lnk_symbol_table_push(symtab, offset_symbol); // write offset for this directory @@ -543,12 +555,12 @@ lnk_serialize_pe_resource_tree(LNK_SectionTable *st, LNK_SymbolTable *symtab, PE resource_data_chunk->align = COFF_RES_ALIGN; // relocate data - String8 resource_data_symbol_name = push_str8f(symtab->arena, "$R%06X", total_res_count); - LNK_Symbol *resource_data_symbol = lnk_make_defined_symbol_chunk(symtab->arena, resource_data_symbol_name, LNK_DefinedSymbolVisibility_Static, 0, resource_data_chunk, 0, 0, 0); + String8 resource_data_symbol_name = push_str8f(symtab->arena->v[0], "$R%06X", total_res_count); + LNK_Symbol *resource_data_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], resource_data_symbol_name, LNK_DefinedSymbolVisibility_Static, 0, resource_data_chunk, 0, 0, 0); lnk_section_push_reloc(dir_sect, coff_resource_data_entry_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(COFF_ResourceDataEntry, data_voff), resource_data_symbol); // push symbol for data offset relocation - LNK_Symbol *coff_data_offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena, offset_name, LNK_DefinedSymbolVisibility_Internal, 0, coff_resource_data_entry_chunk, 0, 0, 0); + LNK_Symbol *coff_data_offset_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], offset_name, LNK_DefinedSymbolVisibility_Internal, 0, coff_resource_data_entry_chunk, 0, 0, 0); lnk_symbol_table_push(symtab, coff_data_offset_symbol); Assert(stack->coff_entry_chunk); @@ -691,8 +703,13 @@ lnk_make_res_obj(TP_Context *tp, static const U64 sect_virt_align = 1; static const U64 sect_file_align = 1; + + TP_Arena *temp_tp_arena = push_array(scratch.arena, TP_Arena, 1); + temp_tp_arena->v = push_array(scratch.arena, Arena *, 1); + temp_tp_arena->count = 1; + temp_tp_arena->v[0] = arena_alloc(); - LNK_SymbolTable *symtab = lnk_symbol_table_alloc(); + LNK_SymbolTable *symtab = lnk_symbol_table_init(temp_tp_arena); LNK_SectionTable *st = lnk_section_table_alloc(0, sect_virt_align, sect_file_align); LNK_Section *header_sect = lnk_section_table_push(st, str8_lit(".null"), 0); @@ -703,9 +720,8 @@ lnk_make_res_obj(TP_Context *tp, // register section symbols (after this point don't push new sections) for (LNK_SectionNode *sect_node = st->list.first; sect_node != 0; sect_node = sect_node->next) { - LNK_Section *sect = §_node->data; - LNK_Symbol *sect_symbol = lnk_make_defined_symbol_chunk(symtab->arena, sect->name, LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); - lnk_symbol_table_push(symtab, sect_symbol); + LNK_Section *sect = §_node->data; + lnk_symbol_table_push_defined_chunk(symtab, sect->name, LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); } st->null_sect = lnk_section_list_remove(&st->list, str8_lit(".null")); lnk_section_table_build_data(tp, st, machine); @@ -826,10 +842,10 @@ lnk_make_res_obj(TP_Context *tp, } // emit symbols for coff section header patch - String8 coff_reloc_symbol_name = push_str8f(symtab->arena, "%S.coff_reloc[]", sect->name); - String8 coff_reloc_count_symbol_name = push_str8f(symtab->arena, "%S.coff_reloc[].count", sect->name); - LNK_Symbol *coff_reloc_symbol = lnk_make_defined_symbol_chunk(symtab->arena, coff_reloc_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, reloc_array_chunk, 0, 0, 0); - LNK_Symbol *coff_reloc_count_symbol = lnk_make_defined_symbol_va(symtab->arena, coff_reloc_count_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, coff_reloc_list.count); + String8 coff_reloc_symbol_name = push_str8f(symtab->arena->v[0], "%S.coff_reloc[]", sect->name); + String8 coff_reloc_count_symbol_name = push_str8f(symtab->arena->v[0], "%S.coff_reloc[].count", sect->name); + LNK_Symbol *coff_reloc_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], coff_reloc_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, reloc_array_chunk, 0, 0, 0); + LNK_Symbol *coff_reloc_count_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], coff_reloc_count_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, coff_reloc_list.count); lnk_symbol_table_push(symtab, coff_reloc_symbol); lnk_symbol_table_push(symtab, coff_reloc_count_symbol); } @@ -846,10 +862,10 @@ lnk_make_res_obj(TP_Context *tp, } String8 coff_symbol_table_data = str8_serial_end(scratch.arena, &srl); LNK_Chunk *coff_symbol_table_chunk = lnk_section_push_chunk_data(misc_sect, misc_sect->root, coff_symbol_table_data, str8_zero()); - LNK_Symbol *coff_symbol_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("COFF_SYMBOL_TABLE"), LNK_DefinedSymbolVisibility_Internal, 0, coff_symbol_table_chunk, 0, 0, 0); + LNK_Symbol *coff_symbol_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], str8_lit("COFF_SYMBOL_TABLE"), LNK_DefinedSymbolVisibility_Internal, 0, coff_symbol_table_chunk, 0, 0, 0); lnk_symbol_table_push(symtab, coff_symbol_table_symbol); - LNK_Symbol *coff_symbol_count_symbol = lnk_make_defined_symbol_va(symtab->arena, str8_lit("COFF_SYMBOL_COUNT"), LNK_DefinedSymbolVisibility_Internal, 0, coff_symbol_list.count); + LNK_Symbol *coff_symbol_count_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], str8_lit("COFF_SYMBOL_COUNT"), LNK_DefinedSymbolVisibility_Internal, 0, coff_symbol_list.count); lnk_symbol_table_push(symtab, coff_symbol_count_symbol); // build obj header @@ -874,7 +890,7 @@ lnk_make_res_obj(TP_Context *tp, lnk_section_push_reloc(header_sect, coff_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_Header, symbol_count), coff_symbol_count_symbol); // push coff header symbol - LNK_Symbol *coff_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_COFF_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, coff_header_chunk, 0, 0, 0); + LNK_Symbol *coff_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], str8_lit(LNK_COFF_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, coff_header_chunk, 0, 0, 0); lnk_symbol_table_push(symtab, coff_header_symbol); } @@ -882,7 +898,7 @@ lnk_make_res_obj(TP_Context *tp, { LNK_Chunk *coff_section_header_array_chunk = lnk_section_push_chunk_list(header_sect, header_sect->root, str8_zero()); for (LNK_SectionNode *sect_node = st->list.first; sect_node != 0; sect_node = sect_node->next) { - if (sect_node == st->null_sect) continue; + if (sect_node == st->null_sect) continue; if (!sect_node->data.emit_header) continue; LNK_Section *sect = §_node->data; @@ -924,7 +940,7 @@ lnk_make_res_obj(TP_Context *tp, // push section header count symbol U64 symbol_count = coff_section_header_array_chunk->u.list->count; - LNK_Symbol *coff_section_header_count_symbol = lnk_make_defined_symbol_va(symtab->arena, str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, symbol_count); + LNK_Symbol *coff_section_header_count_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, symbol_count); lnk_symbol_table_push(symtab, coff_section_header_count_symbol); } @@ -936,8 +952,8 @@ lnk_make_res_obj(TP_Context *tp, String8 res_obj = lnk_section_table_serialize(arena, st); lnk_section_table_release(&st); - lnk_symbol_table_release(&symtab); + arena_release(temp_tp_arena->v[0]); scratch_end(scratch); ProfEnd(); return res_obj; @@ -1012,9 +1028,13 @@ lnk_make_linker_coff_obj(TP_Context *tp, String8 obj_name) { Temp scratch = scratch_begin(&arena, 1); + + TP_Arena *temp_tp_arena = push_array(scratch.arena, TP_Arena, 1); + temp_tp_arena->v = &scratch.arena; + temp_tp_arena->count = 1; - LNK_SymbolTable *symtab = lnk_symbol_table_alloc(); - LNK_SectionTable *st = lnk_section_table_alloc(0, 1, 1); + LNK_SymbolTable *symtab = lnk_symbol_table_init(temp_tp_arena); + LNK_SectionTable *st = lnk_section_table_alloc(0, 1, 1); LNK_Section *header_sect = lnk_section_table_push(st, str8_lit(".coffhdr"), 0); LNK_Section *debug_s_sect = lnk_section_table_push(st, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS); @@ -1023,10 +1043,10 @@ lnk_make_linker_coff_obj(TP_Context *tp, header_sect->emit_header = 0; { - COFF_Header *coff_header = push_array(header_sect->arena, COFF_Header, 1); - coff_header->machine = machine; + COFF_Header *coff_header = push_array(header_sect->arena, COFF_Header, 1); + coff_header->machine = machine; coff_header->section_count = 0; - coff_header->time_stamp = time_stamp; + coff_header->time_stamp = time_stamp; LNK_Chunk *coff_header_chunk = lnk_section_push_chunk_raw(header_sect, header_sect->root, coff_header, sizeof(*coff_header), str8_zero()); lnk_section_push_reloc_undefined(header_sect, coff_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(COFF_Header, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); @@ -1045,13 +1065,13 @@ lnk_make_linker_coff_obj(TP_Context *tp, U64 ver_fe_major = 0; U64 ver_fe_minor = 0; U64 ver_fe_build = 0; - U64 ver_feqfe = 0; - U64 ver_major = 14; - U64 ver_minor = 36; - U64 ver_build = 32537; - U64 ver_qfe = 0; + U64 ver_feqfe = 0; + U64 ver_major = 14; + U64 ver_minor = 36; + U64 ver_build = 32537; + U64 ver_qfe = 0; String8 version_string = push_str8f(scratch.arena, "Epic Games Tools (R) RAD Linker"); - String8 comp3_data = cv_make_comp3(scratch.arena, 0, CV_Language_LINK, cv_arch, ver_fe_major, ver_fe_minor, ver_fe_build, ver_feqfe, ver_major, ver_minor, ver_build, ver_qfe, version_string); + String8 comp3_data = cv_make_comp3(scratch.arena, 0, CV_Language_LINK, cv_arch, ver_fe_major, ver_fe_minor, ver_fe_build, ver_feqfe, ver_major, ver_minor, ver_build, ver_qfe, version_string); cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data); // S_ENVBLOCK @@ -1091,13 +1111,12 @@ lnk_make_linker_coff_obj(TP_Context *tp, // register section symbols (after this point don't push new sections) for (LNK_SectionNode *sect_node = st->list.first; sect_node != NULL; sect_node = sect_node->next) { LNK_Section *sect = §_node->data; - LNK_Symbol *sect_symbol = lnk_make_defined_symbol_chunk(symtab->arena, sect->name, LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); - lnk_symbol_table_push(symtab, sect_symbol); + lnk_symbol_table_push_defined_chunk(symtab, sect->name, LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); } LNK_Chunk *coff_section_header_array_chunk = lnk_section_push_chunk_list(header_sect, header_sect->root, str8_zero()); for (LNK_SectionNode *sect_node = st->list.first; sect_node != NULL; sect_node = sect_node->next) { - if (sect_node == st->null_sect) continue; + if (sect_node == st->null_sect) continue; if (!sect_node->data.emit_header) continue; LNK_Section *sect = §_node->data; @@ -1138,7 +1157,7 @@ lnk_make_linker_coff_obj(TP_Context *tp, // push section header count symbol U64 symbol_count = coff_section_header_array_chunk->u.list->count; - LNK_Symbol *coff_section_header_count_symbol = lnk_make_defined_symbol_va(symtab->arena, str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, symbol_count); + LNK_Symbol *coff_section_header_count_symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, symbol_count); lnk_symbol_table_push(symtab, coff_section_header_count_symbol); } @@ -1228,21 +1247,6 @@ lnk_push_loaded_lib(Arena *arena, } } -internal -THREAD_POOL_TASK_FUNC(lnk_lazy_initer) -{ - LNK_LazyIniter *task = raw_task; - Rng1U64 range = task->range_arr[task_id]; - for (U64 lib_idx = range.min; lib_idx < range.max; lib_idx += 1) { - LNK_Lib *lib = &task->lib_arr[lib_idx].data; - String8Node *name_node = lib->symbol_name_list.first; - for (U64 symbol_idx = 0; symbol_idx < lib->symbol_count; symbol_idx += 1, name_node = name_node->next) { - LNK_Symbol *symbol = &task->symbol_arr_arr[lib_idx][symbol_idx]; - lnk_init_lazy_symbol(symbol, name_node->string, lib, lib->member_off_arr[symbol_idx]); - } - } -} - internal void lnk_push_input_from_lazy(Arena *arena, PathStyle path_style, LNK_LazySymbol *lazy, LNK_InputImportList *input_import_list, LNK_InputObjList *input_obj_list) { @@ -1298,40 +1302,26 @@ lnk_push_linker_symbols(LNK_SymbolTable *symtab, COFF_MachineType machine) // passing it around as a function argument. // // 100h: lea rax, [rip + ffffff00h] ; -100h - LNK_Symbol *image_base = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("__ImageBase"), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelectType_ANY, 0); - lnk_symbol_table_push(symtab, image_base); + LNK_Symbol *image_base = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("__ImageBase"), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelectType_ANY, 0); { // load config symbols if (machine == COFF_MachineType_X86) { - LNK_Symbol *safe_se_handler_table = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_SAFE_SE_HANDLER_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelectType_NODUPLICATES, 0); - LNK_Symbol *safe_se_handler_count = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_SAFE_SE_HANDLER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelectType_NODUPLICATES, 0); - lnk_symbol_table_push(symtab, safe_se_handler_table); - lnk_symbol_table_push(symtab, safe_se_handler_count); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_SAFE_SE_HANDLER_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelectType_NODUPLICATES, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_SAFE_SE_HANDLER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, g_null_chunk_ptr, 0, COFF_ComdatSelectType_NODUPLICATES, 0); } // TODO: investigate IMAGE_ENCLAVE_CONFIG 32/64 - LNK_Symbol *enclave_config = lnk_make_defined_symbol_va(symtab->arena, str8_lit(LNK_ENCLAVE_CONFIG_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, 0); + lnk_symbol_table_push_defined_va(symtab, str8_lit(LNK_ENCLAVE_CONFIG_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0, 0); - LNK_Symbol *guard_flags = lnk_make_defined_symbol(symtab->arena, str8_lit(LNK_GUARD_FLAGS_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); - LNK_Symbol *guard_fids_table = lnk_make_defined_symbol(symtab->arena, str8_lit(LNK_GUARD_FIDS_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); - LNK_Symbol *guard_fids_count = lnk_make_defined_symbol(symtab->arena, str8_lit(LNK_GUARD_FIDS_COUNT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); - LNK_Symbol *guard_iat_table = lnk_make_defined_symbol(symtab->arena, str8_lit(LNK_GUARD_IAT_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); - LNK_Symbol *guard_iat_count = lnk_make_defined_symbol(symtab->arena, str8_lit(LNK_GUARD_IAT_COUNT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); - LNK_Symbol *guard_longjmp_table = lnk_make_defined_symbol(symtab->arena, str8_lit(LNK_GUARD_LONGJMP_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0); - LNK_Symbol *guard_longjmp_count = lnk_make_defined_symbol(symtab->arena, str8_lit(LNK_GUARD_LONGJMP_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0); - LNK_Symbol *guard_ehcont_table = lnk_make_defined_symbol(symtab->arena, str8_lit(LNK_GUARD_EHCONT_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); - LNK_Symbol *guard_ehcont_count = lnk_make_defined_symbol(symtab->arena, str8_lit(LNK_GUARD_EHCONT_COUNT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); - - lnk_symbol_table_push(symtab, enclave_config); - lnk_symbol_table_push(symtab, guard_flags); - lnk_symbol_table_push(symtab, guard_fids_table); - lnk_symbol_table_push(symtab, guard_fids_count); - lnk_symbol_table_push(symtab, guard_iat_table); - lnk_symbol_table_push(symtab, guard_iat_count); - lnk_symbol_table_push(symtab, guard_longjmp_table); - lnk_symbol_table_push(symtab, guard_longjmp_count); - lnk_symbol_table_push(symtab, guard_ehcont_table); - lnk_symbol_table_push(symtab, guard_ehcont_count); + lnk_symbol_table_push_defined(symtab, str8_lit(LNK_GUARD_FLAGS_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); + lnk_symbol_table_push_defined(symtab, str8_lit(LNK_GUARD_FIDS_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); + lnk_symbol_table_push_defined(symtab, str8_lit(LNK_GUARD_FIDS_COUNT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); + lnk_symbol_table_push_defined(symtab, str8_lit(LNK_GUARD_IAT_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); + lnk_symbol_table_push_defined(symtab, str8_lit(LNK_GUARD_IAT_COUNT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); + lnk_symbol_table_push_defined(symtab, str8_lit(LNK_GUARD_LONGJMP_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0); + lnk_symbol_table_push_defined(symtab, str8_lit(LNK_GUARD_LONGJMP_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Extern, 0); + lnk_symbol_table_push_defined(symtab, str8_lit(LNK_GUARD_EHCONT_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); + lnk_symbol_table_push_defined(symtab, str8_lit(LNK_GUARD_EHCONT_COUNT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Extern, 0); } } @@ -1422,11 +1412,8 @@ lnk_build_debug_pdb(LNK_SectionTable *st, lnk_chunk_set_debugf(sect->arena, debug_pdb_chunk, LNK_CV_HEADER_PDB70_SYMBOL_NAME); // push symbols - LNK_Symbol *debug_pdb_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_CV_HEADER_PDB70_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_pdb_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, debug_pdb_symbol); - - LNK_Symbol *guid_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_CV_HEADER_GUID_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_pdb_chunk, OffsetOf(PE_CvHeaderPDB70, guid), 0, 0); - lnk_symbol_table_push(symtab, guid_symbol); + LNK_Symbol *debug_pdb_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_CV_HEADER_PDB70_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_pdb_chunk, 0, 0, 0); + LNK_Symbol *guid_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_CV_HEADER_GUID_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_pdb_chunk, OffsetOf(PE_CvHeaderPDB70, guid), 0, 0); // push debug directory lnk_push_pe_debug_data_directory(sect, dir_array_chunk, debug_pdb_symbol, PE_DebugDirectoryType_CODEVIEW, time_stamp); @@ -1452,11 +1439,8 @@ lnk_build_debug_rdi(LNK_SectionTable *st, LNK_Chunk *debug_rdi_chunk = lnk_section_push_chunk_data(rdi_sect, rdi_sect->root, debug_rdi, str8_zero()); lnk_chunk_set_debugf(rdi_sect->arena, debug_rdi, LNK_CV_HEADER_RDI_SYMBOL_NAME); // push symbols - LNK_Symbol *debug_rdi_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_CV_HEADER_RDI_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_rdi_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, debug_rdi_symbol); - - LNK_Symbol *guid_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_CV_HEADER_GUID_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_rdi_chunk, OffsetOf(PE_CvHeaderRDI, guid), 0, 0); - lnk_symbol_table_push(symtab, guid_symbol); + LNK_Symbol *debug_rdi_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_CV_HEADER_RDI_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_rdi_chunk, 0, 0, 0); + LNK_Symbol *guid_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_CV_HEADER_GUID_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_rdi_chunk, OffsetOf(PE_CvHeaderRDI, guid), 0, 0); // push debug directory lnk_push_pe_debug_data_directory(debug_sect, debug_dir_array_chunk, debug_rdi_symbol, PE_DebugDirectoryType_CODEVIEW, time_stamp); @@ -1566,6 +1550,8 @@ lnk_build_guard_tables(TP_Context *tp, // TODO: push noname exports + NotImplemented; +#if 0 // push thunks LNK_SymbolScopeIndex scope_array[] = { LNK_SymbolScopeIndex_Defined, LNK_SymbolScopeIndex_Internal }; for (U64 iscope = 0; iscope < ArrayCount(scope_array); ++iscope) { @@ -1582,6 +1568,7 @@ lnk_build_guard_tables(TP_Context *tp, } } } +#endif // build section data lnk_section_table_build_data(tp, st, machine); @@ -1628,8 +1615,7 @@ lnk_build_guard_tables(TP_Context *tp, }; for (U64 i = 0; i < ArrayCount(sect_layout); ++i) { LNK_Section *sect = lnk_section_table_push(st, str8_cstring(sect_layout[i].name), sect_layout[i].flags); - LNK_Symbol *symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(sect_layout[i].symbol), LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); - lnk_symbol_table_push(symtab, symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(sect_layout[i].symbol), LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); } // TODO: emit table for SEH on X86 @@ -1768,6 +1754,13 @@ lnk_emit_base_reloc_info(Arena *arena, if (is_addr) { U64 reloc_voff = lnk_virt_off_from_reloc(sect_id_map, reloc); U64 page_voff = AlignDownPow2(reloc_voff, page_size); + + if (str8_match(reloc->symbol->name, str8_lit("_mi_heap_empty"), 0)) { + int x = 0; + } + if (page_voff == 0x21C7000) { + int x = 0; + } LNK_BaseRelocPageNode *page; { @@ -1945,8 +1938,7 @@ lnk_build_base_relocs(TP_Context *tp, if (main_page_list->count > 0) { LNK_Section *base_reloc_sect = lnk_section_table_push(st, str8_lit(".reloc"), LNK_RELOC_SECTION_FLAGS); - LNK_Symbol *base_reloc_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_BASE_RELOC_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, base_reloc_sect->root, 0, 0, 0); - lnk_symbol_table_push(symtab, base_reloc_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_BASE_RELOC_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, base_reloc_sect->root, 0, 0, 0); ProfBegin("Page List -> Array"); LNK_BaseRelocPageArray page_arr = lnk_base_reloc_page_array_from_list(base_reloc_sect->arena, *main_page_list); @@ -2046,10 +2038,8 @@ lnk_build_dos_header(LNK_SymbolTable *symtab, LNK_Section *header_sect, LNK_Chun lnk_chunk_set_debugf(header_sect->arena, dos_header_chunk, LNK_DOS_HEADER_SYMBOL_NAME); lnk_chunk_set_debugf(header_sect->arena, dos_program_chunk, LNK_DOS_PROGRAM_SYMBOL_NAME); - LNK_Symbol *dos_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_DOS_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, dos_header_chunk, 0, 0, 0); - LNK_Symbol *dos_program_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_DOS_PROGRAM_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, dos_program_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, dos_header_symbol); - lnk_symbol_table_push(symtab, dos_program_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_DOS_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, dos_header_chunk, 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_DOS_PROGRAM_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, dos_program_chunk, 0, 0, 0); // :coff_file_offset lnk_section_push_reloc_undefined(header_sect, dos_header_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(PE_DosHeader, coff_file_offset), str8_lit(LNK_NT_HEADERS_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); @@ -2066,8 +2056,7 @@ lnk_build_pe_magic(LNK_SymbolTable *symtab, LNK_Section *header_sect, LNK_Chunk LNK_Chunk *pe_magic_chunk = lnk_section_push_chunk_raw(header_sect, parent, pe_magic, sizeof(*pe_magic), str8_zero()); lnk_chunk_set_debugf(header_sect->arena, pe_magic_chunk, LNK_PE_MAGIC_SYMBOL_NAME); - LNK_Symbol *pe_magic_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_PE_MAGIC_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, pe_magic_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, pe_magic_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_PE_MAGIC_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, pe_magic_chunk, 0, 0, 0); return pe_magic_chunk; } @@ -2088,8 +2077,7 @@ lnk_build_coff_file_header(LNK_SymbolTable *symtab, LNK_Section *header_sect, LN LNK_Chunk *file_header_chunk = lnk_section_push_chunk_raw(header_sect, parent, file_header, sizeof(*file_header), str8_zero()); lnk_chunk_set_debugf(header_sect->arena, file_header_chunk, LNK_COFF_HEADER_SYMBOL_NAME); - LNK_Symbol *file_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_COFF_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, file_header_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, file_header_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_COFF_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, file_header_chunk, 0, 0, 0); // :section_count lnk_section_push_reloc_undefined(header_sect, file_header_chunk, LNK_Reloc_ADDR_16, OffsetOf(COFF_Header, section_count), str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); @@ -2158,8 +2146,7 @@ lnk_build_pe_optional_header_x64(LNK_SymbolTable *symtab, lnk_chunk_set_debugf(header_sect->arena, opt_header_chunk, LNK_PE_OPT_HEADER_SYMBOL_NAME); // define optional header symbol - LNK_Symbol *opt_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_PE_OPT_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, opt_header_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, opt_header_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_PE_OPT_HEADER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, opt_header_chunk, 0, 0, 0); // :entry_point_va lnk_section_push_reloc_undefined(header_sect, opt_header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_OptionalHeader32Plus, entry_point_va), entry_point_name, LNK_SymbolScopeFlag_Main); @@ -2202,8 +2189,7 @@ lnk_build_pe_optional_header_x64(LNK_SymbolTable *symtab, lnk_section_push_reloc(header_sect, opt_header_chunk, LNK_Reloc_FILE_ALIGN_32, OffsetOf(PE_OptionalHeader32Plus, sizeof_headers), &g_null_symbol); // :check_sum - LNK_Symbol *checksum_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_PE_CHECKSUM_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, opt_header_chunk, OffsetOf(PE_OptionalHeader32Plus, check_sum), COFF_ComdatSelectType_NODUPLICATES, 0); - lnk_symbol_table_push(symtab, checksum_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_PE_CHECKSUM_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, opt_header_chunk, OffsetOf(PE_OptionalHeader32Plus, check_sum), COFF_ComdatSelectType_NODUPLICATES, 0); // :data_dir_count lnk_section_push_reloc_undefined(header_sect, opt_header_chunk, LNK_Reloc_ADDR_32, OffsetOf(PE_OptionalHeader32Plus, data_dir_count), str8_lit(LNK_PE_DIRECTORY_COUNT_SYMBOL_NAME), LNK_SymbolScopeFlag_Internal); @@ -2215,18 +2201,18 @@ internal LNK_Chunk * lnk_build_pe_directories(LNK_SymbolTable *symtab, LNK_Section *header_sect, LNK_Chunk *parent) { static struct { - char *name; - PE_DataDirectoryIndex index; - LNK_SymbolScopeFlags scope; + char *name; + PE_DataDirectoryIndex index; + LNK_SymbolScopeFlags scope; } directory_map[] = { - { LNK_LOAD_CONFIG_SYMBOL_NAME , PE_DataDirectoryIndex_LOAD_CONFIG , LNK_SymbolScopeFlag_Main }, + { LNK_LOAD_CONFIG_SYMBOL_NAME , PE_DataDirectoryIndex_LOAD_CONFIG , LNK_SymbolScopeFlag_Main }, { LNK_PDATA_SYMBOL_NAME , PE_DataDirectoryIndex_EXCEPTIONS , LNK_SymbolScopeFlag_Internal }, { LNK_EDATA_SYMBOL_NAME , PE_DataDirectoryIndex_EXPORT , LNK_SymbolScopeFlag_Internal }, { LNK_BASE_RELOC_SYMBOL_NAME , PE_DataDirectoryIndex_BASE_RELOC , LNK_SymbolScopeFlag_Internal }, { LNK_IMPORT_DLL_TABLE_SYMBOL_NAME , PE_DataDirectoryIndex_IMPORT , LNK_SymbolScopeFlag_Internal }, { LNK_IMPORT_IAT_SYMBOL_NAME , PE_DataDirectoryIndex_IMPORT_ADDR , LNK_SymbolScopeFlag_Internal }, { LNK_DELAYED_IMPORT_DLL_TABLE_SYMBOL_NAME, PE_DataDirectoryIndex_DELAY_IMPORT, LNK_SymbolScopeFlag_Internal }, - { LNK_TLS_SYMBOL_NAME , PE_DataDirectoryIndex_TLS , LNK_SymbolScopeFlag_Main }, + { LNK_TLS_SYMBOL_NAME , PE_DataDirectoryIndex_TLS , LNK_SymbolScopeFlag_Main }, { LNK_DEBUG_DIR_SYMBOL_NAME , PE_DataDirectoryIndex_DEBUG , LNK_SymbolScopeFlag_Internal }, { LNK_RSRC_SYMBOL_NAME , PE_DataDirectoryIndex_RESOURCES , LNK_SymbolScopeFlag_Internal }, }; @@ -2239,10 +2225,8 @@ lnk_build_pe_directories(LNK_SymbolTable *symtab, LNK_Section *header_sect, LNK_ lnk_chunk_set_debugf(header_sect->arena, directory_array_chunk, LNK_PE_DIRECTORY_ARRAY_SYMBOL_NAME); // define PE directory symbols - LNK_Symbol *directory_array_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_PE_DIRECTORY_ARRAY_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, directory_array_chunk, 0, 0, 0); - LNK_Symbol *directory_count_symbol = lnk_make_defined_symbol_va(symtab->arena, str8_lit(LNK_PE_DIRECTORY_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, directory_count); - lnk_symbol_table_push(symtab, directory_array_symbol); - lnk_symbol_table_push(symtab, directory_count_symbol); + LNK_Symbol *directory_array_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_PE_DIRECTORY_ARRAY_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, directory_array_chunk, 0, 0, 0); + LNK_Symbol *directory_count_symbol = lnk_symbol_table_push_defined_va(symtab, str8_lit(LNK_PE_DIRECTORY_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, directory_count); for (U64 dir_idx = 0; dir_idx < ArrayCount(directory_map); dir_idx += 1) { String8 symbol_name = str8_cstring(directory_map[dir_idx].name); @@ -2270,9 +2254,8 @@ lnk_build_coff_section_table(LNK_SymbolTable *symtab, LNK_Section *header_sect, Assert(!test_symbol); (void)test_symbol; // define symbol - String8 sect_symbol_name = push_str8_copy(symtab->arena, sect->name); - LNK_Symbol *sect_symbol = lnk_make_defined_symbol_chunk(symtab->arena, sect_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); - lnk_symbol_table_push(symtab, sect_symbol); + String8 sect_symbol_name = push_str8_copy(symtab->arena->v[0], sect->name); + lnk_symbol_table_push_defined_chunk(symtab, sect_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); } // push COFF header array chunk @@ -2280,8 +2263,7 @@ lnk_build_coff_section_table(LNK_SymbolTable *symtab, LNK_Section *header_sect, lnk_chunk_set_debugf(header_sect->arena, coff_header_array_chunk, LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME); // define symbol for COFF header array - LNK_Symbol *coff_header_array_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, coff_header_array_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, coff_header_array_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, coff_header_array_chunk, 0, 0, 0); // push headers for (LNK_Section *sect = §_arr.v[0], *sect_opl = sect + sect_arr.count; sect < sect_opl; sect += 1) { @@ -2331,8 +2313,7 @@ lnk_build_coff_section_table(LNK_SymbolTable *symtab, LNK_Section *header_sect, // push symbol for section header count U64 header_count = coff_header_array_chunk->u.list->count; - LNK_Symbol *header_symbol = lnk_make_defined_symbol_va(symtab->arena, str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, header_count); - lnk_symbol_table_push(symtab, header_symbol); + lnk_symbol_table_push_defined_va(symtab, str8_lit(LNK_COFF_SECT_HEADER_COUNT_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, header_count); return coff_header_array_chunk; } @@ -2365,21 +2346,13 @@ lnk_build_win32_image_header(LNK_SymbolTable *symtab, lnk_chunk_set_debugf(header_sect->arena, pe_optional_chunk , "PE Optional Header Container" ); lnk_chunk_set_debugf(header_sect->arena, coff_sect_header_chunk, "COFF Section Headers Container"); - LNK_Symbol *win32_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_WIN32_HEADER_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, win32_header_chunk , 0, 0, 0); - LNK_Symbol *dos_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_DOS_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, dos_chunk , 0, 0, 0); - LNK_Symbol *nt_headers_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_NT_HEADERS_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, nt_chunk , 0, 0, 0); - LNK_Symbol *pe_magic_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_PE_MAGIC_CONTAINER_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, pe_magic_chunk , 0, 0, 0); - LNK_Symbol *coff_file_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_COFF_FILE_HEADER_CONTAINER_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, coff_file_header_chunk, 0, 0, 0); - LNK_Symbol *pe_optional_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_PE_OPT_HEADER_CONTAINER_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, pe_optional_chunk , 0, 0, 0); - LNK_Symbol *coff_sect_header_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_COFF_SECTION_HEADER_CONTAINER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, coff_sect_header_chunk, 0, 0, 0); - - lnk_symbol_table_push(symtab, win32_header_symbol ); - lnk_symbol_table_push(symtab, dos_symbol ); - lnk_symbol_table_push(symtab, nt_headers_symbol ); - lnk_symbol_table_push(symtab, pe_magic_symbol ); - lnk_symbol_table_push(symtab, coff_file_header_symbol); - lnk_symbol_table_push(symtab, pe_optional_symbol ); - lnk_symbol_table_push(symtab, coff_sect_header_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_WIN32_HEADER_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, win32_header_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_DOS_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, dos_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_NT_HEADERS_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, nt_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_PE_MAGIC_CONTAINER_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, pe_magic_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_COFF_FILE_HEADER_CONTAINER_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, coff_file_header_chunk, 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_PE_OPT_HEADER_CONTAINER_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, pe_optional_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_COFF_SECTION_HEADER_CONTAINER_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, coff_sect_header_chunk, 0, 0, 0); lnk_build_dos_header(symtab, header_sect, dos_chunk); lnk_build_pe_magic(symtab, header_sect, pe_magic_chunk); @@ -2432,15 +2405,15 @@ THREAD_POOL_TASK_FUNC(lnk_undef_symbol_finder) Assert(symbol->type == LNK_Symbol_Undefined); LNK_UndefinedSymbol *undef = &symbol->u.undefined; - LNK_SymbolNode *has_defn = lnk_symbol_table_search_node(task->symtab, undef->scope_flags, symbol->name); + LNK_Symbol *has_defn = lnk_symbol_table_search(task->symtab, undef->scope_flags, symbol->name); if (has_defn) { - Assert(LNK_Symbol_IsDefined(has_defn->data->type) || has_defn->data->type == LNK_Symbol_Weak); + Assert(LNK_Symbol_IsDefined(has_defn->type) || has_defn->type == LNK_Symbol_Weak); continue; } - LNK_SymbolNode *lazy = lnk_symbol_table_search_node(task->symtab, LNK_SymbolScopeFlag_Lib, symbol->name); + LNK_Symbol *lazy = lnk_symbol_table_search(task->symtab, LNK_SymbolScopeFlag_Lib, symbol->name); if (lazy) { - lnk_push_input_from_lazy(arena, task->path_style, &lazy->data->u.lazy, &result->input_import_list, &result->input_obj_list); + lnk_push_input_from_lazy(arena, task->path_style, &lazy->u.lazy, &result->input_import_list, &result->input_obj_list); } else { lnk_symbol_list_push_node(&result->unresolved_symbol_list, symbol_node); } @@ -2461,22 +2434,22 @@ THREAD_POOL_TASK_FUNC(lnk_weak_symbol_finder) LNK_WeakSymbol *weak = &symbol->u.weak; Assert((weak->scope_flags & ~(LNK_SymbolScopeFlag_Defined | LNK_SymbolScopeFlag_Internal)) == 0); - LNK_SymbolNode *has_strong_defn = lnk_symbol_table_search_node(task->symtab, weak->scope_flags, symbol->name); + LNK_Symbol *has_strong_defn = lnk_symbol_table_search(task->symtab, weak->scope_flags, symbol->name); if (has_strong_defn) { - Assert(LNK_Symbol_IsDefined(has_strong_defn->data->type)); + Assert(LNK_Symbol_IsDefined(has_strong_defn->type)); continue; } - LNK_SymbolNode *lazy = 0; + LNK_Symbol *lazy = 0; switch (weak->lookup_type) { case COFF_WeakExtType_NOLIBRARY: { // NOLIBRARY means weak symbol should be resolved in case where strong definition pulls in lib member. } break; case COFF_WeakExtType_SEARCH_LIBRARY: { - lazy = lnk_symbol_table_search_node(task->symtab, LNK_SymbolScopeFlag_Lib, symbol->name); + lazy = lnk_symbol_table_search(task->symtab, LNK_SymbolScopeFlag_Lib, symbol->name); } break; case COFF_WeakExtType_SEARCH_ALIAS: { - lazy = lnk_symbol_table_search_node(task->symtab, LNK_SymbolScopeFlag_Lib, symbol->name); + lazy = lnk_symbol_table_search(task->symtab, LNK_SymbolScopeFlag_Lib, symbol->name); if (!lazy) { if (str8_match(str8_lit(".weak."), symbol->name, StringMatchFlag_RightSideSloppy)) { // TODO: Clang and MingGW encode extra info in alias @@ -2495,14 +2468,14 @@ THREAD_POOL_TASK_FUNC(lnk_weak_symbol_finder) // In this case linker needs to parse .weak.bar.default.foo and search for bar and foo as well. Assert("TODO: MinGW weak symbol"); } else { - lazy = lnk_symbol_table_search_node(task->symtab, LNK_SymbolScopeFlag_Lib, weak->fallback_symbol->name); + lazy = lnk_symbol_table_search(task->symtab, LNK_SymbolScopeFlag_Lib, weak->fallback_symbol->name); } } } break; } if (lazy) { - lnk_push_input_from_lazy(arena, task->path_style, &lazy->data->u.lazy, &result->input_import_list, &result->input_obj_list); + lnk_push_input_from_lazy(arena, task->path_style, &lazy->u.lazy, &result->input_import_list, &result->input_obj_list); } else { lnk_symbol_list_push_node(&result->unresolved_symbol_list, symbol_node); } @@ -2564,26 +2537,66 @@ lnk_run_symbol_finder(TP_Context *tp, } internal -THREAD_POOL_TASK_FUNC(lnk_defined_symbol_inserter) +THREAD_POOL_TASK_FUNC(lnk_defined_symbol_pusher_task) { - LNK_DefinedSymbolInserter *task = raw_task; - LNK_SymbolTable *symtab = task->symtab; - Rng1U64 range = task->range_arr[task_id]; - for (U64 bucket_idx = range.min; bucket_idx < range.max; bucket_idx += 1) { - LNK_SymbolList *bucket = &task->bucket_arr[bucket_idx]; - for (LNK_SymbolNode *curr = bucket->first, *next; curr != 0; curr = next) { - next = curr->next; - LNK_SymbolNode *extant_node = lnk_symbol_table_search_bucket(symtab, LNK_SymbolScopeIndex_Defined, bucket_idx, curr->data->name, curr->hash); - if (extant_node) { - LNK_SymbolList *symtab_bucket = lnk_symbol_table_bucket_from_hash(symtab, LNK_SymbolScopeIndex_Defined, curr->hash); - lnk_symbol_list_insert_after(symtab_bucket, extant_node, curr); - } else { - lnk_symbol_table_push_(symtab, LNK_SymbolScopeIndex_Defined, curr, curr->hash); - } + LNK_SymbolPusher *task = raw_task; + LNK_SymbolTable *symtab = task->symtab; + LNK_Obj *obj = &task->u.objs.v[task_id].data; + + LNK_SymbolHashTrieChunkList **chunk_lists = symtab->chunk_lists; + + for (LNK_SymbolNode *symnode = obj->symbol_list.first; symnode != 0; symnode = symnode->next) { + if (symnode->data->type == LNK_Symbol_DefinedExtern) { + U64 hash = lnk_symbol_hash(symnode->data->name); + lnk_symbol_table_push_(symtab, arena, &chunk_lists[LNK_SymbolScopeIndex_Defined][worker_id], LNK_SymbolScopeIndex_Defined, hash, symnode->data); + } else if (symnode->data->type == LNK_Symbol_Weak) { + U64 hash = lnk_symbol_hash(symnode->data->name); + lnk_symbol_table_push_(symtab, arena, &chunk_lists[LNK_SymbolScopeIndex_Weak][worker_id], LNK_SymbolScopeIndex_Weak, hash, symnode->data); } } } +internal void +lnk_push_defined_symbols(TP_Context *tp, LNK_SymbolTable *symtab, LNK_ObjNodeArray objs) +{ + ProfBeginFunction(); + LNK_SymbolPusher task = {0}; + task.symtab = symtab; + task.u.objs = objs; + tp_for_parallel(tp, symtab->arena, objs.count, lnk_defined_symbol_pusher_task, &task); + ProfEnd(); +} + +internal +THREAD_POOL_TASK_FUNC(lnk_lazy_symbol_pusher_task) +{ + LNK_SymbolPusher *task = raw_task; + LNK_SymbolTable *symtab = task->symtab; + LNK_Lib *lib = &task->u.libs.v[task_id].data; + String8Node *name_node = lib->symbol_name_list.first; + + LNK_Symbol *lazy_symbols = push_array_no_zero(arena, LNK_Symbol, lib->symbol_count); + + for (U64 symbol_idx = 0; symbol_idx < lib->symbol_count; ++symbol_idx, name_node = name_node->next) { + LNK_Symbol *symbol = &lazy_symbols[symbol_idx]; + lnk_init_lazy_symbol(symbol, name_node->string, lib, lib->member_off_arr[symbol_idx]); + + U64 hash = lnk_symbol_hash(symbol->name); + lnk_symbol_table_push_(symtab, arena, &symtab->chunk_lists[LNK_SymbolScopeIndex_Lib][worker_id], LNK_SymbolScopeIndex_Lib, hash, symbol); + } +} + +internal void +lnk_push_lazy_symbols(TP_Context *tp, LNK_SymbolTable *symtab, LNK_LibNodeArray libs) +{ + ProfBeginFunction(); + LNK_SymbolPusher task = {0}; + task.symtab = symtab; + task.u.libs = libs; + tp_for_parallel(tp, symtab->arena, libs.count, lnk_lazy_symbol_pusher_task, &task); + ProfEnd(); +} + //////////////////////////////// internal void @@ -2872,6 +2885,7 @@ lnk_init_section_table(LNK_SymbolTable *symtab, U64 section_virt_off, U64 sect_a { ".edata", LNK_EDATA_SYMBOL_NAME, LNK_EDATA_SECTION_FLAGS }, { ".rsrc", LNK_RSRC_SYMBOL_NAME, LNK_RSRC_SECTION_FLAGS }, { ".debug", LNK_DEBUG_SYMBOL_NAME, LNK_DEBUG_SECTION_FLAGS }, + { ".tls", LNK_TLS_SYMBOL_NAME, LNK_TLS_SECTION_FLAGS }, }; LNK_SectionTable *st = lnk_section_table_alloc(section_virt_off, sect_align, file_align); @@ -2880,8 +2894,7 @@ lnk_init_section_table(LNK_SymbolTable *symtab, U64 section_virt_off, U64 sect_a sect->symbol_name = str8_cstring(sect_layout[i].symbol); sect->symbol_name = push_str8_copy(sect->arena, sect->symbol_name); - LNK_Symbol *symbol = lnk_make_defined_symbol_chunk(symtab->arena, sect->symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); - lnk_symbol_table_push(symtab, symbol); + lnk_symbol_table_push_defined_chunk(symtab, sect->symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, sect->root, 0, 0, 0); } st->null_sect = lnk_section_list_remove(&st->list, str8_lit(".null")); @@ -2903,6 +2916,7 @@ lnk_init_merge_directive_list(Arena *arena, LNK_ObjList obj_list) LNK_MergeDirectiveList result = {0}; lnk_merge_directive_list_push(arena, &result, (LNK_MergeDirective){ str8_lit_comp(".xdata") , str8_lit_comp(".rdata") }); + //lnk_merge_directive_list_push(arena, &result, (LNK_MergeDirective){ str8_lit_comp(".tls"), str8_lit_comp(".data") }); // collect merge directives from objs for (LNK_ObjNode *obj_node = obj_list.first; obj_node != 0; obj_node = obj_node->next) { @@ -3130,6 +3144,15 @@ lnk_blake3_hash_parallel(TP_Context *tp, U64 chunk_count, String8 data) return result; } +LNK_CHUNK_VISITOR_SIG(lnk_max_tls_align) +{ + if (chunk->type == LNK_Chunk_Leaf) { + U64 *max_align = ud; + *max_align = Max(*max_align, chunk->align); + } + return 0; +} + internal void lnk_run(int argc, char **argv) { @@ -3150,7 +3173,6 @@ lnk_run(int argc, char **argv) State_SearchEntryPoint, State_CheckUnusedDelayLoads, State_ReportUnresolvedSymbols, - State_RewireComdats, State_DiscardMetaDataSections, State_BuildDebugDirectory, State_BuildExportTable, @@ -3207,7 +3229,6 @@ l.count += 1; \ LNK_InputLibList input_libs[LNK_InputSource_Count] = {0}; LNK_InputObjList input_obj_list = {0}; LNK_InputImportList input_import_list = {0}; - LNK_SymbolList input_defn_list = {0}; LNK_SymbolList input_weak_list = {0}; // :null_obj @@ -3222,7 +3243,7 @@ l.count += 1; \ input_libs[LNK_InputSource_Default] = config->input_default_lib_list; // state - LNK_SymbolTable *symtab = lnk_symbol_table_alloc_ex(config->symbol_table_cap_defined, config->symbol_table_cap_internal, config->symbol_table_cap_weak, config->symbol_table_cap_lib); + LNK_SymbolTable *symtab = lnk_symbol_table_init(tp_arena); LNK_SectionTable *st = lnk_init_section_table(symtab, config->section_virt_off, config->sect_align, config->file_align); LNK_ImportTable *imptab_static = 0; LNK_ImportTable *imptab_delayed = 0; @@ -3249,11 +3270,10 @@ l.count += 1; \ B32 build_base_relocs = !(config->flags & LNK_ConfigFlag_Fixed); B32 report_unresolved_symbols = 1; B32 check_unused_delay_loads = !!(config->flags & LNK_ConfigFlag_CheckUnusedDelayLoadDll); - B32 do_comdat_rewire = 1; B32 build_win32_header = 1; B32 patch_relocs = 1; B32 sort_exception_info = 1; - B32 build_imp_lib = config->build_imp_lib; + B32 build_imp_lib = 1; //config->build_imp_lib; LNK_ObjList obj_list = {0}; LNK_LibList lib_index[LNK_InputSource_Count] = {0}; String8 image_data = str8_zero(); @@ -3332,8 +3352,8 @@ l.count += 1; \ if (entry_point_symbol) { lnk_error(LNK_Error_EntryPoint, "multiple entry point symbols found: %S(%S) and %S(%S)", - entry_point_symbol->name, entry_point_symbol->debug, - symbol->name, symbol->debug); + entry_point_symbol->name, entry_point_symbol->obj->path, + symbol->name, symbol->obj->path); } else { entry_point_symbol = symbol; } @@ -3432,8 +3452,8 @@ l.count += 1; \ ProfBegin("Push /INCLUDE Symbols"); for (String8Node *include_node = include_symbol_list.first; include_node != 0; include_node = include_node->next) { - String8 name = push_str8_copy(symtab->arena, include_node->string); - LNK_Symbol *symbol = lnk_make_undefined_symbol(symtab->arena, name, LNK_SymbolScopeFlag_Main); + String8 name = push_str8_copy(symtab->arena->v[0], include_node->string); + LNK_Symbol *symbol = lnk_make_undefined_symbol(symtab->arena->v[0], name, LNK_SymbolScopeFlag_Main); lnk_symbol_list_push(scratch.arena, &lookup_undef_list, symbol); } ProfEnd(); @@ -3443,64 +3463,19 @@ l.count += 1; \ for (String8Node *from_node = alt_name_list.from_list.first, *to_node = alt_name_list.to_list.first; from_node != 0; from_node = from_node->next, to_node = to_node->next) { - String8 to_name = push_str8_copy(symtab->arena, to_node->string); - String8 from_name = push_str8_copy(symtab->arena, from_node->string); - LNK_Symbol *fallback = lnk_make_undefined_symbol(symtab->arena, to_name, LNK_SymbolScopeFlag_Main); - LNK_Symbol *weak = lnk_make_weak_symbol(symtab->arena, from_name, COFF_WeakExtType_SEARCH_ALIAS, fallback); + LNK_Symbol *weak = lnk_symbol_table_push_weak(symtab, from_node->string, COFF_WeakExtType_SEARCH_ALIAS, to_node->string); lnk_symbol_list_push(scratch.arena, &input_weak_list, weak); } ProfEnd(); - - ProfBegin("Push Defined Symbols"); - { - Temp temp = temp_begin(scratch.arena); - - ProfBegin("List -> Array"); - LNK_SymbolNodeArray symbol_arr = lnk_symbol_node_array_from_list(temp.arena, input_defn_list); - ProfEnd(); - - ProfBegin("Hash Symbol Names"); - lnk_symbol_node_ptr_array_hash(tp, symbol_arr.v, symbol_arr.count); - ProfEnd(); - - ProfBegin("Populate Buckets"); - LNK_SymbolList *bucket_arr = push_array(temp.arena, LNK_SymbolList, symtab->bucket_count[LNK_SymbolScopeIndex_Defined]); - for (U64 symbol_idx = 0; symbol_idx < symbol_arr.count; symbol_idx += 1) { - LNK_SymbolNode *symbol_node = symbol_arr.v[symbol_idx]; - U64 bucket_idx = symbol_node->hash % symtab->bucket_count[LNK_SymbolScopeIndex_Defined]; - lnk_symbol_list_push_node(&bucket_arr[bucket_idx], symbol_node); - } - ProfEnd(); - - ProfBegin("Insert Defined Symbols"); - LNK_DefinedSymbolInserter symbol_inserter = {0}; - symbol_inserter.symtab = symtab; - symbol_inserter.bucket_arr = bucket_arr; - symbol_inserter.range_arr = tp_divide_work(temp.arena, symtab->bucket_count[LNK_SymbolScopeIndex_Defined], tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, lnk_defined_symbol_inserter, &symbol_inserter); - ProfEnd(); - - temp_end(temp); - } - ProfEnd(); - - ProfBegin("Push Weak Symbols"); - for (LNK_SymbolNode *curr = input_weak_list.first; curr != 0; curr = curr->next) { - lnk_symbol_table_push(symtab, curr->data); - } - ProfEnd(); - - LNK_SymbolList new_weak_symbols = lnk_symbol_list_copy(scratch.arena, input_weak_list); - + // we defined new symbols, give unresolved symbols another chance to be resolved lnk_symbol_list_concat_in_place(&lookup_undef_list, &unresolved_undef_list); - lnk_symbol_list_concat_in_place(&lookup_weak_list, &new_weak_symbols); + lnk_symbol_list_concat_in_place(&lookup_weak_list, &input_weak_list); lnk_symbol_list_concat_in_place(&lookup_weak_list, &unresolved_weak_list); // reset inputs MemoryZeroStruct(&include_symbol_list); MemoryZeroStruct(&alt_name_list); - MemoryZeroStruct(&input_defn_list); MemoryZeroStruct(&input_weak_list); ProfEnd(); @@ -3612,16 +3587,15 @@ l.count += 1; \ // derive machine from obj if (config->machine == COFF_MachineType_UNKNOWN) { config->machine = obj->machine; - } - - // is obj machine compatible? - if (obj->machine != COFF_MachineType_UNKNOWN && // obj with unknown machine type is compatible with any other machine type - config->machine != obj->machine) { - 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)); + } 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)); + } } } ProfEnd(); @@ -3644,14 +3618,15 @@ l.count += 1; \ // collect libs for input LNK_InputLibList lib_list = lnk_collect_default_lib_obj_arr(tp, tp_arena, obj_node_arr); // TODO: put these on temp arena str8_list_concat_in_place(&input_libs[LNK_InputSource_Obj], &lib_list); + + // update symbol table + lnk_push_defined_symbols(tp, symtab, obj_node_arr); // collect symbols for input - LNK_SymbolList new_defn_list = lnk_run_symbol_collector(tp, tp_arena, obj_node_arr, LNK_Symbol_DefinedExtern); LNK_SymbolList new_weak_list = lnk_run_symbol_collector(tp, tp_arena, obj_node_arr, LNK_Symbol_Weak); LNK_SymbolList new_undef_list = lnk_run_symbol_collector(tp, tp_arena, obj_node_arr, LNK_Symbol_Undefined); // TODO: allocate these on temp arena // schedule symbol input - lnk_symbol_list_concat_in_place(&input_defn_list, &new_defn_list); lnk_symbol_list_concat_in_place(&input_weak_list, &new_weak_list); lnk_symbol_list_concat_in_place(&lookup_undef_list, &new_undef_list); @@ -3723,43 +3698,16 @@ l.count += 1; \ } ProfEnd(); - LNK_LibNodeArray lib_arr; - { - ProfBegin("Disk Read Libs"); - String8Array path_arr = str8_array_from_list(scratch.arena, &unique_input_lib_list); - String8Array data_arr = lnk_read_data_from_file_path_parallel(tp, tp_arena->v[0], path_arr); - ProfEnd(); - - ProfBegin("Lib Init"); - lib_arr = lnk_lib_list_push_parallel(tp, tp_arena, &lib_index[input_source], data_arr, path_arr); - ProfEnd(); - - ProfBegin("Count Symbols"); - U64 total_symbol_count = 0; - for (U64 lib_idx = 0; lib_idx < lib_arr.count; lib_idx += 1) { - total_symbol_count += lib_arr.v[lib_idx].data.symbol_count; - } - ProfEnd(); - - ProfBegin("Setup Symbol Array Pointers"); - LNK_Symbol *symbol_arr = push_array_no_zero(symtab->arena, LNK_Symbol, total_symbol_count); - LNK_Symbol **symbol_arr_arr = push_array_no_zero(scratch.arena, LNK_Symbol *, lib_arr.count); - for (U64 lib_idx = 0, cursor = 0; lib_idx < lib_arr.count; lib_idx += 1) { - symbol_arr_arr[lib_idx] = &symbol_arr[cursor]; - cursor += lib_arr.v[lib_idx].data.symbol_count; - } - ProfEnd(); - - ProfBegin("Lazy Symbol Init"); - LNK_LazyIniter lazy_initer_ctx = {0}; - lazy_initer_ctx.range_arr = tp_divide_work(scratch.arena, lib_arr.count, tp->worker_count); - lazy_initer_ctx.lib_arr = lib_arr.v; - lazy_initer_ctx.symbol_arr_arr = symbol_arr_arr; - tp_for_parallel(tp, 0, tp->worker_count, lnk_lazy_initer, &lazy_initer_ctx); - ProfEnd(); - - lnk_symbol_table_push_lazy_arr(tp, symtab, symbol_arr, total_symbol_count); - } + ProfBegin("Disk Read Libs"); + String8Array path_arr = str8_array_from_list(scratch.arena, &unique_input_lib_list); + String8Array data_arr = lnk_read_data_from_file_path_parallel(tp, tp_arena->v[0], path_arr); + ProfEnd(); + + ProfBegin("Lib Init"); + LNK_LibNodeArray lib_arr = lnk_lib_list_push_parallel(tp, tp_arena, &lib_index[input_source], data_arr, path_arr); + ProfEnd(); + + lnk_push_lazy_symbols(tp, symtab, lib_arr); if (lnk_get_log_status(LNK_Log_InputLib)) { if (lib_arr.count > 0) { @@ -3925,12 +3873,7 @@ l.count += 1; \ goto exit; } } break; - case State_RewireComdats: { - ProfBegin("Fold COMDAT symbols"); - lnk_fold_comdat_chunks(tp, symtab); - ProfEnd(); - } break; - + case State_DiscardMetaDataSections: { ProfBegin("Discard Meta Data Sections"); lnk_discard_meta_data_sections(st); @@ -3945,8 +3888,7 @@ l.count += 1; \ LNK_Chunk *debug_dir_array_chunk = lnk_section_push_chunk_list(debug_sect, debug_chunk, str8_zero()); // push symbols for PE directory patch - LNK_Symbol *dir_array_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit(LNK_DEBUG_DIR_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_dir_array_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, dir_array_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_DEBUG_DIR_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_dir_array_chunk, 0, 0, 0); // debug entry for PDB if (config->debug_mode != LNK_DebugMode_None && config->debug_mode != LNK_DebugMode_Null) { @@ -4061,12 +4003,45 @@ l.count += 1; \ String8 size_string = str8_from_memory_size2(scratch.arena, total_input_size); lnk_log(LNK_Log_InputLib, "[Total Lib Input Size %S]", size_string); } + + //lnk_symbol_hash_trie_debug(symtab->scopes[LNK_SymbolScopeIndex_Lib]); ProfBegin("Image Serialize"); image_data = lnk_section_table_serialize(scratch.arena, st); ProfEnd(); - + LNK_Section **sect_id_map = lnk_sect_id_map_from_section_table(scratch.arena, st); + + LNK_Symbol *tls_used_symbol = lnk_symbol_table_searchf(symtab, LNK_SymbolScopeFlag_Main, "_tls_used"); + if (tls_used_symbol) { + ProfBegin("Patch TLS Align"); + + // loop over .tls sections and extract max alignment + LNK_Symbol *tls_sect_symbol = lnk_symbol_table_searchf(symtab, LNK_SymbolScopeFlag_Internal, LNK_TLS_SYMBOL_NAME); + LNK_Chunk *tls_root_chunk = tls_sect_symbol->u.defined.u.chunk; + U64 tls_align = 0; + lnk_visit_chunks(0, tls_root_chunk, lnk_max_tls_align, &tls_align); + + if (IsPow2(tls_align)) { + // compute TLS header offset + U64 tls_header_foff = lnk_file_off_from_symbol(sect_id_map, tls_used_symbol); + + // patch TLS header + if (coff_word_size_from_machine(config->machine) == 8) { + String8 raw_tls_used = str8_substr(image_data, rng_1u64(tls_header_foff, tls_header_foff + sizeof(PE_TLSHeader64))); + PE_TLSHeader64 *tls_header = (PE_TLSHeader64 *) raw_tls_used.str; + tls_header->characteristics |= coff_section_flag_from_align_size(tls_align); + } else { + String8 raw_tls_used = str8_substr(image_data, rng_1u64(tls_header_foff, tls_header_foff + sizeof(PE_TLSHeader32))); + PE_TLSHeader32 *tls_header = (PE_TLSHeader32 *) raw_tls_used.str; + tls_header->characteristics |= coff_section_flag_from_align_size(tls_align); + } + } else { + lnk_error(LNK_Warning_TLSAlign, "unable to patch TLS Header characteristics, alignment must be power of two, align inferred from section flags: %llu", tls_align); + } + + ProfEnd(); + } if (config->flags & LNK_ConfigFlag_WriteImageChecksum) { ProfBegin("Image Checksum"); @@ -4196,8 +4171,7 @@ l.count += 1; \ state_list_push(scratch.arena, state_list, State_InputImports); continue; } - if (input_defn_list.count || - input_weak_list.count || + if (input_weak_list.count || include_symbol_list.node_count || alt_name_list.from_list.node_count) { state_list_push(scratch.arena, state_list, State_InputSymbols); @@ -4264,11 +4238,6 @@ l.count += 1; \ state_list_push(scratch.arena, state_list, State_BuildAndInputLinkerObj); continue; } - if (do_comdat_rewire) { - do_comdat_rewire = 0; - state_list_push(scratch.arena, state_list, State_RewireComdats); - continue; - } if (check_unused_delay_loads) { check_unused_delay_loads = 0; state_list_push(scratch.arena, state_list, State_CheckUnusedDelayLoads); @@ -4359,7 +4328,6 @@ l.count += 1; \ // linker is done punt memory release to OS //lnk_section_table_release(&st); - //lnk_symbol_table_release(&symtab); //lnk_export_table_release(&export_table); //lnk_import_table_release(&imptab_static); //lnk_import_table_release(&imptab_delayed); @@ -4376,6 +4344,9 @@ internal void entry_point(CmdLine *cmdline) { Temp scratch = scratch_begin(0,0); + + int a = 123; + int asdasd = 2; #if PROFILE_TELEMETRY tmMessage(0, TMMF_ICON_NOTE, BUILD_TITLE); diff --git a/src/linker/lnk.h b/src/linker/lnk.h index d8e5c28d..b77ea5ca 100644 --- a/src/linker/lnk.h +++ b/src/linker/lnk.h @@ -172,13 +172,6 @@ typedef struct HashTable **page_ht_arr; } LNK_ObjBaseRelocTask; -typedef struct -{ - Rng1U64 *range_arr; - LNK_LibNode *lib_arr; - LNK_Symbol **symbol_arr_arr; -} LNK_LazyIniter; - typedef struct { LNK_InputObjList input_obj_list; @@ -195,6 +188,15 @@ typedef struct Rng1U64 *range_arr; } LNK_SymbolFinder; +typedef struct +{ + LNK_SymbolTable *symtab; + union { + LNK_ObjNodeArray objs; + LNK_LibNodeArray libs; + } u; +} LNK_SymbolPusher; + typedef struct { LNK_SymbolTable *symtab; @@ -214,7 +216,6 @@ typedef struct LNK_Obj **obj_arr; } LNK_ObjRelocPatcher; - typedef struct { String8 path; diff --git a/src/linker/lnk_chunk.h b/src/linker/lnk_chunk.h index 072fa85c..23d5dccb 100644 --- a/src/linker/lnk_chunk.h +++ b/src/linker/lnk_chunk.h @@ -43,6 +43,8 @@ typedef struct LNK_Chunk #if LNK_DEBUG_CHUNKS String8 debug; #endif + + int debug; } LNK_Chunk, * LNK_ChunkPtr; typedef struct LNK_ChunkNode diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index a9589880..e7a177d5 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -2827,20 +2827,23 @@ THREAD_POOL_TASK_FUNC(lnk_push_dbi_sec_contrib_task) //////////////////////////////// internal -THREAD_POOL_TASK_FUNC(lnk_build_pdb_public_symbols_task) +THREAD_POOL_TASK_FUNC(lnk_build_pdb_public_symbols_defined_task) { - U64 bucket_idx = task_id; - LNK_BuildPublicSymbolsTaskData *task = raw_task; + ProfBeginFunction(); - LNK_Section **sect_id_map = task->sect_id_map; - LNK_SymbolScopeIndex scope_idx = task->scope_idx; - LNK_SymbolList bucket = task->bucket_arr[scope_idx][bucket_idx]; - CV_SymbolList *pub_list = &task->pub_list_arr[bucket_idx]; + LNK_BuildPublicSymbolsTask *task = raw_task; + LNK_Section **sect_id_map = task->sect_id_map; + CV_SymbolList *pub_list = &task->pub_list_arr[task_id]; + LNK_SymbolHashTrieChunkList chunk_list = task->chunk_lists[task_id]; - for (LNK_SymbolNode *symbol_node = bucket.first; symbol_node != 0; symbol_node = symbol_node->next) { - LNK_Symbol *symbol = symbol_node->data; + for (LNK_SymbolHashTrieChunk *chunk = chunk_list.first; chunk != 0; chunk = chunk->next) { + CV_SymbolNode *nodes = push_array_no_zero(arena, CV_SymbolNode, chunk->count); + + for (U64 i = 0, node_idx = 0; i < chunk->count; ++i) { + LNK_Symbol *symbol = chunk->v[i].symbol; + + Assert(LNK_Symbol_IsDefined(symbol->type)); - if (LNK_Symbol_IsDefined(symbol->type)) { LNK_DefinedSymbol *defined_symbol = &symbol->u.defined; if (defined_symbol->value_type == LNK_DefinedSymbolValue_Chunk) { CV_Pub32Flags flags = 0; @@ -2854,11 +2857,15 @@ THREAD_POOL_TASK_FUNC(lnk_build_pdb_public_symbols_task) U32 symbol_off32 = safe_cast_u32(symbol_off); U16 symbol_isect16 = safe_cast_u16(symbol_isect); - CV_SymbolNode *pub_node = cv_symbol_list_push(arena, pub_list); - pub_node->data = cv_make_pub32(arena, flags, symbol_off32, symbol_isect16, symbol->name); + nodes[node_idx].data = cv_make_pub32(arena, flags, symbol_off32, symbol_isect16, symbol->name); + cv_symbol_list_push_node(pub_list, &nodes[node_idx]); + + ++node_idx; } } } + + ProfEnd(); } internal @@ -2866,8 +2873,8 @@ THREAD_POOL_TASK_FUNC(lnk_gsi_hash_cv_list_task) { ProfBeginFunction(); - LNK_BuildPublicSymbolsTaskData *task = raw_task; - Rng1U64 range = task->symbol_ranges[task_id]; + LNK_BuildPublicSymbolsTask *task = raw_task; + Rng1U64 range = task->symbol_ranges[task_id]; for (U64 symbol_idx = range.min; symbol_idx < range.max; ++symbol_idx) { CV_Symbol *symbol = &task->symbols.v[symbol_idx]->data; @@ -2883,22 +2890,20 @@ lnk_build_pdb_public_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, LNK_Section **sect_id_map, - PDB_PsiContext *psi, - LNK_SymbolScopeIndex scope_idx) + PDB_PsiContext *psi) { ProfBeginFunction(); Temp scratch = scratch_begin(arena->v, arena->count); - ProfBegin("Make Public Symbols"); - LNK_BuildPublicSymbolsTaskData task = {0}; - task.sect_id_map = sect_id_map; - task.scope_idx = scope_idx; - task.bucket_arr = symtab->buckets; - task.pub_list_arr = push_array(scratch.arena, CV_SymbolList, symtab->bucket_count[scope_idx]); - tp_for_parallel(tp, arena, symtab->bucket_count[scope_idx], lnk_build_pdb_public_symbols_task, &task); + ProfBegin("Defined"); + LNK_BuildPublicSymbolsTask task = {0}; + task.sect_id_map = sect_id_map; + task.pub_list_arr = push_array(scratch.arena, CV_SymbolList, tp->worker_count); + task.chunk_lists = symtab->chunk_lists[LNK_SymbolScopeIndex_Defined]; + tp_for_parallel(tp, arena, tp->worker_count, lnk_build_pdb_public_symbols_defined_task, &task); ProfEnd(); - CV_SymbolPtrArray symbols = cv_symbol_ptr_array_from_list(scratch.arena, tp, symtab->bucket_count[scope_idx], task.pub_list_arr); + CV_SymbolPtrArray symbols = cv_symbol_ptr_array_from_list(scratch.arena, tp, tp->worker_count, task.pub_list_arr); ProfBegin("GSI Push"); gsi_push_many_arr(tp, psi->gsi, symbols.count, symbols.v); @@ -3070,7 +3075,7 @@ lnk_build_pdb(TP_Context *tp, ProfBegin("Build DBI Section Headers"); { LNK_Symbol *coff_sect_array_symbol = lnk_symbol_table_searchf(symtab, LNK_SymbolScopeFlag_Internal, LNK_COFF_SECT_HEADER_ARRAY_SYMBOL_NAME); - LNK_Chunk *coff_sect_chunk = lnk_defined_symbol_get_chunk(&coff_sect_array_symbol->u.defined); + LNK_Chunk *coff_sect_chunk = lnk_chunk_from_symbol(coff_sect_array_symbol); String8 coff_sect_chunk_data = lnk_data_from_chunk_ref(sect_id_map, coff_sect_chunk->ref); U64 coff_sect_count = coff_sect_chunk_data.size / sizeof(COFF_SectionHeader); COFF_SectionHeader *coff_sect_ptr = (COFF_SectionHeader*)coff_sect_chunk_data.str; @@ -3125,7 +3130,7 @@ lnk_build_pdb(TP_Context *tp, } ProfEnd(); - lnk_build_pdb_public_symbols(tp, tp_arena, symtab, sect_id_map, pdb->psi, LNK_SymbolScopeIndex_Defined); + lnk_build_pdb_public_symbols(tp, tp_arena, symtab, sect_id_map, pdb->psi); pdb_build(tp, tp_arena, pdb, string_ht); diff --git a/src/linker/lnk_debug_info.h b/src/linker/lnk_debug_info.h index 979dcef0..55865019 100644 --- a/src/linker/lnk_debug_info.h +++ b/src/linker/lnk_debug_info.h @@ -333,16 +333,15 @@ typedef struct typedef struct { - LNK_Section **sect_id_map; - LNK_SymbolScopeIndex scope_idx; - LNK_SymbolList **bucket_arr; - CV_SymbolList *pub_list_arr; + LNK_Section **sect_id_map; + LNK_SymbolHashTrieChunkList *chunk_lists; + CV_SymbolList *pub_list_arr; Rng1U64 *symbol_ranges; PDB_GsiContext *gsi; CV_SymbolPtrArray symbols; U32 *hashes; -} LNK_BuildPublicSymbolsTaskData; +} LNK_BuildPublicSymbolsTask; typedef struct { @@ -566,8 +565,7 @@ internal void lnk_build_pdb_public_symbols(TP_Context *tp, TP_Arena *arena, LNK_SymbolTable *symtab, LNK_Section **sect_id_map, - PDB_PsiContext *psi, - LNK_SymbolScopeIndex scope_idx); + PDB_PsiContext *psi); internal String8List lnk_build_pdb(TP_Context *tp, TP_Arena *tp_arena, diff --git a/src/linker/lnk_directive.c b/src/linker/lnk_directive.c index 8857cc3a..6ce82983 100644 --- a/src/linker/lnk_directive.c +++ b/src/linker/lnk_directive.c @@ -70,6 +70,12 @@ lnk_parse_directives(Arena *arena, LNK_DirectiveInfo *directive_info, String8 bu for (U64 i = 0; i < ArrayCount(directive_table); ++i) { if (str8_match(directive_table[i].name, opt->string, StringMatchFlag_CaseInsensitive)) { kind = directive_table[i].kind; +<<<<<<< HEAD +======= + if (kind == LNK_Directive_Merge) { + String8 v = str8_list_join(scratch.arena, &opt->value_strings, &(StringJoin){ .sep = str8_lit_comp(" ")}); + } +>>>>>>> 9e2d09f (switch to thread safe hash trie map) break; } } diff --git a/src/linker/lnk_export_table.c b/src/linker/lnk_export_table.c index 4351d594..ecbe952b 100644 --- a/src/linker/lnk_export_table.c +++ b/src/linker/lnk_export_table.c @@ -218,20 +218,16 @@ lnk_build_edata(LNK_ExportTable *exptab, LNK_SectionTable *st, LNK_SymbolTable * lnk_chunk_set_debugf(edata->arena, string_buffer_chunk, "EXPORT_STRING_BUFFER"); lnk_chunk_set_debugf(edata->arena, image_name_chunk, "EXPORT_IMAGE_NAME"); - LNK_Symbol *image_name_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("export_table.name_voff"), LNK_DefinedSymbolVisibility_Internal, 0, image_name_chunk, 0, 0, 0); - LNK_Symbol *address_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("export_table.export_address_table_voff"), LNK_DefinedSymbolVisibility_Internal, 0, voff_table_chunk, 0, 0, 0); - LNK_Symbol *name_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("export_table.name_pointer_table_voff"), LNK_DefinedSymbolVisibility_Internal, 0, name_voff_table_chunk, 0, 0, 0); - LNK_Symbol *ordinal_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_lit("export_table.ordinal_table_voff"), LNK_DefinedSymbolVisibility_Internal, 0, ordinal_table_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, image_name_symbol); - lnk_symbol_table_push(symtab, address_table_symbol); - lnk_symbol_table_push(symtab, name_table_symbol); - lnk_symbol_table_push(symtab, ordinal_table_symbol); + LNK_Symbol *image_name_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("export_table.name_voff"), LNK_DefinedSymbolVisibility_Internal, 0, image_name_chunk, 0, 0, 0); + LNK_Symbol *address_table_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("export_table.export_address_table_voff"), LNK_DefinedSymbolVisibility_Internal, 0, voff_table_chunk, 0, 0, 0); + LNK_Symbol *name_table_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("export_table.name_pointer_table_voff"), LNK_DefinedSymbolVisibility_Internal, 0, name_voff_table_chunk, 0, 0, 0); + LNK_Symbol *ordinal_table_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("export_table.ordinal_table_voff"), LNK_DefinedSymbolVisibility_Internal, 0, ordinal_table_chunk, 0, 0, 0); // patch header fields - lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTable, name_voff), image_name_symbol); + lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTable, name_voff), image_name_symbol); lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTable, export_address_table_voff), address_table_symbol); - lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTable, name_pointer_table_voff), name_table_symbol); - lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTable, ordinal_table_voff), ordinal_table_symbol); + lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTable, name_pointer_table_voff), name_table_symbol); + lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTable, ordinal_table_voff), ordinal_table_symbol); // reserve virtual offset chunks LNK_Chunk **ordinal_voff_map = push_array(scratch.arena, LNK_Chunk *, exptab->max_ordinal); @@ -254,9 +250,8 @@ lnk_build_edata(LNK_ExportTable *exptab, LNK_SectionTable *st, LNK_SymbolTable * lnk_chunk_set_debugf(edata->arena, name_chunk, "export: %S", name_cstr); // push name symbol - String8 name_export_name = push_str8f(symtab->arena, "export.%S", name_cstr); - LNK_Symbol *name_symbol = lnk_make_defined_symbol_chunk(symtab->arena, name_export_name, LNK_DefinedSymbolVisibility_Internal, 0, name_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, name_symbol); + String8 name_export_name = push_str8f(symtab->arena->v[0], "export.%S", name_cstr); + LNK_Symbol *name_symbol = lnk_symbol_table_push_defined_chunk(symtab, name_export_name, LNK_DefinedSymbolVisibility_Internal, 0, name_chunk, 0, 0, 0); // name voff LNK_Chunk *voff_chunk = lnk_section_push_chunk_bss(edata, name_voff_table_chunk, exptab->voff_size, /* export table must be sorted lexically: */ name_cstr); diff --git a/src/linker/lnk_import_table.c b/src/linker/lnk_import_table.c index df6cc351..1cf40ff3 100644 --- a/src/linker/lnk_import_table.c +++ b/src/linker/lnk_import_table.c @@ -18,17 +18,11 @@ lnk_import_table_alloc_static(LNK_SectionTable *st, LNK_SymbolTable *symtab, COF LNK_Chunk *null_dll_import = lnk_section_push_chunk_data(data_sect, dll_table_chunk, str8(0, sizeof(PE_ImportEntry)), str8_lit("zzzzz")); lnk_chunk_set_debugf(data_sect->arena, null_dll_import, "DLL_DIRECTORY_TERMINATOR"); - LNK_Symbol *dll_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_IMPORT_DLL_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, dll_table_chunk, 0, 0, 0); - LNK_Symbol *int_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_IMPORT_NAME_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, int_chunk , 0, 0, 0); - LNK_Symbol *iat_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_IMPORT_IAT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, iat_chunk , 0, 0, 0); - LNK_Symbol *ilt_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_IMPORT_ILT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk , 0, 0, 0); - LNK_Symbol *code_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_IMPORT_JMP_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, code_chunk , 0, 0, 0); - - lnk_symbol_table_push(symtab, dll_table_symbol); - lnk_symbol_table_push(symtab, int_symbol); - lnk_symbol_table_push(symtab, iat_symbol); - lnk_symbol_table_push(symtab, ilt_symbol); - lnk_symbol_table_push(symtab, code_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_IMPORT_DLL_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, dll_table_chunk, 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_IMPORT_NAME_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, int_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_IMPORT_IAT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, iat_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_IMPORT_ILT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_IMPORT_JMP_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, code_chunk , 0, 0, 0); Arena *arena = arena_alloc(); LNK_ImportTable *imptab = push_array(arena, LNK_ImportTable, 1); @@ -79,23 +73,14 @@ lnk_import_table_alloc_delayed(LNK_SectionTable *st, LNK_SymbolTable *symtab, CO lnk_chunk_set_debugf(data_sect->arena, null_biat_chunk, "BIAT_TERMINATOR"); } - LNK_Symbol *dll_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_DELAYED_IMPORT_DLL_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, dll_table_chunk , 0, 0, 0); - LNK_Symbol *int_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_DELAYED_IMPORT_INT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, int_chunk , 0, 0, 0); - LNK_Symbol *handle_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_DELAYED_IMPORT_HANDLE_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, handle_table_chunk, 0, 0, 0); - LNK_Symbol *iat_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_DELAYED_IMPORT_IAT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, iat_chunk , 0, 0, 0); - LNK_Symbol *ilt_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_DELAYED_IMPORT_ILT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk , 0, 0, 0); - LNK_Symbol *biat_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_DELAYED_IMPORT_BIAT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, biat_chunk , 0, 0, 0); - LNK_Symbol *uiat_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_DELAYED_IMPORT_UIAT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, uiat_chunk , 0, 0, 0); - LNK_Symbol *code_symbol = lnk_make_defined_symbol_chunk(symtab->arena, str8_cstring(LNK_DELAYED_IMPORT_CODE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, code_chunk , 0, 0, 0); - - lnk_symbol_table_push(symtab, dll_table_symbol); - lnk_symbol_table_push(symtab, int_symbol); - lnk_symbol_table_push(symtab, handle_table_symbol); - lnk_symbol_table_push(symtab, iat_symbol); - lnk_symbol_table_push(symtab, ilt_symbol); - lnk_symbol_table_push(symtab, biat_symbol); - lnk_symbol_table_push(symtab, uiat_symbol); - lnk_symbol_table_push(symtab, code_symbol); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_DELAYED_IMPORT_DLL_TABLE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, dll_table_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_DELAYED_IMPORT_INT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, int_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_DELAYED_IMPORT_HANDLE_TABLE_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, handle_table_chunk, 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_DELAYED_IMPORT_IAT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, iat_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_DELAYED_IMPORT_ILT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_DELAYED_IMPORT_BIAT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, biat_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_DELAYED_IMPORT_UIAT_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, uiat_chunk , 0, 0, 0); + lnk_symbol_table_push_defined_chunk(symtab, str8_cstring(LNK_DELAYED_IMPORT_CODE_SYMBOL_NAME) , LNK_DefinedSymbolVisibility_Internal, 0, code_chunk , 0, 0, 0); LNK_ImportTableFlags flags = 0; if (is_unloadable) { @@ -193,21 +178,18 @@ lnk_import_table_push_dll_static(LNK_ImportTable *imptab, LNK_SymbolTable *symta LNK_Chunk *iat_table_chunk = lnk_section_push_chunk_list(data_sect, imptab->iat_chunk, str8_zero()); LNK_Chunk *code_table_chunk = lnk_section_push_chunk_list(code_sect, imptab->code_chunk, str8_zero()); - String8 ilt_symbol_name = push_str8f(symtab->arena, "%S.lookup_table_voff", dll_name); - LNK_Symbol *ilt_symbol = lnk_make_defined_symbol_chunk(symtab->arena, ilt_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, ilt_table_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, ilt_symbol); + String8 ilt_symbol_name = push_str8f(symtab->arena->v[0], "%S.lookup_table_voff", dll_name); + LNK_Symbol *ilt_symbol = lnk_symbol_table_push_defined_chunk(symtab, ilt_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, ilt_table_chunk, 0, 0, 0); - String8 iat_symbol_name = push_str8f(symtab->arena, "%S.import_addr_table_voff", dll_name); - LNK_Symbol *iat_symbol = lnk_make_defined_symbol_chunk(symtab->arena, iat_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, iat_table_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, iat_symbol); + String8 iat_symbol_name = push_str8f(symtab->arena->v[0], "%S.import_addr_table_voff", dll_name); + LNK_Symbol *iat_symbol = lnk_symbol_table_push_defined_chunk(symtab, iat_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, iat_table_chunk, 0, 0, 0); - String8 dll_name_cstr = push_cstr(data_sect->arena, dll_name); + String8 dll_name_cstr = push_cstr(data_sect->arena, dll_name); LNK_Chunk *dll_name_chunk = lnk_section_push_chunk_data(data_sect, int_table_chunk, dll_name_cstr, str8_zero()); lnk_chunk_set_debugf(data_sect->arena, dll_name_chunk, "DLL name chunk (%S)", dll_name); - String8 dll_name_voff_name = push_str8f(symtab->arena, "%S.name_voff", dll_name); - LNK_Symbol *dll_name_voff_symbol = lnk_make_defined_symbol_chunk(symtab->arena, dll_name_voff_name, LNK_DefinedSymbolVisibility_Internal, 0, dll_name_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, dll_name_voff_symbol); + String8 dll_name_voff_name = push_str8f(symtab->arena->v[0], "%S.name_voff", dll_name); + LNK_Symbol *dll_name_voff_symbol = lnk_symbol_table_push_defined_chunk(symtab, dll_name_voff_name, LNK_DefinedSymbolVisibility_Internal, 0, dll_name_chunk, 0, 0, 0); // chunk for dll directory entry PE_ImportEntry *dir = push_array(imptab->arena, PE_ImportEntry, 1); @@ -272,32 +254,29 @@ lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symt imp_desc->time_stamp = 0; // emit entry chunk - String8 imp_desc_data = str8_struct(imp_desc); + String8 imp_desc_data = str8_struct(imp_desc); LNK_Chunk *imp_desc_chunk = lnk_section_push_chunk_data(data_sect, imptab->dll_table_chunk, imp_desc_data, str8_zero()); // emit entry symbol - String8 imp_desc_name = push_str8f(symtab->arena, "__DELAY_IMPORT_DESCRIPTOR_%S", dll_name); - LNK_Symbol *imp_desc_symbol = lnk_make_defined_symbol_chunk(symtab->arena, imp_desc_name, LNK_DefinedSymbolVisibility_Extern, 0, imp_desc_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, imp_desc_symbol); + String8 imp_desc_name = push_str8f(symtab->arena->v[0], "__DELAY_IMPORT_DESCRIPTOR_%S", dll_name); + LNK_Symbol *imp_desc_symbol = lnk_symbol_table_push_defined_chunk(symtab, imp_desc_name, LNK_DefinedSymbolVisibility_Extern, 0, imp_desc_chunk, 0, 0, 0); // emit string table chunk - String8 int_table_chunk_debug = push_str8f(data_sect->arena, "delayed.%S.int", dll_name); - LNK_Chunk *int_table_chunk = lnk_section_push_chunk_list(data_sect, imptab->int_chunk, int_table_chunk_debug); + String8 int_table_chunk_debug = push_str8f(data_sect->arena, "delayed.%S.int", dll_name); + LNK_Chunk *int_table_chunk = lnk_section_push_chunk_list(data_sect, imptab->int_chunk, int_table_chunk_debug); - String8 int_table_symbol_name = push_str8f(symtab->arena, "delayed.%S.int", dll_name); - LNK_Symbol *int_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, int_table_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, int_table_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, int_table_symbol); + String8 int_table_symbol_name = push_str8f(symtab->arena->v[0], "delayed.%S.int", dll_name); + LNK_Symbol *int_table_symbol = lnk_symbol_table_push_defined_chunk(symtab, int_table_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, int_table_chunk, 0, 0, 0); LNK_Chunk *null_string_chunk = lnk_section_push_chunk_list(data_sect, int_table_chunk, str8_lit("zzzzz")); lnk_chunk_set_debugf(data_sect->arena, null_string_chunk, "string table null"); // emit DLL name chunk - String8 name_chunk_data = push_cstr(data_sect->arena, dll_name); - LNK_Chunk *name_chunk = lnk_section_push_chunk_data(data_sect, int_table_chunk, name_chunk_data, str8_zero()); + String8 name_chunk_data = push_cstr(data_sect->arena, dll_name); + LNK_Chunk *name_chunk = lnk_section_push_chunk_data(data_sect, int_table_chunk, name_chunk_data, str8_zero()); - String8 name_symbol_name = push_str8f(symtab->arena, "delayed.%S.name", dll_name); - LNK_Symbol *name_symbol = lnk_make_defined_symbol_chunk(symtab->arena, name_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, name_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, name_symbol); + String8 name_symbol_name = push_str8f(symtab->arena->v[0], "delayed.%S.name", dll_name); + LNK_Symbol *name_symbol = lnk_symbol_table_push_defined_chunk(symtab, name_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, name_chunk, 0, 0, 0); // patch DLL name voff lnk_section_push_reloc(data_sect, imp_desc_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_DelayedImportEntry, name_voff), name_symbol); @@ -305,9 +284,8 @@ lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symt // emit DLL handle chunk LNK_Chunk *handle_chunk = lnk_section_push_chunk_bss(data_sect, imptab->handle_table_chunk, handle_size, str8_zero()); - String8 handle_name = push_str8f(symtab->arena, "delayed.%S.handle", dll_name); - LNK_Symbol *handle_symbol = lnk_make_defined_symbol_chunk(symtab->arena, handle_name, LNK_DefinedSymbolVisibility_Internal, 0, handle_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, handle_symbol); + String8 handle_name = push_str8f(symtab->arena->v[0], "delayed.%S.handle", dll_name); + LNK_Symbol *handle_symbol = lnk_symbol_table_push_defined_chunk(symtab, handle_name, LNK_DefinedSymbolVisibility_Internal, 0, handle_chunk, 0, 0, 0); // patch DLL handle voff lnk_section_push_reloc(data_sect, imp_desc_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_DelayedImportEntry, module_handle_voff), handle_symbol); @@ -315,9 +293,8 @@ lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symt // emit IAT chunk LNK_Chunk *iat_table_chunk = lnk_section_push_chunk_list(data_sect, imptab->iat_chunk, str8_zero()); - String8 iat_table_name = push_str8f(symtab->arena, "delayed.%S.iat", dll_name); - LNK_Symbol *iat_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, iat_table_name, LNK_DefinedSymbolVisibility_Internal, 0, iat_table_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, iat_table_symbol); + String8 iat_table_name = push_str8f(symtab->arena->v[0], "delayed.%S.iat", dll_name); + LNK_Symbol *iat_table_symbol = lnk_symbol_table_push_defined_chunk(symtab, iat_table_name, LNK_DefinedSymbolVisibility_Internal, 0, iat_table_chunk, 0, 0, 0); LNK_Chunk *null_iat_chunk = lnk_section_push_chunk_bss(data_sect, iat_table_chunk, import_size, str8_lit("zzzzzz")); lnk_chunk_set_debugf(data_sect->arena, null_iat_chunk, "%S: IAT terminator", dll_name); @@ -328,9 +305,8 @@ lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symt LNK_Chunk *null_ilt_chunk = lnk_section_push_chunk_bss(data_sect, ilt_table_chunk, import_size, str8_lit("zzzzzz")); lnk_chunk_set_debugf(data_sect->arena, null_ilt_chunk, "%S: ILT terminator", dll_name); - String8 ilt_table_name = push_str8f(symtab->arena, "delayed.%S.ilt", dll_name); - LNK_Symbol *ilt_table_symbol = lnk_make_defined_symbol_chunk(symtab->arena, ilt_table_name, LNK_DefinedSymbolVisibility_Extern, 0, ilt_table_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, ilt_table_symbol); + String8 ilt_table_name = push_str8f(symtab->arena->v[0], "delayed.%S.ilt", dll_name); + LNK_Symbol *ilt_table_symbol = lnk_symbol_table_push_defined_chunk(symtab, ilt_table_name, LNK_DefinedSymbolVisibility_Extern, 0, ilt_table_chunk, 0, 0, 0); // patch import address table voff lnk_section_push_reloc(data_sect, imp_desc_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_DelayedImportEntry, iat_voff), iat_table_symbol); @@ -343,9 +319,8 @@ lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symt if (imptab->flags & LNK_ImportTableFlag_EmitBiat) { biat_chunk = lnk_section_push_chunk_list(data_sect, imptab->biat_chunk, str8_zero()); - String8 biat_symbol_name = push_str8f(symtab->arena, "delayed.%S.BIAT", dll_name); - LNK_Symbol *biat_symbol = lnk_make_defined_symbol_chunk(symtab->arena, biat_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, biat_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, biat_symbol); + String8 biat_symbol_name = push_str8f(symtab->arena->v[0], "delayed.%S.BIAT", dll_name); + LNK_Symbol *biat_symbol = lnk_symbol_table_push_defined_chunk(symtab, biat_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, biat_chunk, 0, 0, 0); // patch BIAT field off lnk_section_push_reloc(data_sect, imp_desc_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_DelayedImportEntry, bound_table_voff), biat_symbol); @@ -356,9 +331,8 @@ lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symt if (imptab->flags & LNK_ImportTableFlag_EmitUiat) { uiat_chunk = lnk_section_push_chunk_list(data_sect, imptab->uiat_chunk, str8_zero()); - String8 uiat_symbol_name = push_str8f(symtab->arena, "delayed.%S.UIAT", dll_name); - LNK_Symbol *uiat_symbol = lnk_make_defined_symbol_chunk(symtab->arena, uiat_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, uiat_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, uiat_symbol); + String8 uiat_symbol_name = push_str8f(symtab->arena->v[0], "delayed.%S.UIAT", dll_name); + LNK_Symbol *uiat_symbol = lnk_symbol_table_push_defined_chunk(symtab, uiat_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, uiat_chunk, 0, 0, 0); // patch UIAT field voff lnk_section_push_reloc(data_sect, imp_desc_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_DelayedImportEntry, unload_table_voff), uiat_symbol); @@ -372,7 +346,7 @@ lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symt LNK_Chunk *tail_merge_chunk = 0; switch (machine) { case COFF_MachineType_X64: { - LNK_Symbol *delay_load_helper_symbol = lnk_make_undefined_symbol(symtab->arena, str8_lit(LNK_DELAY_LOAD_HELPER2_SYMBOL_NAME), LNK_SymbolScopeFlag_Main); + LNK_Symbol *delay_load_helper_symbol = lnk_make_undefined_symbol(symtab->arena->v[0], str8_lit(LNK_DELAY_LOAD_HELPER2_SYMBOL_NAME), LNK_SymbolScopeFlag_Main); tail_merge_chunk = lnk_emit_tail_merge_thunk_x64(code_sect, code_chunk, imp_desc_symbol, delay_load_helper_symbol); } break; default: { @@ -438,9 +412,8 @@ lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symt LNK_Chunk *int_chunk = lnk_section_push_chunk_data(data_sect, int_table_chunk, int_data, str8_zero()); // create symbol for lookup chunk - String8 int_symbol_name = push_str8f(symtab->arena, "static.%S.%S.name", dll->name, header->func_name); - LNK_Symbol *int_symbol = lnk_make_defined_symbol_chunk(symtab->arena, int_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, int_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, int_symbol); + String8 int_symbol_name = push_str8f(symtab->arena->v[0], "static.%S.%S.name", dll->name, header->func_name); + LNK_Symbol *int_symbol = lnk_symbol_table_push_defined_chunk(symtab, int_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, int_chunk, 0, 0, 0); // in the file IAT mirrors ILT, dynamic linker later overwrites it with imported function addresses. ilt_chunk = lnk_section_push_chunk_bss(data_sect, ilt_table_chunk, import_size, sort_index); @@ -464,12 +437,10 @@ lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symt } break; } - String8 ilt_symbol_name = push_str8f(symtab->arena, "static.%S.%S.ilt", dll->name, header->func_name); - String8 iat_symbol_name = push_str8f(symtab->arena, "__imp_%S", header->func_name); - LNK_Symbol *ilt_symbol = lnk_make_defined_symbol_chunk(symtab->arena, ilt_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk, 0, 0, 0); - LNK_Symbol *iat_symbol = lnk_make_defined_symbol_chunk(symtab->arena, iat_symbol_name, LNK_DefinedSymbolVisibility_Extern, 0, iat_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, ilt_symbol); - lnk_symbol_table_push(symtab, iat_symbol); + String8 ilt_symbol_name = push_str8f(symtab->arena->v[0], "static.%S.%S.ilt", dll->name, header->func_name); + String8 iat_symbol_name = push_str8f(symtab->arena->v[0], "__imp_%S", header->func_name); + LNK_Symbol *ilt_symbol = lnk_symbol_table_push_defined_chunk(symtab, ilt_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk, 0, 0, 0); + LNK_Symbol *iat_symbol = lnk_symbol_table_push_defined_chunk(symtab, iat_symbol_name, LNK_DefinedSymbolVisibility_Extern, 0, iat_chunk, 0, 0, 0); // generate thunks LNK_Symbol *jmp_thunk_symbol = g_null_symbol_ptr; @@ -481,9 +452,8 @@ lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symt lnk_section_associate_chunks(data_sect, iat_chunk, jmp_thunk_chunk); // push jump thunk symbol - String8 jmp_thunk_symbol_name = push_str8_copy(symtab->arena, header->func_name); + String8 jmp_thunk_symbol_name = push_str8_copy(symtab->arena->v[0], header->func_name); jmp_thunk_symbol = lnk_emit_jmp_thunk_symbol(symtab, jmp_thunk_chunk, jmp_thunk_symbol_name); - lnk_symbol_set_debugf(symtab->arena, jmp_thunk_symbol, "x64 jmp thunk %S.%S", dll->name, header->func_name); } break; default: lnk_not_implemented("TODO: support for machine 0x%X", dll->machine); break; } @@ -538,19 +508,16 @@ lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *sym if (header->type == COFF_ImportHeaderType_CODE) { switch (dll->machine) { case COFF_MachineType_X64: { - String8 iat_symbol_name = push_str8f(symtab->arena, "__imp_%S", header->func_name); - LNK_Symbol *iat_symbol = lnk_make_undefined_symbol(symtab->arena, iat_symbol_name, LNK_SymbolScopeFlag_Main); - lnk_symbol_set_debugf(symtab->arena, iat_symbol, "x64 IAT (delayed) %S.%S", dll->name, header->func_name); + String8 iat_symbol_name = push_str8f(symtab->arena->v[0], "__imp_%S", header->func_name); + LNK_Symbol *iat_symbol = lnk_make_undefined_symbol(symtab->arena->v[0], iat_symbol_name, LNK_SymbolScopeFlag_Main); // emit jmp thunk chunk jmp_thunk_chunk = lnk_emit_indirect_jump_thunk_x64(code_sect, code_table_chunk, iat_symbol); jmp_thunk_symbol = lnk_emit_jmp_thunk_symbol(symtab, jmp_thunk_chunk, header->func_name); - lnk_symbol_set_debugf(symtab->arena, jmp_thunk_symbol, "x64 jmp thunk (delayed) %S.%S", dll->name, header->func_name); // emit load thunk load_thunk_chunk = lnk_emit_load_thunk_x64(code_sect, code_table_chunk, iat_symbol, dll->tail_merge_symbol); load_thunk_symbol = lnk_emit_load_thunk_symbol(symtab, load_thunk_chunk, header->func_name); - lnk_symbol_set_debugf(symtab->arena, load_thunk_symbol, "x64 load thunk (delayed) %S.%S", dll->name, header->func_name); } break; default: lnk_not_implemented("TODO: support for machine 0x%X", dll->machine); break; } @@ -582,9 +549,8 @@ lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *sym LNK_Chunk *int_chunk = lnk_section_push_chunk_data(data_sect, int_table_chunk, int_data, str8_zero()); // create symbol for lookup chunk - String8 int_symbol_name = push_str8f(symtab->arena, "%S.%S.name.delayed", dll->name, header->func_name); - int_symbol = lnk_make_defined_symbol_chunk(symtab->arena, int_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, int_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, int_symbol); + String8 int_symbol_name = push_str8f(symtab->arena->v[0], "%S.%S.name.delayed", dll->name, header->func_name); + int_symbol = lnk_symbol_table_push_defined_chunk(symtab, int_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, int_chunk, 0, 0, 0); // dynamic linker patches this voff on DLL load event ilt_chunk = lnk_section_push_chunk_bss(data_sect, ilt_table_chunk, import_size, sort_index); @@ -635,13 +601,11 @@ lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *sym lnk_section_associate_chunks(data_sect, iat_chunk, load_thunk_chunk); } - String8 iat_symbol_name = push_str8f(symtab->arena, "__imp_%S", header->func_name); - LNK_Symbol *iat_symbol = lnk_make_defined_symbol_chunk(symtab->arena, iat_symbol_name, LNK_DefinedSymbolVisibility_Extern, 0, iat_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, iat_symbol); + String8 iat_symbol_name = push_str8f(symtab->arena->v[0], "__imp_%S", header->func_name); + LNK_Symbol *iat_symbol = lnk_symbol_table_push_defined_chunk(symtab, iat_symbol_name, LNK_DefinedSymbolVisibility_Extern, 0, iat_chunk, 0, 0, 0); - String8 ilt_symbol_name = push_str8f(symtab->arena, "%S.%S.ilt.delayed", dll->name, header->func_name); - LNK_Symbol *ilt_symbol = lnk_make_defined_symbol_chunk(symtab->arena, ilt_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, ilt_symbol); + String8 ilt_symbol_name = push_str8f(symtab->arena->v[0], "%S.%S.ilt.delayed", dll->name, header->func_name); + LNK_Symbol *ilt_symbol = lnk_symbol_table_push_defined_chunk(symtab, ilt_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk, 0, 0, 0); // fill out import LNK_ImportFunc *func = push_array(imptab->arena, LNK_ImportFunc, 1); @@ -771,9 +735,8 @@ lnk_emit_load_thunk_symbol(LNK_SymbolTable *symtab, LNK_Chunk *chunk, String8 fu { ProfBeginFunction(); // emit load thunk symbol - String8 load_thunk_name = push_str8f(symtab->arena, "__imp_load_%S", func_name); - LNK_Symbol *load_thunk_symbol = lnk_make_defined_symbol_chunk(symtab->arena, load_thunk_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, load_thunk_symbol); + String8 load_thunk_name = push_str8f(symtab->arena->v[0], "__imp_load_%S", func_name); + LNK_Symbol *load_thunk_symbol = lnk_symbol_table_push_defined_chunk(symtab, load_thunk_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, 0, 0); ProfEnd(); return load_thunk_symbol; } @@ -782,9 +745,8 @@ internal LNK_Symbol * lnk_emit_jmp_thunk_symbol(LNK_SymbolTable *symtab, LNK_Chunk *chunk, String8 func_name) { ProfBeginFunction(); - String8 jmp_thunk_name = push_str8f(symtab->arena, "%S", func_name); - LNK_Symbol *jmp_thunk_symbol = lnk_make_defined_symbol_chunk(symtab->arena, jmp_thunk_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, jmp_thunk_symbol); + String8 jmp_thunk_name = push_str8f(symtab->arena->v[0], "%S", func_name); + LNK_Symbol *jmp_thunk_symbol = lnk_symbol_table_push_defined_chunk(symtab, jmp_thunk_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, 0, 0); ProfEnd(); return jmp_thunk_symbol; } @@ -793,9 +755,8 @@ internal LNK_Symbol * lnk_emit_tail_merge_symbol(LNK_SymbolTable *symtab, LNK_Chunk *chunk, String8 func_name) { ProfBeginFunction(); - String8 tail_merge_name = push_str8f(symtab->arena, "__tailMerge_%S", func_name); - LNK_Symbol *tail_merge_symbol = lnk_make_defined_symbol_chunk(symtab->arena, tail_merge_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, 0, 0); - lnk_symbol_table_push(symtab, tail_merge_symbol); + String8 tail_merge_name = push_str8f(symtab->arena->v[0], "__tailMerge_%S", func_name); + LNK_Symbol *tail_merge_symbol = lnk_symbol_table_push_defined_chunk(symtab, tail_merge_name, LNK_DefinedSymbolVisibility_Extern, LNK_DefinedSymbolFlag_IsFunc|LNK_DefinedSymbolFlag_IsThunk, chunk, 0, 0, 0); ProfEnd(); return tail_merge_symbol; } diff --git a/src/linker/lnk_lib.c b/src/linker/lnk_lib.c index a2457166..193d53a2 100644 --- a/src/linker/lnk_lib.c +++ b/src/linker/lnk_lib.c @@ -97,6 +97,8 @@ lnk_lib_symbol_array_sort(LNK_LibSymbol *arr, U64 count) internal LNK_Lib lnk_lib_from_data(Arena *arena, String8 data, String8 path) { + ProfBeginFunction(); + U64 symbol_count; String8 string_table; U32 *member_off_arr; @@ -167,9 +169,11 @@ lnk_lib_from_data(Arena *arena, String8 data, String8 path) lib.symbol_name_list = symbol_name_list; lib.long_names = parse.long_names; + ProfEnd(); return lib; } +internal THREAD_POOL_TASK_FUNC(lnk_lib_initer) { LNK_LibIniter *task = raw_task; @@ -179,6 +183,7 @@ THREAD_POOL_TASK_FUNC(lnk_lib_initer) String8 path = task->path_arr[task_id]; *lib = lnk_lib_from_data(arena, data, path); + lib->input_idx = task->base_input_idx + task_id; } internal LNK_LibNodeArray @@ -187,15 +192,16 @@ lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, S Assert(data_arr.count == path_arr.count); U64 lib_count = data_arr.count; - LNK_LibIniter lib_initer = {0}; - lib_initer.node_arr = lnk_lib_list_reserve(arena->v[0], list, lib_count); - lib_initer.data_arr = data_arr.v; - lib_initer.path_arr = path_arr.v; - tp_for_parallel(tp, arena, lib_count, lnk_lib_initer, &lib_initer); + LNK_LibIniter task = {0}; + task.node_arr = lnk_lib_list_reserve(arena->v[0], list, lib_count); + task.data_arr = data_arr.v; + task.path_arr = path_arr.v; + task.base_input_idx = list->count; + tp_for_parallel(tp, arena, lib_count, lnk_lib_initer, &task); - LNK_LibNodeArray arr; - arr.count = lib_count; - arr.v = lib_initer.node_arr; + LNK_LibNodeArray arr = {0}; + arr.count = lib_count; + arr.v = task.node_arr; return arr; } diff --git a/src/linker/lnk_lib.h b/src/linker/lnk_lib.h index 3801e9fd..af87ae84 100644 --- a/src/linker/lnk_lib.h +++ b/src/linker/lnk_lib.h @@ -12,6 +12,7 @@ typedef struct LNK_Lib U32 * member_off_arr; String8List symbol_name_list; String8 long_names; + U64 input_idx; } LNK_Lib; typedef struct LNK_LibNode @@ -92,9 +93,10 @@ typedef struct LNK_LibBuild typedef struct { - LNK_LibNode *node_arr; - String8 *data_arr; - String8 *path_arr; + LNK_LibNode *node_arr; + String8 *data_arr; + String8 *path_arr; + U64 base_input_idx; } LNK_LibIniter; //////////////////////////////// diff --git a/src/linker/lnk_obj.c b/src/linker/lnk_obj.c index d2270a2e..95113386 100644 --- a/src/linker/lnk_obj.c +++ b/src/linker/lnk_obj.c @@ -417,7 +417,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) lnk_chunk_set_debugf(arena, master_common_block, "%S: master common block", path); // convert from coff - LNK_SymbolArray symbol_arr = lnk_symbol_array_from_coff(arena, input->data, cached_path, coff_info.string_table_off, coff_info.section_count_no_null, coff_sect_arr, coff_symbols, chunk_arr, master_common_block); + LNK_SymbolArray symbol_arr = lnk_symbol_array_from_coff(arena, input->data, obj, cached_path, coff_info.string_table_off, coff_info.section_count_no_null, coff_sect_arr, coff_symbols, chunk_arr, master_common_block); LNK_SymbolList symbol_list = lnk_symbol_list_from_array(arena, symbol_arr); LNK_RelocList *reloc_list_arr = lnk_reloc_list_array_from_coff(arena, coff_info.machine, input->data, coff_info.section_count_no_null, coff_sect_arr, chunk_arr, symbol_arr); @@ -425,6 +425,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) obj->data = input->data; obj->path = cached_path; obj->lib_path = cached_lib_path; + obj->input_idx = obj_idx; obj->machine = coff_info.machine; obj->chunk_count = chunk_count; obj->sect_count = coff_info.section_count_no_null; @@ -712,6 +713,7 @@ lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_ObjList *obj_lis internal LNK_SymbolArray lnk_symbol_array_from_coff(Arena *arena, String8 coff_data, + LNK_Obj *obj, String8 obj_path, U64 string_table_off, U64 sect_count, @@ -729,7 +731,8 @@ lnk_symbol_array_from_coff(Arena *arena, for (U64 symbol_idx = 0; symbol_idx < coff_symbols.count; symbol_idx += 1) { COFF_Symbol32 *coff_symbol = &coff_symbols.v[symbol_idx]; LNK_Symbol *symbol = &symbol_array.v[symbol_idx]; - lnk_symbol_set_debug(symbol, obj_path); + + symbol->obj = obj; String8 name = coff_read_symbol_name(coff_data, string_table_off, &coff_symbol->name); diff --git a/src/linker/lnk_obj.h b/src/linker/lnk_obj.h index 370059d1..6a6ee555 100644 --- a/src/linker/lnk_obj.h +++ b/src/linker/lnk_obj.h @@ -32,6 +32,7 @@ typedef struct LNK_Obj String8 data; String8 path; String8 lib_path; + U64 input_idx; U64 common_symbol_size; COFF_MachineType machine; U64 chunk_count; @@ -179,7 +180,7 @@ internal LNK_ChunkList * lnk_collect_obj_chunks(TP_Context *tp, TP_Arena *arena internal LNK_ObjNodeArray lnk_obj_list_push_parallel(TP_Context *tp, TP_Arena *tp_arena, LNK_ObjList *obj_list, LNK_SectionTable *st, 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, String8 coff_data, String8 obj_path, U64 string_table_off, U64 sect_count, COFF_SectionHeader *coff_sect_arr, COFF_Symbol32Array coff_symbols, LNK_Chunk *chunk_arr, LNK_Chunk *master_common_block); +internal LNK_SymbolArray lnk_symbol_array_from_coff(Arena *arena, String8 coff_data, LNK_Obj *obj, String8 obj_path, U64 string_table_off, U64 sect_count, COFF_SectionHeader *coff_sect_arr, COFF_Symbol32Array coff_symbols, LNK_Chunk *chunk_arr, LNK_Chunk *master_common_block); internal LNK_RelocList lnk_reloc_list_from_coff_reloc_array(Arena *arena, COFF_MachineType machine, LNK_Chunk *chunk, LNK_SymbolArray symbol_array, COFF_Reloc *reloc_v, U64 reloc_count); internal LNK_RelocList * lnk_reloc_list_array_from_coff(Arena *arena, COFF_MachineType machine, String8 coff_data, U64 sect_count, COFF_SectionHeader *coff_sect_arr, LNK_Chunk *sect_chunk_arr, LNK_SymbolArray symbol_array); internal LNK_DirectiveInfo lnk_init_directives(Arena *arena, String8 obj_path, U64 chunk_count, String8 *sect_name_arr, LNK_Chunk *chunk_arr); diff --git a/src/linker/lnk_symbol_table.c b/src/linker/lnk_symbol_table.c index f6addf1f..26a31e55 100644 --- a/src/linker/lnk_symbol_table.c +++ b/src/linker/lnk_symbol_table.c @@ -118,18 +118,20 @@ lnk_make_lazy_symbol(Arena *arena, String8 name, LNK_Lib *lib, U64 member_offset } internal LNK_Chunk * -lnk_defined_symbol_get_chunk(LNK_DefinedSymbol *symbol) +lnk_chunk_from_symbol(LNK_Symbol *symbol) { - if (symbol->value_type == LNK_DefinedSymbolValue_Chunk) { - return symbol->u.chunk; + if (LNK_Symbol_IsDefined(symbol->type) && symbol->u.defined.value_type == LNK_DefinedSymbolValue_Chunk) { + return symbol->u.defined.u.chunk; } return 0; } +//////////////////////////////// + internal void lnk_symbol_list_push_node(LNK_SymbolList *list, LNK_SymbolNode *node) { - DLLPushBack(list->first, list->last, node); + SLLQueuePush(list->first, list->last, node); list->count += 1; } @@ -137,85 +139,15 @@ internal LNK_SymbolNode * lnk_symbol_list_push(Arena *arena, LNK_SymbolList *list, LNK_Symbol *symbol) { LNK_SymbolNode *node = push_array(arena, LNK_SymbolNode, 1); - node->data = symbol; + node->data = symbol; lnk_symbol_list_push_node(list, node); return node; } -internal void -lnk_symbol_list_push_list(LNK_SymbolList *list, LNK_SymbolList *to_push) -{ - if (to_push->count) { - if (list->count) { - list->last->next = to_push->first; - to_push->first->prev = list->last; - list->last = to_push->last; - list->count += to_push->count; - } else { - *list = *to_push; - } - MemoryZeroStruct(to_push); - } -} - -internal void -lnk_symbol_list_insert_after(LNK_SymbolList *list, LNK_SymbolNode *node, LNK_SymbolNode *insert) -{ - DLLInsert(list->first, list->last, node, insert); - list->count += 1; -} - -internal LNK_SymbolNode * -lnk_symbol_list_pop_node(LNK_SymbolList *list) -{ - LNK_SymbolNode *node = 0; - if (list->count) { - node = list->first; - DLLRemove(list->first, list->last, node); - node->next = 0; - node->prev = 0; - list->count -= 1; - } - return node; -} - -internal LNK_Symbol * -lnk_symbol_list_pop(LNK_SymbolList *list) -{ - LNK_SymbolNode *node = lnk_symbol_list_pop_node(list); - return node ? node->data : 0; -} - -internal void -lnk_symbol_list_remove(LNK_SymbolList *list, LNK_SymbolNode *node) -{ - Assert(list->count > 0); - - list->count -= 1; - DLLRemove(list->first, list->last, node); - - node->next = 0; - node->prev = 0; -} - internal void lnk_symbol_list_concat_in_place(LNK_SymbolList *list, LNK_SymbolList *to_concat) { - DLLConcatInPlace(list, to_concat); -} - -internal LNK_SymbolList -lnk_symbol_list_copy(Arena *arena, LNK_SymbolList list) -{ - LNK_SymbolList result = {0}; - LNK_SymbolNode *node_arr = push_array_no_zero(arena, LNK_SymbolNode, list.count); - for (LNK_SymbolNode *i = list.first; i != 0; i = i->next) { - Assert(result.count < list.count); - LNK_SymbolNode *n = &node_arr[result.count++]; - n->data = i->data; - SLLQueuePush(result.first, result.last, n); - } - return result; + SLLConcatInPlace(list, to_concat); } internal LNK_SymbolNode * @@ -243,8 +175,8 @@ lnk_symbol_list_from_array(Arena *arena, LNK_SymbolArray arr) LNK_SymbolNode *node_arr = push_array_no_zero(arena, LNK_SymbolNode, arr.count); for (U64 i = 0; i < arr.count; i += 1) { LNK_SymbolNode *node = &node_arr[i]; - node->prev = node->next = 0; - node->data = &arr.v[i]; + node->next = 0; + node->data = &arr.v[i]; lnk_symbol_list_push_node(&list, node); } return list; @@ -262,50 +194,6 @@ lnk_symbol_node_array_from_list(Arena *arena, LNK_SymbolList list) return result; } -internal -THREAD_POOL_TASK_FUNC(lnk_symbol_node_ptr_hasher) -{ - LNK_SymbolNodePtrHasher *hasher = raw_task; - Rng1U64 range = hasher->range_arr[task_id]; - for (U64 symbol_idx = range.min; symbol_idx < range.max; symbol_idx += 1) { - LNK_SymbolNode *symbol_node = hasher->input_arr[symbol_idx]; - symbol_node->hash = lnk_symbol_table_hash(symbol_node->data->name); - } -} - -internal void -lnk_symbol_node_ptr_array_hash(TP_Context *tp, LNK_SymbolNode **arr, U64 count) -{ - Temp scratch = scratch_begin(0, 0); - LNK_SymbolNodePtrHasher hasher = {0}; - hasher.input_arr = arr; - hasher.range_arr = tp_divide_work(scratch.arena, count, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, lnk_symbol_node_ptr_hasher, &hasher); - scratch_end(scratch); -} - -internal -THREAD_POOL_TASK_FUNC(lnk_symbol_node_hasher) -{ - LNK_SymbolNodeHasher *hasher = raw_task; - Rng1U64 range = hasher->range_arr[task_id]; - for (U64 symbol_idx = range.min; symbol_idx < range.max; symbol_idx += 1) { - LNK_SymbolNode *symbol_node = &hasher->input_arr[symbol_idx]; - symbol_node->hash = lnk_symbol_table_hash(symbol_node->data->name); - } -} - -internal void -lnk_symbol_node_array_hash(TP_Context *tp, LNK_SymbolNode *arr, U64 count) -{ - Temp scratch = scratch_begin(0, 0); - LNK_SymbolNodeHasher hasher = {0}; - hasher.input_arr = arr; - hasher.range_arr = tp_divide_work(scratch.arena, count, tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, lnk_symbol_node_hasher, &hasher); - scratch_end(scratch); -} - internal LNK_SymbolArray lnk_symbol_array_from_list(Arena *arena, LNK_SymbolList list) { @@ -318,127 +206,332 @@ lnk_symbol_array_from_list(Arena *arena, LNK_SymbolList list) return arr; } -internal LNK_Symbol * -lnk_symbol_array_search(LNK_SymbolArray symarr, String8 name, StringMatchFlags flags) +//////////////////////////////// + +internal LNK_SymbolHashTrie * +lnk_symbol_hash_trie_chunk_list_push(Arena *arena, LNK_SymbolHashTrieChunkList *list, U64 cap) { - for (U64 isym = 0; isym < symarr.count; ++isym) { - LNK_Symbol *sym = &symarr.v[isym]; - if (str8_match(sym->name, name, flags)) { - return sym; + if (list->last == 0 || list->last->count >= list->last->cap) { + LNK_SymbolHashTrieChunk *chunk = push_array(arena, LNK_SymbolHashTrieChunk, 1); + chunk->cap = cap; + chunk->v = push_array_no_zero(arena, LNK_SymbolHashTrie, cap); + SLLQueuePush(list->first, list->last, chunk); + ++list->count; + } + + LNK_SymbolHashTrie *result = &list->last->v[list->last->count++]; + return result; +} + +internal B32 +lnk_can_replace_symbol(const LNK_Symbol *dst, const LNK_Symbol *src) +{ + B32 can_replace = 0; + + Assert(dst != src); + Assert(str8_match(dst->name, src->name, 0)); + Assert(src->type != LNK_Symbol_Undefined); + + if (dst->type == LNK_Symbol_Lazy && src->type == LNK_Symbol_Lazy) { + // link.exe picks symbol from lib that is discovered first + LNK_Lib *dst_lib = dst->u.lazy.lib; + LNK_Lib *src_lib = src->u.lazy.lib; + + if (dst_lib->input_idx == src_lib->input_idx) { + //Assert(!"TODO: report duplicate symbols in lib"); } - } - return 0; -} -internal -THREAD_POOL_TASK_FUNC(lnk_symbol_name_hasher) -{ - LNK_SymbolNameHasher *task = raw_task; - Rng1U64 range = task->range_arr[task_id]; - for (U64 symbol_idx = range.min; symbol_idx < range.max; symbol_idx += 1) { - LNK_Symbol *symbol = &task->symbol_arr[symbol_idx]; - task->hash_arr[symbol_idx] = lnk_symbol_table_hash(symbol->name); - } -} + can_replace = dst_lib->input_idx > src_lib->input_idx; + } else if (dst->type == LNK_Symbol_Lazy && (LNK_Symbol_IsDefined(src->type) || src->type == LNK_Symbol_Weak)) { + can_replace = 1; + } else if (dst->type == LNK_Symbol_Weak && LNK_Symbol_IsDefined(src->type)) { + // strong definition found, replace weak symbol + can_replace = 1; + } else if (dst->type == LNK_Symbol_Weak && src->type == LNK_Symbol_Weak) { + B32 is_fallback_same = str8_match(dst->u.weak.fallback_symbol->name, src->u.weak.fallback_symbol->name, 0); + if (!is_fallback_same) { + lnk_error(LNK_Error_MultiplyDefinedSymbol, "multiply defined weak symbol %S, symbol defined in:", src->name); + lnk_supplement_error("%S", dst->obj->path); + lnk_supplement_error("%S", src->obj->path); + } -internal U64 * -lnk_symbol_array_hash(TP_Context *tp, Arena *arena, LNK_Symbol *arr, U64 count) -{ - Temp scratch = scratch_begin(&arena, 1); + if (src->obj && !dst->obj) { + can_replace = 1; + } else if (src->obj && dst->obj) { + can_replace = src->obj->input_idx < dst->obj->input_idx; + } + } else if (LNK_Symbol_IsDefined(dst->type) && LNK_Symbol_IsDefined(src->type)) { + const LNK_DefinedSymbol *dst_defn = &dst->u.defined; + const LNK_DefinedSymbol *src_defn = &src->u.defined; - U64 stride = CeilIntegerDiv(count, tp->worker_count); - Rng1U64 *range_arr = push_array_no_zero(scratch.arena, Rng1U64, tp->worker_count); - for (U64 thread_idx = 0; thread_idx < tp->worker_count; thread_idx += 1) { - Rng1U64 *range = &range_arr[thread_idx]; - range->min = Min(count, stride * thread_idx); - range->max = Min(count, range->min + stride); + if (dst_defn->value_type == LNK_DefinedSymbolValue_Chunk && + src_defn->value_type == LNK_DefinedSymbolValue_Chunk) { + Assert(dst_defn->u.chunk->is_discarded == 0); + Assert(dst_defn->u.chunk->type == LNK_Chunk_Leaf); + Assert(src_defn->u.chunk->type == LNK_Chunk_Leaf); + + // handle communal variable + // + // MSVC CRT relies on this behaviour (e.g. __src_ucrt_dll_is_in_use in ucrt_detection.c) + if (dst_defn->u.chunk->u.leaf.str == 0 && src_defn->u.chunk->u.leaf.size > 0) { + return 1; + } + + COFF_ComdatSelectType dst_select = dst_defn->u.selection; + COFF_ComdatSelectType src_select = src_defn->u.selection; + + // handle objs compiled with /GR- and /GR + if ((src_select == COFF_ComdatSelectType_ANY && dst_select == COFF_ComdatSelectType_LARGEST) || + (src_select == COFF_ComdatSelectType_LARGEST && dst_select == COFF_ComdatSelectType_ANY)) { + dst_select = COFF_ComdatSelectType_LARGEST; + src_select = COFF_ComdatSelectType_LARGEST; + } + + if (src_select == dst_select) { + switch (src_select) { + default: InvalidPath; + case COFF_ComdatSelectType_NULL: + case COFF_ComdatSelectType_ANY: { + LNK_Chunk *dst_chunk = dst_defn->u.chunk; + LNK_Chunk *src_chunk = src_defn->u.chunk; + U64 dst_chunk_size = lnk_chunk_get_size(dst_chunk); + U64 src_chunk_size = lnk_chunk_get_size(src_chunk); + if (src_chunk_size == dst_chunk_size) { + can_replace = src_chunk->input_idx < dst_chunk->input_idx; + } else { + // both COMDATs are valid but to get smaller exe pick smallest + can_replace = src_chunk_size < dst_chunk_size; + } + } break; + case COFF_ComdatSelectType_NODUPLICATES: { + lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src->obj, "multiply defined symbol %S in %S.", dst->name, dst->obj->path); + } break; + case COFF_ComdatSelectType_SAME_SIZE: { + LNK_Chunk *dst_chunk = dst_defn->u.chunk; + LNK_Chunk *src_chunk = src_defn->u.chunk; + U64 dst_chunk_size = lnk_chunk_get_size(dst_chunk); + U64 src_chunk_size = lnk_chunk_get_size(src_chunk); + B32 is_same_size = (dst_chunk_size == src_chunk_size); + if (!is_same_size) { + lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src->obj, "multiply defined symbol %S in %S.", dst->name, dst->obj->path); + } + } break; + case COFF_ComdatSelectType_EXACT_MATCH: { + B32 is_exact_match = (dst_defn->u.check_sum == src_defn->u.check_sum); + if (!is_exact_match) { + lnk_error_obj(LNK_Error_MultiplyDefinedSymbol, src->obj, "multiply defined symbol %S in %S.", dst->name, dst->obj->path); + } + } break; + case COFF_ComdatSelectType_LARGEST: { + LNK_Chunk *dst_chunk = dst_defn->u.chunk; + LNK_Chunk *src_chunk = src_defn->u.chunk; + U64 dst_chunk_size = lnk_chunk_get_size(dst_chunk); + U64 src_chunk_size = lnk_chunk_get_size(src_chunk); + if (dst_chunk_size == src_chunk_size) { + can_replace = src_chunk->input_idx < dst_chunk->input_idx; + } else { + can_replace = dst_chunk_size < src_chunk_size; + } + } break; + case COFF_ComdatSelectType_ASSOCIATIVE: { + // ignore + } break; + } + } else { + String8 src_select_str = coff_string_from_comdat_select_type(src_defn->u.selection); + String8 dst_select_str = coff_string_from_comdat_select_type(dst_defn->u.selection); + lnk_error_obj(LNK_Warning_UnresolvedComdat, src->obj, + "%S: COMDAT selection conflict detected, current selection %S, leader selection %S from %S", + src->name, src_select_str, dst_select_str, dst->obj->path); + } + } else if (dst_defn->value_type == LNK_DefinedSymbolValue_VA && src_defn->value_type == LNK_DefinedSymbolValue_Chunk) { + can_replace = 1; + } else { + InvalidPath; + } + } else { + InvalidPath; } - LNK_SymbolNameHasher hasher_ctx = {0}; - hasher_ctx.symbol_arr = arr; - hasher_ctx.range_arr = range_arr; - hasher_ctx.hash_arr = push_array_no_zero(arena, U64, count); - tp_for_parallel(tp, 0, tp->worker_count, lnk_symbol_name_hasher, &hasher_ctx); - - scratch_end(scratch); - return hasher_ctx.hash_arr; -} - -internal LNK_SymbolTable * -lnk_symbol_table_alloc(void) -{ - return lnk_symbol_table_alloc_ex(0x1000, 0x100, 0x500, 0x1000); -} - -internal LNK_SymbolTable * -lnk_symbol_table_alloc_ex(U64 defined_cap, U64 internal_cap, U64 weak_cap, U64 lib_cap) -{ - ProfBeginDynamic("Alloc Symbol Table [Defined: 0x%llx, Internal: 0x%llx, Weak: 0x%llx, Lib: 0x%llx]", defined_cap, internal_cap, weak_cap, lib_cap); - Arena *arena = arena_alloc(); - LNK_SymbolTable *symtab = push_array(arena, LNK_SymbolTable, 1); - symtab->arena = arena; - symtab->bucket_count[LNK_SymbolScopeIndex_Defined] = defined_cap; - symtab->bucket_count[LNK_SymbolScopeIndex_Internal] = internal_cap; - symtab->bucket_count[LNK_SymbolScopeIndex_Weak] = weak_cap; - symtab->bucket_count[LNK_SymbolScopeIndex_Lib] = lib_cap; - for (U64 iscope = 0; iscope < ArrayCount(symtab->buckets); ++iscope) { - symtab->buckets[iscope] = push_array(symtab->arena, LNK_SymbolList, symtab->bucket_count[iscope]); - } - ProfEnd(); - return symtab; + return can_replace; } internal void -lnk_symbol_table_release(LNK_SymbolTable **symtab) +lnk_on_symbol_replace(LNK_Symbol *dst, LNK_Symbol *src) { - ProfBeginFunction(); - arena_release((*symtab)->arena); - *symtab = 0; - ProfEnd(); -} + Assert(dst != src); -internal U64 -lnk_symbol_table_hash(String8 string) -{ - return hash_from_str8(string); -} + if (dst->type == LNK_Symbol_Lazy && src->type == LNK_Symbol_Lazy) { + dst->u.lazy = src->u.lazy; + } else if (LNK_Symbol_IsDefined(dst->type)) { + LNK_DefinedSymbol *dst_defined = &dst->u.defined; -internal LNK_SymbolNode * -lnk_symbol_table_search_bucket(LNK_SymbolTable *symtab, LNK_SymbolScopeIndex scope_idx, U64 bucket_idx, String8 name, U64 hash) -{ - for (LNK_SymbolNode *node = symtab->buckets[scope_idx][bucket_idx].first; node != 0; node = node->next) { - if (hash == node->hash && str8_match(node->data->name, name, 0)) { - return node; + if (dst_defined->value_type == LNK_DefinedSymbolValue_Chunk) { + // discard chunk from output + dst_defined->u.chunk->is_discarded = 1; + + if (LNK_Symbol_IsDefined(src->type)) { + LNK_DefinedSymbol *src_defined = &src->u.defined; + + if (src_defined->value_type == LNK_DefinedSymbolValue_Chunk) { + // static symbols that are not part of obj's symbol table might point to discarded chunk + dst_defined->u.chunk->ref = src_defined->u.chunk->ref; + + // copy offset because after folding COMDATS we might end + // up with larger sized chunk and, for instance, a vftable + // might have a function pointer preceeding lead symbol + dst_defined->u.chunk = src_defined->u.chunk; + dst_defined->u.chunk_offset = src_defined->u.chunk_offset; + } + } else { + InvalidPath; + } } } - return 0; } -internal LNK_SymbolNode * -lnk_symbol_table_search_node_hash(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope_flags, String8 name, U64 hash) +internal void +lnk_symbol_hash_trie_insert_or_replace(Arena *arena, LNK_SymbolHashTrieChunkList *chunk_list, LNK_SymbolHashTrie **trie, U64 hash, LNK_Symbol *new_symbol) { - while (scope_flags) { - LNK_SymbolScopeIndex scope_idx = ctz64(scope_flags); - scope_flags &= scope_flags - 1; - U64 bucket_idx = hash % symtab->bucket_count[scope_idx]; - LNK_SymbolNode *node = lnk_symbol_table_search_bucket(symtab, scope_idx, bucket_idx, name, hash); - if (node) return node; + LNK_SymbolHashTrie **curr_trie_ptr = trie; + + for (U64 h = hash; ; h <<= 2) { + // load current pointer + LNK_SymbolHashTrie *curr_trie = ins_atomic_ptr_eval(curr_trie_ptr); + + if (curr_trie == 0) { + // init node + LNK_SymbolHashTrie *new_trie = lnk_symbol_hash_trie_chunk_list_push(arena, chunk_list, 512); + new_trie->name = &new_symbol->name; + new_trie->symbol = new_symbol; + MemoryZeroArray(new_trie->child); + + // try to insert new node + LNK_SymbolHashTrie *cmp = ins_atomic_ptr_eval_cond_assign(curr_trie_ptr, new_trie, curr_trie); + + // was symbol inserted? + if (cmp == curr_trie) { + break; + } + + // rollback chunk list push + chunk_list->last->count -= 1; + + // retry insert with trie node from another thread + curr_trie = cmp; + } + + // load current symbol + String8 *curr_name = ins_atomic_ptr_eval(&curr_trie->name); + + if (curr_name) { + if (str8_match(*curr_name, new_symbol->name, 0)) { + for (LNK_Symbol *src = new_symbol, *dst;;) { + LNK_Symbol *dst = ins_atomic_ptr_eval_assign(&curr_trie->symbol, 0); + + if (dst) { + if (lnk_can_replace_symbol(dst, src)) { + // HACK: patch dst because relocations might point to it + lnk_on_symbol_replace(dst, src); + + // swap + dst = src; + } else { + // discard source + lnk_on_symbol_replace(src, dst); + } + } + + // try insert back symbol + dst = ins_atomic_ptr_eval_cond_assign(&curr_trie->symbol, src, 0); + + if (dst == 0) { + break; + } + } + + break; + } + } + + // descend + curr_trie_ptr = curr_trie->child + (h >> 62); } - return 0; } -internal LNK_SymbolNode * -lnk_symbol_table_search_node(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope_flags, String8 name) +internal LNK_SymbolHashTrie * +lnk_symbol_hash_trie_search(LNK_SymbolHashTrie *trie, U64 hash, String8 name) { - U64 hash = lnk_symbol_table_hash(name); - return lnk_symbol_table_search_node_hash(symtab, scope_flags, name, hash); + LNK_SymbolHashTrie *result = 0; + LNK_SymbolHashTrie **curr_ptr = ≜ + for (U64 h = hash; ; h <<= 2) { + LNK_SymbolHashTrie *curr = ins_atomic_ptr_eval(curr_ptr); + if (curr == 0) { + break; + } + if (curr->symbol) { + if (str8_match(curr->symbol->name, name, 0)) { + result = curr; + break; + } + } + curr_ptr = curr->child + (h >> 62); + } + return result; +} + +internal void +lnk_symbol_hash_trie_remove(LNK_SymbolHashTrie *trie) +{ + ins_atomic_ptr_eval_assign(&trie->name, 0); + ins_atomic_ptr_eval_assign(&trie->symbol, 0); +} + +//////////////////////////////// + +internal U64 +lnk_symbol_hash(String8 string) +{ + XXH3_state_t hasher; XXH3_64bits_reset(&hasher); + XXH3_64bits_update(&hasher, &string.size, sizeof(string.size)); + XXH3_64bits_update(&hasher, string.str, string.size); + XXH64_hash_t result = XXH3_64bits_digest(&hasher); + return result; +} + +internal LNK_SymbolTable * +lnk_symbol_table_init(TP_Arena *arena) +{ + LNK_SymbolTable *symtab = push_array(arena->v[0], LNK_SymbolTable, 1); + symtab->arena = arena; + for (U64 i = 0; i < LNK_SymbolScopeIndex_Count; ++i) { + symtab->chunk_lists[i] = push_array(arena->v[0], LNK_SymbolHashTrieChunkList, arena->count); + } + return symtab; } internal LNK_Symbol * -lnk_symbol_table_search(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope_flags, String8 name) +lnk_symbol_table_search_hash(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope_flags, U64 hash, String8 name) { - LNK_SymbolNode *node = lnk_symbol_table_search_node(symtab, scope_flags, name); - return node ? node->data : 0; + LNK_Symbol *result = 0; + while (scope_flags) { + LNK_SymbolScopeIndex scope_idx = ctz64(scope_flags); + scope_flags &= scope_flags - 1; + + LNK_SymbolHashTrie *match = lnk_symbol_hash_trie_search(symtab->scopes[scope_idx], hash, name); + if (match) { + result = match->symbol; + break; + } + } + return result; +} + +internal LNK_Symbol * +lnk_symbol_table_search(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope, String8 name) +{ + U64 hash = lnk_symbol_hash(name); + return lnk_symbol_table_search_hash(symtab, scope, hash, name); } internal LNK_Symbol * @@ -452,75 +545,37 @@ lnk_symbol_table_searchf(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope_fla va_end(args); LNK_Symbol *symbol = lnk_symbol_table_search(symtab, scope_flags, name); + scratch_end(scratch); return symbol; } internal void -lnk_symbol_table_remove(LNK_SymbolTable *symtab, LNK_SymbolScopeIndex scope, String8 name) +lnk_symbol_table_push_(LNK_SymbolTable *symtab, Arena *arena, LNK_SymbolHashTrieChunkList *chunk_list, LNK_SymbolScopeIndex scope_idx, U64 hash, LNK_Symbol *symbol) { - U64 hash = lnk_symbol_table_hash(name); - U64 ibucket = hash % symtab->bucket_count[scope]; - for (;;) { - LNK_SymbolNode *node = lnk_symbol_table_search_bucket(symtab, scope, ibucket, name, hash); - if (!node) { - break; - } - LNK_SymbolList *bucket = &symtab->buckets[scope][ibucket]; - DLLRemove(bucket->first, bucket->last, node); - bucket->count -= 1; - } -} - -internal LNK_SymbolList * -lnk_symbol_table_bucket_from_hash(LNK_SymbolTable *symtab, LNK_SymbolScopeIndex scope_idx, U64 hash) -{ - U64 bucket_idx = hash % symtab->bucket_count[scope_idx]; - LNK_SymbolList *bucket = &symtab->buckets[scope_idx][bucket_idx]; - return bucket; + lnk_symbol_hash_trie_insert_or_replace(arena, chunk_list, &symtab->scopes[scope_idx], hash, symbol); } internal void -lnk_symbol_table_push_(LNK_SymbolTable *symtab, LNK_SymbolScopeIndex scope_idx, LNK_SymbolNode *node, U64 hash) +lnk_symbol_table_push_hash(LNK_SymbolTable *symtab, U64 hash, LNK_Symbol *symbol) { - LNK_SymbolList *bucket = lnk_symbol_table_bucket_from_hash(symtab, scope_idx, hash); - node->hash = hash; - lnk_symbol_list_push_node(bucket, node); -} - -internal void -lnk_symbol_table_push_node_hash(LNK_SymbolTable *symtab, LNK_SymbolNode *node, U64 hash) -{ - switch (node->data->type) { + switch (symbol->type) { case LNK_Symbol_Null: break; case LNK_Symbol_DefinedExtern: { - lnk_symbol_table_push_(symtab, LNK_SymbolScopeIndex_Defined, node, hash); + lnk_symbol_table_push_(symtab, symtab->arena->v[0], &symtab->chunk_lists[LNK_SymbolScopeIndex_Defined][0], LNK_SymbolScopeIndex_Defined, hash, symbol); } break; + case LNK_Symbol_DefinedInternal: { - lnk_symbol_table_push_(symtab, LNK_SymbolScopeIndex_Internal, node, hash); + lnk_symbol_table_push_(symtab, symtab->arena->v[0], &symtab->chunk_lists[LNK_SymbolScopeIndex_Internal][0], LNK_SymbolScopeIndex_Internal, hash, symbol); } break; + case LNK_Symbol_Weak: { - LNK_SymbolNode *is_strong_defn_present = lnk_symbol_table_search_node(symtab, LNK_SymbolScopeFlag_Defined, node->data->name); - if (is_strong_defn_present) { - break; - } - - LNK_SymbolNode *is_weak_present = lnk_symbol_table_search_node(symtab, LNK_SymbolScopeFlag_Weak, node->data->name); - if (is_weak_present) { - B32 is_fallback_same = str8_match(is_weak_present->data->u.weak.fallback_symbol->name, node->data->u.weak.fallback_symbol->name, 0); - if (!is_fallback_same) { - lnk_error(LNK_Error_MultiplyDefinedSymbol, "Weak symbol %S conflict detected, symbol defined in:", node->data->name); - lnk_supplement_error("%S", node->data->debug); - lnk_supplement_error("%S", is_weak_present->data->debug); - } - break; - } - - lnk_symbol_table_push_(symtab, LNK_SymbolScopeIndex_Weak, node, hash); + lnk_symbol_table_push_(symtab, symtab->arena->v[0], &symtab->chunk_lists[LNK_SymbolScopeIndex_Weak][0], LNK_SymbolScopeIndex_Weak, hash, symbol); } break; + case LNK_Symbol_Lazy: { - lnk_symbol_table_push_(symtab, LNK_SymbolScopeIndex_Lib, node, hash); + lnk_symbol_table_push_(symtab, symtab->arena->v[0], &symtab->chunk_lists[LNK_SymbolScopeIndex_Lib][0], LNK_SymbolScopeIndex_Lib, hash, symbol); } break; // symbols not supported @@ -532,80 +587,55 @@ lnk_symbol_table_push_node_hash(LNK_SymbolTable *symtab, LNK_SymbolNode *node, U } internal void -lnk_symbol_table_push_node(LNK_SymbolTable *symtab, LNK_SymbolNode *node) -{ - U64 hash = lnk_symbol_table_hash(node->data->name); - lnk_symbol_table_push_node_hash(symtab, node, hash); -} - -internal LNK_SymbolNode * lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_Symbol *symbol) { - LNK_SymbolNode *node = push_array(symtab->arena, LNK_SymbolNode, 1); - node->data = symbol; - lnk_symbol_table_push_node(symtab, node); - return node; -} - -internal -THREAD_POOL_TASK_FUNC(lnk_lazy_symbol_inserter) -{ - LNK_LazySymbolInserter *task = raw_task; - LNK_SymbolTable *symtab = task->symtab; - Rng1U64 range = task->range_arr[task_id]; - for (U64 bucket_idx = range.min; bucket_idx < range.max; bucket_idx += 1) { - LNK_SymbolList *bucket = &task->bucket_arr[bucket_idx]; - for (LNK_SymbolNode *curr = bucket->first, *next; curr != 0; curr = next) { - next = curr->next; - lnk_symbol_table_push_(symtab, LNK_SymbolScopeIndex_Lib, curr, curr->hash); - } - } + U64 hash = lnk_symbol_hash(symbol->name); + lnk_symbol_table_push_hash(symtab, hash, symbol); } internal void -lnk_symbol_table_push_lazy_arr(TP_Context *tp, LNK_SymbolTable *symtab, LNK_Symbol *arr, U64 count) +lnk_symbol_table_remove(LNK_SymbolTable *symtab, LNK_SymbolScopeIndex scope, String8 name) { - Temp scratch = scratch_begin(0,0); - - ProfBegin("Push Symbol Nodes"); - LNK_SymbolNode *node_arr = push_array_no_zero(symtab->arena, LNK_SymbolNode, count); - for (U64 symbol_idx = 0; symbol_idx < count; symbol_idx += 1) { - LNK_SymbolNode *node = &node_arr[symbol_idx]; - node->prev = node->next = 0; - node->data = &arr[symbol_idx]; + U64 hash = lnk_symbol_hash(name); + LNK_SymbolHashTrie *trie = lnk_symbol_hash_trie_search(symtab->scopes[scope], hash, name); + if (trie) { + lnk_symbol_hash_trie_remove(trie); } - ProfEnd(); - - ProfBegin("Hash Symbol Names"); - lnk_symbol_node_array_hash(tp, node_arr, count); - ProfEnd(); - - ProfBegin("Populate Buckets"); - LNK_SymbolList *bucket_arr = push_array(scratch.arena, LNK_SymbolList, symtab->bucket_count[LNK_SymbolScopeIndex_Lib]); - for (U64 symbol_idx = 0; symbol_idx < count; symbol_idx += 1) { - LNK_SymbolNode *symbol_node = &node_arr[symbol_idx]; - U64 bucket_idx = symbol_node->hash % symtab->bucket_count[LNK_SymbolScopeIndex_Lib]; - lnk_symbol_list_push_node(&bucket_arr[bucket_idx], symbol_node); - } - ProfEnd(); - - ProfBegin("Update Symbol Table"); - LNK_LazySymbolInserter symbol_inserter; - symbol_inserter.symtab = symtab; - symbol_inserter.bucket_arr = bucket_arr; - symbol_inserter.range_arr = tp_divide_work(scratch.arena, symtab->bucket_count[LNK_SymbolScopeIndex_Lib], tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, lnk_lazy_symbol_inserter, &symbol_inserter); - ProfEnd(); - - scratch_end(scratch); } -internal void -lnk_symbol_table_push_list(LNK_SymbolTable *symtab, LNK_SymbolList *list) +internal LNK_Symbol * +lnk_symbol_table_push_defined_chunk(LNK_SymbolTable *symtab, String8 name, LNK_DefinedSymbolVisibility visibility, LNK_DefinedSymbolFlags flags, LNK_Chunk *chunk, U64 offset, COFF_ComdatSelectType selection, U32 check_sum) { - ProfBeginFunction(); - MemoryZeroStruct(list); - ProfEnd(); + LNK_Symbol *symbol = lnk_make_defined_symbol_chunk(symtab->arena->v[0], name, visibility, flags, chunk, offset, selection, check_sum); + lnk_symbol_table_push(symtab, symbol); + return symbol; +} + +internal LNK_Symbol * +lnk_symbol_table_push_defined(LNK_SymbolTable *symtab, String8 name, LNK_DefinedSymbolVisibility visibility, LNK_DefinedSymbolFlags flags) +{ + LNK_Symbol *symbol = lnk_make_defined_symbol(symtab->arena->v[0], name, visibility, flags); + lnk_symbol_table_push(symtab, symbol); + return symbol; +} + +internal LNK_Symbol * +lnk_symbol_table_push_defined_va(LNK_SymbolTable *symtab, String8 name, LNK_DefinedSymbolVisibility visibility, LNK_DefinedSymbolFlags flags, U64 va) +{ + LNK_Symbol *symbol = lnk_make_defined_symbol_va(symtab->arena->v[0], name, visibility, flags, va); + lnk_symbol_table_push(symtab, symbol); + return symbol; +} + +internal LNK_Symbol * +lnk_symbol_table_push_weak(LNK_SymbolTable *symtab, String8 weak_name, COFF_WeakExtType lookup, String8 strong_name) +{ + weak_name = push_str8_copy(symtab->arena->v[0], weak_name); + strong_name = push_str8_copy(symtab->arena->v[0], strong_name); + LNK_Symbol *strong_symbol = lnk_make_undefined_symbol(symtab->arena->v[0], strong_name, LNK_SymbolScopeFlag_Main); + LNK_Symbol *weak_symbol = lnk_make_weak_symbol(symtab->arena->v[0], weak_name, COFF_WeakExtType_SEARCH_ALIAS, strong_symbol); + lnk_symbol_table_push(symtab, weak_symbol); + return weak_symbol; } internal LNK_Symbol * @@ -636,10 +666,15 @@ lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_Symbol *resolve_symbol) } run_resolver = 1; } break; + case LNK_Symbol_DefinedExtern: { + // search for defined symbol because we don't update symbol pointers in relocations + // whenver we replace them in the symbol table + symbol = lnk_symbol_table_search(symtab, LNK_SymbolScopeFlag_Defined, symbol->name); + Assert(symbol); + } break; case LNK_Symbol_DefinedStatic: - case LNK_Symbol_DefinedExtern: case LNK_Symbol_DefinedInternal: { - /* resolved */ + // symbol resolved } break; default: NotImplemented; } @@ -647,186 +682,62 @@ lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_Symbol *resolve_symbol) return symbol; } -internal LNK_SymbolList -lnk_pop_comdat_chain(LNK_SymbolList *bucket, LNK_SymbolNode **cursor) -{ - LNK_SymbolList chain_list = {0}; - - LNK_SymbolNode *leader_node = *cursor; - *cursor = (*cursor)->next; - - lnk_symbol_list_remove(bucket, leader_node); - lnk_symbol_list_push_node(&chain_list, leader_node); - - while (*cursor) { - LNK_SymbolNode *next = (*cursor)->next; - - // symbols with identical names are stored in order - if (!str8_match(leader_node->data->name, (*cursor)->data->name, 0)) { - break; - } - - // move node to chain list - lnk_symbol_list_remove(bucket, *cursor); - lnk_symbol_list_push_node(&chain_list, *cursor); - - // advance - *cursor = next; - } - - return chain_list; -} - -internal LNK_SymbolNode * -lnk_fold_comdat_chain(LNK_SymbolList chain_list) -{ - LNK_SymbolNode *lead_node = chain_list.first; - - if (LNK_Symbol_IsDefined(lead_node->data->type)) { - LNK_Symbol *lead = lead_node->data; - if (lead->u.defined.value_type != LNK_DefinedSymbolValue_Chunk && chain_list.count > 1) { - lnk_error(LNK_Error_MultiplyDefinedSymbol, "Unable to perfrom COMDAT fold on symbol %S, symbol must reference a section, defined in %S", - lead->name, lead->debug); - return 0; - } - } - - for (LNK_SymbolNode *curr_node = lead_node->next; curr_node != 0; curr_node = curr_node->next) { - Assert(LNK_Symbol_IsDefined(lead_node->data->type)); - Assert(LNK_Symbol_IsDefined(curr_node->data->type)); - - LNK_DefinedSymbol *lead_defined = &lead_node->data->u.defined; - LNK_DefinedSymbol *curr_defined = &curr_node->data->u.defined; - - if (curr_defined->value_type != LNK_DefinedSymbolValue_Chunk) { - lnk_error(LNK_Error_MultiplyDefinedSymbol, "Unable to perfrom COMDAT fold on symbol %S, symbol must reference a section, defined in %S", - curr_node->data->name, curr_node->data->debug); - return 0; - } - - // There is no mentioning of this rule in PE spec, but according to comment from lld-link in 'handleComdatSelection': - // "cl.exe picks "any" for vftabels when building with /GR- and "largest" when building /GR.". However, - // chromium links '__src_ucrt_dll_is_in_use' from MSVCRT which is not a vftable but still requires selection override. - if ((curr_defined->u.selection == COFF_ComdatSelectType_ANY && lead_defined->u.selection == COFF_ComdatSelectType_LARGEST) || - (curr_defined->u.selection == COFF_ComdatSelectType_LARGEST && lead_defined->u.selection == COFF_ComdatSelectType_ANY)) { - lead_defined->u.selection = COFF_ComdatSelectType_LARGEST; - curr_defined->u.selection = COFF_ComdatSelectType_LARGEST; - } - - // COMDATs must have same selection rule - if (lead_defined->u.selection != curr_defined->u.selection) { - String8 curr_selection_str = coff_string_from_comdat_select_type(curr_defined->u.selection); - String8 lead_selection_str = coff_string_from_comdat_select_type(lead_defined->u.selection); - lnk_error(LNK_Warning_UnresolvedComdat, - "COMDAT selection conflict detected in symbol %S defined in %S (%S), leader selection %S from %S", - curr_node->data->name, curr_node->data->debug, curr_selection_str, lead_selection_str, lead_node->data->debug); - return 0; - } - - switch (curr_defined->u.selection) { - case COFF_ComdatSelectType_NULL: - case COFF_ComdatSelectType_ANY: { - // both COMDATs are valid but to get smaller exe pick smallest - LNK_Chunk *lead_chunk = lead_defined->u.chunk; - LNK_Chunk *curr_chunk = curr_defined->u.chunk; - U64 lead_chunk_size = lnk_chunk_get_size(lead_chunk); - U64 curr_chunk_size = lnk_chunk_get_size(curr_chunk); - if (curr_chunk_size < lead_chunk_size) { - lead_node = curr_node; - } - } break; - case COFF_ComdatSelectType_NODUPLICATES: { - lnk_error(LNK_Error_MultiplyDefinedSymbol, "%S: error: multiply defined symbol %S in %S.", curr_node->data->debug, curr_node->data->name, lead_node->data->debug); - } break; - case COFF_ComdatSelectType_SAME_SIZE: { - LNK_Chunk *lead_chunk = lead_defined->u.chunk; - LNK_Chunk *curr_chunk = curr_defined->u.chunk; - U64 lead_chunk_size = lnk_chunk_get_size(lead_chunk); - U64 curr_chunk_size = lnk_chunk_get_size(curr_chunk); - B32 is_same_size = (lead_chunk_size == curr_chunk_size); - if (!is_same_size) { - lnk_error(LNK_Error_MultiplyDefinedSymbol, "%S: error: multiply defined symbol %S in %S.", curr_node->data->debug, curr_node->data->name, lead_node->data->debug); - } - } break; - case COFF_ComdatSelectType_EXACT_MATCH: { - B32 is_exact_match = (lead_defined->u.check_sum == curr_defined->u.check_sum); - if (!is_exact_match) { - lnk_error(LNK_Error_MultiplyDefinedSymbol, "%S: error: multiply defined symbol %S in %S.", curr_node->data->debug, curr_node->data->name, lead_node->data->debug); - } - } break; - case COFF_ComdatSelectType_LARGEST: { - LNK_Chunk *lead_chunk = lead_defined->u.chunk; - LNK_Chunk *curr_chunk = curr_defined->u.chunk; - U64 lead_chunk_size = lnk_chunk_get_size(lead_chunk); - U64 curr_chunk_size = lnk_chunk_get_size(curr_chunk); - if (lead_chunk_size > curr_chunk_size) { - lead_node = curr_node; - } - } break; - case COFF_ComdatSelectType_ASSOCIATIVE: { - // ignore - } break; - } - } - - // rewire chunks so they point to COMDAT leader - for (LNK_SymbolNode *curr_node = chain_list.first; curr_node != 0; curr_node = curr_node->next) { - if (curr_node == lead_node) { - continue; - } - - LNK_DefinedSymbol *curr_defined = &curr_node->data->u.defined; - LNK_Chunk *curr_chunk = curr_defined->u.chunk; - - // copy offset because after folding COMDATS we might end - // up with larger sized chunk and, for instance, a vftable - // might have a function pointer preceeding lead symbol - curr_defined->u.chunk = lead_node->data->u.defined.u.chunk; - curr_defined->u.chunk_offset = lead_node->data->u.defined.u.chunk_offset; - - // discard chunk from output - curr_chunk->is_discarded = 1; - - // static symbols that are not part of obj's symbol table might point to discarded chunk - curr_chunk->ref = lead_node->data->u.defined.u.chunk->ref; - } - - return lead_node; -} - -internal -THREAD_POOL_TASK_FUNC(lnk_comdat_folder) -{ - LNK_ComdatFolder *task = raw_task; - LNK_SymbolTable *symtab = task->symtab; - Rng1U64 range = task->range_arr[task_id]; - for (U64 bucket_idx = range.min; bucket_idx < range.max; ++bucket_idx) { - LNK_SymbolList *bucket = &symtab->buckets[LNK_SymbolScopeIndex_Defined][bucket_idx]; - LNK_SymbolList leader_list = {0}; - LNK_SymbolNode *curr = bucket->first; - while (curr) { - LNK_SymbolList chain_list = lnk_pop_comdat_chain(bucket, &curr); - LNK_SymbolNode *leader_node = lnk_fold_comdat_chain(chain_list); - if (leader_node) { - lnk_symbol_list_push_node(&leader_list, leader_node); - } - } - Assert(bucket->count == 0); - *bucket = leader_list; - } -} +#if 0 internal void -lnk_fold_comdat_chunks(TP_Context *tp, LNK_SymbolTable *symtab) +lnk_symbol_hash_trie_debug(LNK_SymbolHashTrie *root) { - ProfBeginFunction(); - Temp scratch = scratch_begin(0, 0); + Temp scratch = scratch_begin(0,0); - LNK_ComdatFolder folder = {0}; - folder.symtab = symtab; - folder.range_arr = tp_divide_work(scratch.arena, symtab->bucket_count[LNK_SymbolScopeIndex_Defined], tp->worker_count); - tp_for_parallel(tp, 0, tp->worker_count, lnk_comdat_folder, &folder); + struct Stack { + struct Stack *next; + U64 i; + LNK_SymbolHashTrie *trie; + }; + + struct Stack *stack = push_array(scratch.arena, struct Stack, 1); + stack->i = 0; + stack->trie = root; + + U64 cur_depth = 1; + U64 max_depth = 0; + + char *dashes = "--------------------------------"; + + FILE *f = fopen("trie.txt", "w"); + + while (stack) { + for (; stack->i < ArrayCount(stack->trie->child); ++stack->i) { + + if (stack->i == 0 && stack->trie->symbol) { + fprintf(f, "%.*s%.*s\n", (int)cur_depth, dashes, str8_varg(stack->trie->symbol->name)); + } + + if (stack->trie->child[stack->i] != 0) { + struct Stack *frame = push_array(scratch.arena, struct Stack, 1); + frame->i = 0; + frame->trie = stack->trie->child[stack->i]; + + stack->i += 1; + SLLStackPush(stack, frame); + + cur_depth += 1; + max_depth = Max(cur_depth, max_depth); + + break; + } + } + + if (stack->i >= ArrayCount(stack->trie->child)) { + cur_depth -= 1; + SLLStackPop(stack); + } + } + + fprintf(f, "Max Depth: %llu\n", max_depth); + fclose(f); scratch_end(scratch); - ProfEnd(); } + +#endif diff --git a/src/linker/lnk_symbol_table.h b/src/linker/lnk_symbol_table.h index 4c68996c..e91403df 100644 --- a/src/linker/lnk_symbol_table.h +++ b/src/linker/lnk_symbol_table.h @@ -90,27 +90,22 @@ typedef enum LNK_Symbol_Undefined, } LNK_SymbolType; -#define LNK_DEBUG_SYMBOLS 1 typedef struct LNK_Symbol { - String8 name; - LNK_SymbolType type; + String8 name; + LNK_SymbolType type; + struct LNK_Obj *obj; union { LNK_DefinedSymbol defined; LNK_WeakSymbol weak; LNK_UndefinedSymbol undefined; LNK_LazySymbol lazy; } u; -#if LNK_DEBUG_SYMBOLS - String8 debug; -#endif } LNK_Symbol; typedef struct LNK_SymbolNode { struct LNK_SymbolNode *next; - struct LNK_SymbolNode *prev; - U64 hash; LNK_Symbol *data; } LNK_SymbolNode; @@ -133,55 +128,45 @@ typedef struct LNK_SymbolArray LNK_Symbol *v; } LNK_SymbolArray; +typedef struct LNK_SymbolHashTrie +{ + String8 *name; + LNK_Symbol *symbol; + struct LNK_SymbolHashTrie *child[4]; +} LNK_SymbolHashTrie; + +typedef struct LNK_SymbolHashTrieChunk +{ + struct LNK_SymbolHashTrieChunk *next; + U64 count; + U64 cap; + LNK_SymbolHashTrie *v; +} LNK_SymbolHashTrieChunk; + +typedef struct LNK_SymbolHashTrieChunkList +{ + U64 count; + LNK_SymbolHashTrieChunk *first; + LNK_SymbolHashTrieChunk *last; +} LNK_SymbolHashTrieChunkList; + typedef struct LNK_SymbolTable { - Arena *arena; - U64 bucket_count[LNK_SymbolScopeIndex_Count]; - LNK_SymbolList *buckets[LNK_SymbolScopeIndex_Count]; + TP_Arena *arena; + LNK_SymbolHashTrie *scopes[LNK_SymbolScopeIndex_Count]; + LNK_SymbolHashTrieChunkList *chunk_lists[LNK_SymbolScopeIndex_Count]; } LNK_SymbolTable; //////////////////////////////// // parallel for wrappers -typedef struct -{ - LNK_Symbol *symbol_arr; - Rng1U64 *range_arr; - U64 *hash_arr; -} LNK_SymbolNameHasher; - -typedef struct -{ - LNK_SymbolNode **input_arr; - Rng1U64 *range_arr; -} LNK_SymbolNodePtrHasher; - -typedef struct -{ - LNK_SymbolNode *input_arr; - Rng1U64 *range_arr; -} LNK_SymbolNodeHasher; - typedef struct { LNK_SymbolTable *symtab; - LNK_SymbolList *bucket_arr; - Rng1U64 *range_arr; -} LNK_DefinedSymbolInserter; - -typedef struct -{ - LNK_SymbolTable *symtab; - LNK_SymbolList *bucket_arr; - Rng1U64 *range_arr; + Rng1U64 *ranges; + LNK_Symbol *arr; } LNK_LazySymbolInserter; -typedef struct -{ - LNK_SymbolTable *symtab; - Rng1U64 *range_arr; -} LNK_ComdatFolder; - //////////////////////////////// extern LNK_Symbol g_null_symbol; @@ -201,53 +186,34 @@ internal LNK_Symbol * lnk_make_undefined_symbol(Arena *arena, String8 name, LNK_ internal LNK_Symbol * lnk_make_weak_symbol(Arena *arena, String8 name, COFF_WeakExtType lookup, LNK_Symbol *fallback); internal LNK_Symbol * lnk_make_lazy_symbol(Arena *arena, String8 name, struct LNK_Lib *lib, U64 member_offset); -#if LNK_DEBUG_SYMBOLS -#define lnk_symbol_set_debugf(a, s, fmt, ...) do { (s)->debug = push_str8f((a), fmt, __VA_ARGS__); } while (0) -#define lnk_symbol_set_debug(s, str) do { (s)->debug = str; } while (0) -#else -#define lnk_symbol_set_debugf(...) -#define lnk_symbol_set_debug(...) -#endif +internal LNK_Chunk * lnk_chunk_from_symbol(LNK_Symbol *symbol); -internal LNK_Chunk * lnk_defined_symbol_get_chunk(LNK_DefinedSymbol *symbol); - -internal void lnk_symbol_update_chunk_ref(LNK_Symbol *symbol, U64 src_sect_id, U64 dst_sect_id, U64 *id_map, U64 id_count); +//////////////////////////////// internal void lnk_symbol_list_push_node(LNK_SymbolList *list, LNK_SymbolNode *node); internal LNK_SymbolNode * lnk_symbol_list_push(Arena *arena, LNK_SymbolList *list, LNK_Symbol *symbol); -internal void lnk_symbol_list_push_list(LNK_SymbolList *list, LNK_SymbolList *to_push); -internal void lnk_symbol_list_insert_after(LNK_SymbolList *list, LNK_SymbolNode *node, LNK_SymbolNode *insert); -internal LNK_SymbolNode * lnk_symbol_list_pop_node(LNK_SymbolList *list); -internal LNK_Symbol * lnk_symbol_list_pop(LNK_SymbolList *list); -internal void lnk_symbol_list_remove(LNK_SymbolList *list, LNK_SymbolNode *node); internal void lnk_symbol_list_concat_in_place(LNK_SymbolList *list, LNK_SymbolList *to_concat); -internal LNK_SymbolNodeArray lnk_symbol_node_array_from_list(Arena *arena, LNK_SymbolList list); - internal LNK_SymbolList lnk_symbol_list_from_array(Arena *arena, LNK_SymbolArray arr); internal LNK_SymbolNodeArray lnk_symbol_node_array_from_list(Arena *arena, LNK_SymbolList list); internal LNK_SymbolArray lnk_symbol_array_from_list(Arena *arena, LNK_SymbolList list); -internal LNK_Symbol * lnk_symbol_array_search(LNK_SymbolArray symarr, String8 name, StringMatchFlags flags); -internal U64 * lnk_symbol_array_hash(TP_Context *tp, Arena *arena, LNK_Symbol *arr, U64 count); -internal LNK_SymbolTable * lnk_symbol_table_alloc(void); -internal LNK_SymbolTable * lnk_symbol_table_alloc_ex(U64 defined_cap, U64 internal_cap, U64 weak_cap, U64 lib_cap); -internal void lnk_symbol_table_release(LNK_SymbolTable **symtab); -internal U64 lnk_symbol_table_hash(String8 string); -internal LNK_SymbolNode * lnk_symbol_table_search_bucket(LNK_SymbolTable *symtab, LNK_SymbolScopeIndex scope_idx, U64 bucket_idx, String8 name, U64 hash); -internal LNK_SymbolNode * lnk_symbol_table_search_node_hash(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope_flags, String8 name, U64 hash); -internal LNK_SymbolNode * lnk_symbol_table_search_node(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope, String8 name); -internal LNK_Symbol * lnk_symbol_table_search(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope_flags, String8 name); -internal LNK_Symbol * lnk_symbol_table_searchf(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope_flags, char *fmt, ...); -internal void lnk_symbol_table_push_node_hash(LNK_SymbolTable *symtab, LNK_SymbolNode *node, U64 hash); -internal void lnk_symbol_table_push_node(LNK_SymbolTable *symtab, LNK_SymbolNode *node); -internal LNK_SymbolNode * lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_Symbol *symbol); -internal void lnk_symbol_table_push_lazy_arr(TP_Context *tp, LNK_SymbolTable *symtab, LNK_Symbol *arr, U64 count); +//////////////////////////////// + +internal void lnk_symbol_hash_trie_insert_or_replace(Arena *arena, LNK_SymbolHashTrieChunkList *chunk_list, LNK_SymbolHashTrie **trie, U64 hash, LNK_Symbol *new_symbol); +internal LNK_SymbolHashTrie * lnk_symbol_hash_trie_search(LNK_SymbolHashTrie *trie, U64 hash, String8 name); +internal void lnk_symbol_hash_trie_remove(LNK_SymbolHashTrie *trie); + +//////////////////////////////// + +internal U64 lnk_symbol_hash(String8 string); + +internal LNK_SymbolTable * lnk_symbol_table_init(TP_Arena *arena); +internal LNK_Symbol * lnk_symbol_table_search_hash(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope, U64 hash, String8 name); +internal LNK_Symbol * lnk_symbol_table_search(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope, String8 name); +internal LNK_Symbol * lnk_symbol_table_searchf(LNK_SymbolTable *symtab, LNK_SymbolScopeFlags scope, char *fmt, ...); +internal void lnk_symbol_table_push_hash(LNK_SymbolTable *symtab, U64 hash, LNK_Symbol *symbol); +internal void lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_Symbol *symbol); internal void lnk_symbol_table_remove(LNK_SymbolTable *symtab, LNK_SymbolScopeIndex scope, String8 name); -internal void lnk_symbol_table_replace(LNK_SymbolTable *symtab, LNK_SymbolScopeIndex iscope, LNK_Symbol *symbol); internal LNK_Symbol * lnk_resolve_symbol(LNK_SymbolTable *symtab, LNK_Symbol *resolve_symbol); -internal LNK_SymbolList lnk_pop_comdat_chain(LNK_SymbolList *bucket, LNK_SymbolNode **cursor); -internal LNK_SymbolNode * lnk_fold_comdat_chain(LNK_SymbolList chain_list); -internal void lnk_fold_comdat_chunks(TP_Context *tp, LNK_SymbolTable *symtab); -