From b4bbc38ab22f67fc4764b98b52f434809c6aa3f5 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Fri, 10 Apr 2026 16:42:34 -0700 Subject: [PATCH] validate info stream --- src/linker/pdb_ext/msf_builder.c | 5 ++- src/linker/pdb_ext/msf_builder.h | 2 +- src/linker/pdb_ext/pdb_builder.c | 41 ++++++++++-------------- src/linker/pdb_ext/pdb_builder.h | 10 +++--- src/torture/torture.c | 16 ++++++++-- src/torture/torture_radlink.c | 53 +++++++++++++++++++++++++++++++- 6 files changed, 90 insertions(+), 37 deletions(-) diff --git a/src/linker/pdb_ext/msf_builder.c b/src/linker/pdb_ext/msf_builder.c index 3112daaa..eaa2f146 100644 --- a/src/linker/pdb_ext/msf_builder.c +++ b/src/linker/pdb_ext/msf_builder.c @@ -1453,10 +1453,9 @@ msf_find_stream(MSF_Context *msf, MSF_StreamNumber sn) } internal void -msf_release(MSF_Context **msf_ptr) +msf_release(MSF_Context *msf) { - arena_release((*msf_ptr)->arena); - *msf_ptr = 0; + arena_release(msf->arena); } internal String8List diff --git a/src/linker/pdb_ext/msf_builder.h b/src/linker/pdb_ext/msf_builder.h index 5dd24660..c07b582a 100644 --- a/src/linker/pdb_ext/msf_builder.h +++ b/src/linker/pdb_ext/msf_builder.h @@ -127,7 +127,7 @@ typedef struct //////////////////////////////// internal MSF_Context * msf_alloc(MSF_UInt page_size, MSF_UInt active_fpm); -internal void msf_release(MSF_Context **msf_ptr); +internal void msf_release(MSF_Context *msf_ptr); internal MSF_Error msf_build(MSF_Context *msf); internal U64 msf_get_save_size(MSF_Context *msf); internal String8List msf_get_page_data_nodes(Arena *arena, MSF_Context *msf); diff --git a/src/linker/pdb_ext/pdb_builder.c b/src/linker/pdb_ext/pdb_builder.c index 768d3dd6..dd670423 100644 --- a/src/linker/pdb_ext/pdb_builder.c +++ b/src/linker/pdb_ext/pdb_builder.c @@ -200,7 +200,8 @@ pdb_hash_table_grow(PDB_HashTable *ht, U64 new_capacity) for (U32 i = 0; i < ht->max; ++i) { if (bit_array_is_bit_set(ht->present_bits, i)) { PDB_HashTableBucket *bucket = &ht->bucket_arr[i]; - B32 is_set = pdb_hash_table_try_set(&new_ht, bucket->key, bucket->value); + PDB_HashTableBucket *is_set = pdb_hash_table_try_set(&new_ht, bucket->key, bucket->value); + is_set->insert_idx = bucket->insert_idx; Assert(is_set); } } @@ -215,11 +216,11 @@ pdb_hash_table_hash(String8 key) return (U16)pdb_hash_v1(key); } -internal B32 +internal PDB_HashTableBucket * pdb_hash_table_try_set(PDB_HashTable *ht, String8 key, String8 value) { ProfBeginFunction(); - B32 is_set = 0; + PDB_HashTableBucket *is_set = 0; U32 best_ibucket = pdb_hash_table_hash(key) % ht->max; U32 ibucket = best_ibucket; do { @@ -234,7 +235,7 @@ pdb_hash_table_try_set(PDB_HashTable *ht, String8 key, String8 value) bit_array_set_bit32(ht->deleted_bits, ibucket, 0); ht->count += 1; - is_set = 1; + is_set = bucket; break; } ibucket = (ibucket + 1) % ht->max; @@ -255,7 +256,7 @@ pdb_hash_table_set(PDB_HashTable *ht, String8 key, String8 value) } // set new item - B32 is_set = pdb_hash_table_try_set(ht, key, value); + PDB_HashTableBucket *is_set = pdb_hash_table_try_set(ht, key, value); AssertAlways(is_set); ProfEnd(); @@ -1696,11 +1697,10 @@ gsi_alloc(void) } internal void -gsi_release(PDB_GsiContext **gsi_ptr) +gsi_release(PDB_GsiContext *gsi) { ProfBeginFunction(); - arena_release((*gsi_ptr)->arena); - *gsi_ptr = NULL; + arena_release(gsi->arena); ProfEnd(); } @@ -2238,12 +2238,11 @@ psi_build(TP_Context *tp, PDB_PsiContext *psi, MSF_Context *msf, MSF_StreamNumbe } internal void -psi_release(PDB_PsiContext **psi_ptr) +psi_release(PDB_PsiContext *psi) { ProfBeginFunction(); - gsi_release(&(*psi_ptr)->gsi); - arena_release((*psi_ptr)->arena); - *psi_ptr = NULL; + gsi_release(psi->gsi); + arena_release(psi->arena); ProfEnd(); } @@ -2916,11 +2915,10 @@ dbi_build(TP_Context *tp, PDB_DbiContext *dbi, MSF_Context *msf, MSF_StreamNumbe } internal void -dbi_release(PDB_DbiContext **dbi_ptr) +dbi_release(PDB_DbiContext *dbi) { ProfBeginFunction(); - arena_release((*dbi_ptr)->arena); - *dbi_ptr = 0; + arena_release(dbi->arena); ProfEnd(); } @@ -3077,18 +3075,13 @@ pdb_alloc(U64 page_size, COFF_MachineType machine, COFF_TimeStamp time_stamp, U3 } internal void -pdb_release(PDB_Context **pdb_ptr) +pdb_release(PDB_Context *pdb) { ProfBeginFunction(); - PDB_Context *pdb = *pdb_ptr; - msf_release(&pdb->msf); - dbi_release(&pdb->dbi); - gsi_release(&pdb->gsi); - for (U64 i = 1; i < ArrayCount(pdb->type_servers); ++i) { - pdb_type_server_release(&pdb->type_servers[i]); - } + dbi_release(pdb->dbi); + gsi_release(pdb->gsi); + for (U64 i = 1; i < ArrayCount(pdb->type_servers); ++i) { pdb_type_server_release(&pdb->type_servers[i]); } arena_release(pdb->arena); - *pdb_ptr = 0; ProfEnd(); } diff --git a/src/linker/pdb_ext/pdb_builder.h b/src/linker/pdb_ext/pdb_builder.h index 527d82a2..a62c2694 100644 --- a/src/linker/pdb_ext/pdb_builder.h +++ b/src/linker/pdb_ext/pdb_builder.h @@ -332,7 +332,7 @@ typedef struct // PDB internal PDB_Context * pdb_alloc(U64 page_size, COFF_MachineType machine, COFF_TimeStamp time_stamp, U32 age, Guid guid); -internal void pdb_release(PDB_Context **pdb_ptr); +internal void pdb_release(PDB_Context *pdb); internal void pdb_build(TP_Context *tp, TP_Arena *pool_temp, PDB_Context *pdb, CV_StringHashTable string_ht, B32 build_gsi, B32 is_stripped); internal void pdb_set_machine(PDB_Context *pdb, COFF_MachineType machine); internal void pdb_set_guid(PDB_Context *pdb, Guid guid); @@ -359,7 +359,7 @@ internal PDB_SrcError pdb_add_src(PDB_InfoContext *info, MSF_Context *msf, internal PDB_GsiContext * gsi_alloc(void); internal void gsi_build(TP_Context *tp, PDB_GsiContext *gsi, MSF_Context *msf, MSF_StreamNumber gsi_sn, MSF_StreamNumber symbols_sn); -internal void gsi_release(PDB_GsiContext **gsi_ptr); +internal void gsi_release(PDB_GsiContext *gsi); internal void gsi_write_build_result(TP_Context *tp, PDB_GsiBuildResult build, MSF_Context *msf, MSF_StreamNumber sn, MSF_StreamNumber symbols_sn); internal PDB_GsiBuildResult gsi_build_ex(TP_Context *tp, Arena *arena, PDB_GsiContext *gsi, U64 symbol_data_base, B32 export_symbol_ptr_arr, U64 msf_page_size); internal U32 gsi_hash(PDB_GsiContext *gsi, String8 input); @@ -373,7 +373,7 @@ internal CV_SymbolNode * gsi_search(PDB_GsiContext *gsi, CV_Symbol *symbol); internal PDB_PsiContext * psi_alloc(void); internal void psi_build(TP_Context *tp, PDB_PsiContext *psi, MSF_Context *msf, MSF_StreamNumber sn, MSF_StreamNumber symbols_sn); -internal void psi_release(PDB_PsiContext **psi_ptr); +internal void psi_release(PDB_PsiContext *psi); internal CV_SymbolNode * psi_push(PDB_PsiContext *psi, CV_Pub32Flags flags, U32 offset, U16 isect, String8 name); // TODO: @@ -385,7 +385,7 @@ internal CV_SymbolNode * psi_push(PDB_PsiContext *psi, CV_Pub32Flags flags, U32 internal PDB_DbiContext * dbi_alloc(COFF_MachineType machine, U32 age); internal void dbi_build(TP_Context *tp, PDB_DbiContext *dbi, MSF_Context *msf, MSF_StreamNumber dbi_sn, CV_StringHashTable string_ht, B32 is_stripped); -internal void dbi_release(PDB_DbiContext **dbi_ptr); +internal void dbi_release(PDB_DbiContext *dbi); internal PDB_DbiModule * dbi_push_module(PDB_DbiContext *dbi, String8 obj_path, String8 lib_path); internal String8 dbi_module_read_symbol_data(Arena *arena, MSF_Context *msf, PDB_DbiModule *mod); internal String8 dbi_module_read_c11_data(Arena *arena, MSF_Context *msf, PDB_DbiModule *mod); @@ -409,7 +409,7 @@ internal String8 pdb_data_from_hash_table(Arena *arena, PDB_Hash internal void pdb_hash_table_set(PDB_HashTable *ht, String8 key, String8 value); internal B32 pdb_hash_table_get(PDB_HashTable *ht, String8 key, String8 *value_out); internal void pdb_hash_table_delete(PDB_HashTable *ht, String8 key); -internal B32 pdb_hash_table_try_set(PDB_HashTable *ht, String8 key, String8 value); +internal PDB_HashTableBucket * pdb_hash_table_try_set(PDB_HashTable *ht, String8 key, String8 value); internal B32 pdb_hash_table_is_present(PDB_HashTable *ht, U32 k); internal B32 pdb_hash_table_is_deleted(PDB_HashTable *ht, U32 k); internal U32 pdb_hash_table_hash(String8 key); diff --git a/src/torture/torture.c b/src/torture/torture.c index 702caa4f..f6a332e7 100644 --- a/src/torture/torture.c +++ b/src/torture/torture.c @@ -114,9 +114,19 @@ t_run_fail_handler(void *raw_ctx) internal T_RunResult t_run(T_Run run) { - T_RunCtx ctx = {0}; - ctx.run = run; - os_safe_call(t_run_caller, t_run_fail_handler, &ctx); + T_RunCtx ctx = { .run = run }; + + B32 do_safe_call = 1; +#if OS_WINDOWS + if (IsDebuggerPresent()) { + do_safe_call = 0; + } +#endif + if (do_safe_call) { + os_safe_call(t_run_caller, t_run_fail_handler, &ctx); + } else { + t_run_caller(&ctx); + } return ctx.result; } diff --git a/src/torture/torture_radlink.c b/src/torture/torture_radlink.c index 69936fef..d3ec8d7f 100644 --- a/src/torture/torture_radlink.c +++ b/src/torture/torture_radlink.c @@ -4626,7 +4626,58 @@ T_BeginTest(get_msf_stream_pages) T_Ok(stream_data.first->string.size == 1); } - msf_release(&msf); + msf_release(msf); +} + +T_BeginTest(validate_info_stream) +{ + COFF_TimeStamp time_stamp = 123; + U32 age = 1; + Guid guid = { .data1 = max_U32, .data2 = max_U16 - 1, .data3 = max_U16 - 2, .data4 = { 1, 2, 3, 4, 5, 6, 7, 8 } }; + PDB_Context *pdb = pdb_alloc(MSF_DEFAULT_PAGE_SIZE, COFF_MachineType_X64, time_stamp, age, guid); + + char *stream_names[] = { "one", "two", "three", "four", "five" }; + MSF_StreamNumber stream_numbers[ArrayCount(stream_names)] = {0}; + + for EachElement(i, stream_names) { + stream_numbers[i] = pdb_push_named_stream(&pdb->info->named_stream_ht, pdb->msf, str8_cstring(stream_names[i])); + T_Ok(stream_numbers[i] != MSF_INVALID_STREAM_NUMBER); + } + + TP_Context *tp = tp_alloc(arena, 1, 1, str8_lit("foo")); + TP_Arena *tp_arena = tp_arena_alloc(tp); + pdb_build(tp, tp_arena, pdb, (CV_StringHashTable){0}, 1, 0); + + T_Ok(msf_build(pdb->msf) == MSF_Error_OK); + String8List raw_msf_list = msf_get_page_data_nodes(arena, pdb->msf); + T_Ok(t_write_file_list(str8_lit("test.pdb"), raw_msf_list)); + + String8 raw_msf = t_read_file(arena, str8_lit("test.pdb")); + MSF_Parsed *msf_parsed = msf_parsed_from_data(arena, raw_msf); + String8 info_data = msf_data_from_stream(msf_parsed, PDB_FixedStream_Info); + +#if 0 + fprintf(stderr, "\n"); + for EachIndex(i, info_data.size) { + fprintf(stderr, "0x%02x, ", info_data.str[i]); + if (i % 19 == 18 && i > 0) { fprintf(stderr, "\n"); } + } +#endif + U8 expected_info_data[] = { + 0x94, 0x2e, 0x31, 0x01, 0x7b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfd, + 0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x22, 0x00, 0x00, 0x00, 0x6f, 0x6e, 0x65, 0x00, 0x74, 0x77, + 0x6f, 0x00, 0x74, 0x68, 0x72, 0x65, 0x65, 0x00, 0x66, 0x6f, 0x75, 0x72, 0x00, 0x66, 0x69, 0x76, 0x65, 0x00, 0x2f, + 0x4c, 0x69, 0x6e, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x51, 0x33, 0x01, + }; + T_Ok(str8_match(info_data, str8_array_fixed(expected_info_data), 0)); + + pdb_release(pdb); + tp_arena_release(&tp_arena); + tp_release(tp); } T_BeginTest(patch_cv_symbol_tree)