From f0a967a15d7a8af7784354df8397f33f105c4d24 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Wed, 21 May 2025 15:36:29 -0700 Subject: [PATCH] don't create BIAT and UIAT sections when not requested --- src/base/base_core.c | 23 +++++++++ src/base/base_core.h | 5 ++ src/linker/lnk.c | 9 ++-- src/pe/pe.c | 89 ++++++++++++++++------------------- src/pe/pe_make_import_table.c | 10 ++-- 5 files changed, 80 insertions(+), 56 deletions(-) diff --git a/src/base/base_core.c b/src/base/base_core.c index 0b8c1ec8..e982b684 100644 --- a/src/base/base_core.c +++ b/src/base/base_core.c @@ -636,3 +636,26 @@ u64_array_bsearch(U64 *arr, U64 count, U64 value) return max_U64; } +//////////////////////////////// + +internal U64 +index_of_zero_u32(U32 *ptr, U64 count) +{ + for (U64 i = 0; i < count; i += 1) { + if (ptr[i] == 0) { + return i; + } + } + return max_U64; +} + +internal U64 +index_of_zero_u64(U64 *ptr, U64 count) +{ + for (U64 i = 0; i < count; i += 1) { + if (ptr[i] == 0) { + return i; + } + } + return max_U64; +} diff --git a/src/base/base_core.h b/src/base/base_core.h index 758a5b34..1db2f83f 100644 --- a/src/base/base_core.h +++ b/src/base/base_core.h @@ -925,4 +925,9 @@ internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_dat internal U64 u64_array_bsearch(U64 *arr, U64 count, U64 value); +//////////////////////////////// + +internal U64 index_of_zero_u32(U32 *ptr, U64 count); +internal U64 index_of_zero_u64(U64 *ptr, U64 count); + #endif // BASE_CORE_H diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 975dcdfc..c3946fe1 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -1190,13 +1190,16 @@ THREAD_POOL_TASK_FUNC(lnk_obj_reloc_patcher) for (U64 sect_idx = 0; sect_idx < obj_header.section_count_no_null; sect_idx += 1) { COFF_SectionHeader *section_header = §ion_table[sect_idx]; + // was section discarded? if (section_header->flags & COFF_SectionFlag_LnkRemove) { continue; } + // find section relocs COFF_RelocInfo reloc_info = coff_reloc_info_from_section_header(obj->data, section_header); COFF_Reloc *relocs = (COFF_Reloc *)(obj->data.str + reloc_info.array_off); + // apply relocs for (U64 reloc_idx = 0; reloc_idx < reloc_info.count; reloc_idx += 1) { COFF_Reloc *reloc = &relocs[reloc_idx]; @@ -3154,14 +3157,14 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S { LNK_Section *didat_sect = lnk_section_table_search(sectab, str8_lit(".didat"), PE_IDATA_SECTION_FLAGS); LNK_Symbol *null_import_desc = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, str8_lit("__NULL_DELAY_IMPORT_DESCRIPTOR")); - LNK_Symbol *last_import_desc = lnk_symbol_table_searchf(symtab, LNK_SymbolScope_Defined, "\x7f%S_NULL_THUNK_DATA_DLA", lnk_get_image_name(config)); - if (didat_sect && null_import_desc && last_import_desc) { + LNK_Symbol *last_null_thunk = lnk_symbol_table_searchf(symtab, LNK_SymbolScope_Defined, "\x7f%S_NULL_THUNK_DATA_DLA", lnk_get_image_name(config)); + if (didat_sect && null_import_desc && last_null_thunk) { COFF_ParsedSymbol null_import_desc_parsed = lnk_parsed_symbol_from_coff_symbol_idx(null_import_desc->u.defined.obj, null_import_desc->u.defined.symbol_idx); LNK_SectionContrib *didat_first_contrib = lnk_get_first_section_contrib(didat_sect); PE_DataDirectory *import_dir = str8_deserial_get_raw_ptr(image_data, pe.data_dir_range.min + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_DELAY_IMPORT, sizeof(PE_DataDirectory)); Assert(null_import_desc_parsed.section_number == didat_first_contrib->u.sect_idx+1); Assert(null_import_desc_parsed.value >= didat_first_contrib->u.off); - import_dir->virt_off = image_section_table[didat_first_contrib->u.sect_idx]->voff + didat_first_contrib->u.off; + import_dir->virt_off = image_section_table[didat_first_contrib->u.sect_idx+1]->voff + didat_first_contrib->u.off; import_dir->virt_size = null_import_desc_parsed.value - didat_first_contrib->u.off; } } diff --git a/src/pe/pe.c b/src/pe/pe.c index 50214f2c..f6827811 100644 --- a/src/pe/pe.c +++ b/src/pe/pe.c @@ -998,33 +998,24 @@ pe_parsed_imports_from_data(Arena *arena, { PE_ParsedImport *imports = 0; U64 import_count = 0; - - U64 name_table_off = coff_foff_from_voff(sections, section_count, name_table_voff); - + + U64 name_table_foff = coff_foff_from_voff(sections, section_count, name_table_voff); + String8 entries = str8_substr(raw_data, rng_1u64(name_table_foff, raw_data.size)); if (is_pe32) { - for (;; ++import_count) { - U32 raw_entry = 0; - str8_deserial_read_struct(raw_data, name_table_off + import_count*sizeof(raw_entry), &raw_entry); - if (raw_entry == 0) { - break; - } - } - + import_count = index_of_zero_u32((U32 *)entries.str, entries.size/sizeof(U32)); + if (import_count == max_U64) { import_count = 0; } imports = push_array(arena, PE_ParsedImport, import_count); - - for (U64 imp_idx = 0; imp_idx < import_count; ++imp_idx) { + + for (U64 imp_idx = 0; imp_idx < import_count; imp_idx += 1) { U32 raw_entry = 0; - str8_deserial_read_struct(raw_data, name_table_off + imp_idx*sizeof(raw_entry), &raw_entry); - - B32 is_ordinal = raw_entry & (1 << 31); - - PE_ParsedImport *imp = imports+imp_idx; - ++imp_idx; - + str8_deserial_read_struct(entries, imp_idx*sizeof(raw_entry), &raw_entry); + + B32 is_ordinal = ExtractBit(raw_entry, 31); if (is_ordinal) { // fill out ordinal import + PE_ParsedImport *imp = imports+imp_idx; imp->type = PE_ParsedImport_Ordinal; - imp->u.ordinal = raw_entry & max_U16; + imp->u.ordinal = Extract16(raw_entry, 0); } else { // map voff -> foff U64 off = coff_foff_from_voff(sections, section_count, raw_entry); @@ -1036,35 +1027,27 @@ pe_parsed_imports_from_data(Arena *arena, str8_deserial_read_cstr(raw_data, off+sizeof(hint), &name); // fill out named import + PE_ParsedImport *imp = imports+imp_idx; imp->type = PE_ParsedImport_Name; imp->u.name.hint = hint; imp->u.name.string = name; } } } else { - for (;; ++import_count) { - U64 raw_entry = 0; - str8_deserial_read_struct(raw_data, name_table_off + import_count*sizeof(raw_entry), &raw_entry); - if (raw_entry == 0) { - break; - } - } - + import_count = index_of_zero_u64((U64 *)entries.str, entries.size/sizeof(U64)); + if (import_count == max_U64) { import_count = 0; } imports = push_array(arena, PE_ParsedImport, import_count); - - for (U64 imp_idx = 0; imp_idx < import_count; ++imp_idx) { + + for (U64 imp_idx = 0; imp_idx < import_count; imp_idx += 1) { U64 raw_entry = 0; - str8_deserial_read_struct(raw_data, name_table_off + imp_idx*sizeof(raw_entry), &raw_entry); - - B32 is_ordinal = raw_entry & (1ull << 63); - - PE_ParsedImport *imp = imports+imp_idx; - ++imp_idx; - + str8_deserial_read_struct(entries, imp_idx*sizeof(raw_entry), &raw_entry); + + B32 is_ordinal = ExtractBit(raw_entry, 63); if (is_ordinal) { // fill out ordinal import + PE_ParsedImport *imp = imports+imp_idx; imp->type = PE_ParsedImport_Ordinal; - imp->u.ordinal = raw_entry & max_U16; + imp->u.ordinal = Extract16(raw_entry, 0); } else { // map voff -> foff U64 off = coff_foff_from_voff(sections, section_count, raw_entry); @@ -1076,6 +1059,7 @@ pe_parsed_imports_from_data(Arena *arena, str8_deserial_read_cstr(raw_data, off + sizeof(hint), &name); // fill out named import + PE_ParsedImport *imp = imports+imp_idx; imp->type = PE_ParsedImport_Name; imp->u.name.hint = hint; imp->u.name.string = name; @@ -1220,18 +1204,25 @@ pe_delay_imports_from_data(Arena *arena, raw_dll->name_table_voff, &import_count); + // parse bound table - U64 bound_table_foff = coff_foff_from_voff(sections, section_count, raw_dll->bound_table_voff); - Rng1U64 bound_table_range = rng_1u64(bound_table_foff, raw_data.size); - U64 bound_table_count; - U64 * bound_table = pe_array_from_null_term_addr(arena, is_pe32, raw_data, bound_table_range, &bound_table_count); - + Rng1U64 bound_table_range = {0}; + if (raw_dll->bound_table_voff) { + U64 bound_table_foff = coff_foff_from_voff(sections, section_count, raw_dll->bound_table_voff); + bound_table_range = rng_1u64(bound_table_foff, raw_data.size); + } + U64 bound_table_count; + U64 *bound_table = pe_array_from_null_term_addr(arena, is_pe32, raw_data, bound_table_range, &bound_table_count); + // parse unload table - U64 unload_table_foff = coff_foff_from_voff(sections, section_count, raw_dll->unload_table_voff); - Rng1U64 unload_table_range = rng_1u64(unload_table_foff, raw_data.size); - U64 unload_table_count; - U64 * unload_table = pe_array_from_null_term_addr(arena, is_pe32, raw_data, unload_table_range, &unload_table_count); - + Rng1U64 unload_table_range = {0}; + if (raw_dll->unload_table_voff) { + U64 unload_table_foff = coff_foff_from_voff(sections, section_count, raw_dll->unload_table_voff); + unload_table_range = rng_1u64(unload_table_foff, raw_data.size); + } + U64 unload_table_count; + U64 *unload_table = pe_array_from_null_term_addr(arena, is_pe32, raw_data, unload_table_range, &unload_table_count); + // fill out DLL PE_ParsedDelayDLLImport *dll = dlls+dll_idx; dll->attributes = raw_dll->attributes; diff --git a/src/pe/pe_make_import_table.c b/src/pe/pe_make_import_table.c index 15b54396..696e9010 100644 --- a/src/pe/pe_make_import_table.c +++ b/src/pe/pe_make_import_table.c @@ -341,11 +341,11 @@ pe_make_import_dll_obj_delayed(Arena *arena, COFF_TimeStamp time_stamp, COFF_Mac COFF_ObjSection *iat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$5"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); COFF_ObjSection *int_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$6"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, str8_zero()); COFF_ObjSection *dll_name_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$7"), PE_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr); - COFF_ObjSection *biat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$8"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); - COFF_ObjSection *uiat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$9"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); - COFF_ObjSection *code_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text$i"), PE_TEXT_SECTION_FLAGS, str8_zero()); - COFF_ObjSection *handle_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data$h"), PE_DATA_SECTION_FLAGS, str8_array(handle, handle_size)); + COFF_ObjSection *code_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text$i"), PE_TEXT_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_zero()); + COFF_ObjSection *handle_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data$h"), PE_DATA_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_array(handle, handle_size)); COFF_ObjSection *debug_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), PE_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols); + COFF_ObjSection *biat_sect = 0; + COFF_ObjSection *uiat_sect = 0; // sections symbols COFF_ObjSymbol *dll_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_sect->name, 0, dll_sect); @@ -362,12 +362,14 @@ pe_make_import_dll_obj_delayed(Arena *arena, COFF_TimeStamp time_stamp, COFF_Mac // patch BIAT virtual offset in import header if (emit_biat) { + biat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$8"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); COFF_ObjSymbol *biat_symbol = coff_obj_writer_push_symbol_static(obj_writer, biat_sect->name, 0, biat_sect); coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, bound_table_voff), biat_symbol); } // patch UIAT virtual offset in import header if (emit_uiat) { + uiat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$9"), PE_IDATA_SECTION_FLAGS|import_align, str8_zero()); COFF_ObjSymbol *uiat_symbol = coff_obj_writer_push_symbol_static(obj_writer, uiat_sect->name, 0, uiat_sect); coff_obj_writer_section_push_reloc_voff(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, unload_table_voff), uiat_symbol); }