From 1e6df05d9f182249ea0106c464fa576fd5f52e6f Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Wed, 11 Feb 2026 17:20:38 -0800 Subject: [PATCH] sort resource pointers --- src/linker/lnk.c | 31 +++++++++++++++++++++++-------- src/pe/pe.c | 24 ++++++++++++++++++++++++ src/pe/pe.h | 10 ++++++++++ 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/linker/lnk.c b/src/linker/lnk.c index a2cbdf66..ebea90b2 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -493,8 +493,8 @@ lnk_make_null_obj(Arena *arena) internal int lnk_res_string_id_is_before(void *raw_a, void *raw_b) { - PE_Resource *a = raw_a; - PE_Resource *b = raw_b; + PE_Resource *a = *(PE_Resource **)raw_a; + PE_Resource *b = *(PE_Resource **)raw_b; Assert(a->id.type == COFF_ResourceIDType_String); Assert(b->id.type == COFF_ResourceIDType_String); int is_before = str8_is_before_case_sensitive(&a->id.u.string, &b->id.u.string); @@ -504,8 +504,8 @@ lnk_res_string_id_is_before(void *raw_a, void *raw_b) internal int lnk_res_number_id_is_before(void *raw_a, void *raw_b) { - PE_Resource *a = raw_a; - PE_Resource *b = raw_b; + PE_Resource *a = *(PE_Resource **)raw_a; + PE_Resource *b = *(PE_Resource **)raw_b; Assert(a->id.type == COFF_ResourceIDType_Number); Assert(b->id.type == COFF_ResourceIDType_Number); int is_before = u16_is_before(&a->id.u.number, &b->id.u.number); @@ -576,10 +576,25 @@ lnk_serialize_pe_resource_tree(COFF_ObjWriter *obj_writer, PE_ResourceDir *root_ dir_header->id_entry_count = res->u.dir->id_list.count; // sort input resources - PE_ResourceArray named_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->named_list); - PE_ResourceArray id_array = pe_resource_list_to_array(scratch.arena, &res->u.dir->id_list); - radsort(named_array.v, named_array.count, lnk_res_string_id_is_before); - radsort(id_array.v, id_array.count, lnk_res_number_id_is_before); + PE_ResourceArray named_array; + PE_ResourceArray id_array; + { + Temp scratch2 = scratch_begin(&scratch.arena, 1); + + named_array = pe_resource_list_to_array(scratch2.arena, &res->u.dir->named_list); + id_array = pe_resource_list_to_array(scratch2.arena, &res->u.dir->id_list); + + PE_ResourcePtrArray named_ptr_array = pe_resource_ptr_from_array(scratch2.arena, named_array); + PE_ResourcePtrArray id_ptr_array = pe_resource_ptr_from_array(scratch2.arena, id_array); + + radsort(named_ptr_array.v, named_ptr_array.count, lnk_res_string_id_is_before); + radsort(id_ptr_array.v, id_ptr_array.count, lnk_res_number_id_is_before); + + named_array = pe_resource_from_ptr_array(scratch.arena, named_ptr_array); + id_array = pe_resource_from_ptr_array(scratch.arena, id_ptr_array); + + scratch_end(scratch2); + } // allocate COFF entries COFF_ResourceDirEntry *named_entries = push_array(obj_writer->arena, COFF_ResourceDirEntry, named_array.count); diff --git a/src/pe/pe.c b/src/pe/pe.c index 61786acd..2a967c2c 100644 --- a/src/pe/pe.c +++ b/src/pe/pe.c @@ -1712,6 +1712,30 @@ pe_make_manifest_resource(Arena *arena, U32 resource_id, String8 manifest_data) return res; } +internal PE_ResourcePtrArray +pe_resource_ptr_from_array(Arena *arena, PE_ResourceArray arr) +{ + PE_ResourcePtrArray result = {0}; + result.count = arr.count; + result.v = push_array(arena, PE_Resource *, arr.count); + for EachIndex(i, arr.count) { + result.v[i] = &arr.v[i]; + } + return result; +} + +internal PE_ResourceArray +pe_resource_from_ptr_array(Arena *arena, PE_ResourcePtrArray arr) +{ + PE_ResourceArray result = {0}; + result.count = arr.count; + result.v = push_array(arena, PE_Resource, arr.count); + for EachIndex(i, arr.count) { + result.v[i] = *arr.v[i]; + } + return result; +} + //////////////////////////////// //~ Debug Directory diff --git a/src/pe/pe.h b/src/pe/pe.h index bb4386b0..378d71ed 100644 --- a/src/pe/pe.h +++ b/src/pe/pe.h @@ -867,6 +867,13 @@ struct PE_ResourceArray U64 count; }; +typedef struct PE_ResourcePtrArray PE_ResourcePtrArray; +struct PE_ResourcePtrArray +{ + PE_Resource **v; + U64 count; +}; + typedef struct PE_ResourceDir PE_ResourceDir; struct PE_ResourceDir { @@ -1097,6 +1104,9 @@ internal PE_ResourceDir * pe_resource_table_from_directory_data(Arena *arena, S internal String8 pe_make_manifest_resource(Arena *arena, U32 resource_id, String8 manifest_data); +internal PE_ResourcePtrArray pe_resource_ptr_from_array(Arena *arena, PE_ResourceArray arr); +internal PE_ResourceArray pe_resource_from_ptr_array(Arena *arena, PE_ResourcePtrArray arr); + //////////////////////////////// //~ Debug Directory