ubsan cleanup

This commit is contained in:
Nikita Smith
2026-02-13 20:59:26 -08:00
parent fbc3cbd6eb
commit 1f51c6f25b
16 changed files with 180 additions and 110 deletions
+3 -3
View File
@@ -238,9 +238,9 @@ bit_array_set_bit32(U32Array bit_array, U64 idx, B32 state)
U64 word_idx = idx / 32;
U64 bit_idx = idx % 32;
if (state) {
bit_array.v[word_idx] |= (1 << bit_idx);
bit_array.v[word_idx] |= (1u << bit_idx);
} else {
bit_array.v[word_idx] &= ~(1 << bit_idx);
bit_array.v[word_idx] &= ~(1u << bit_idx);
}
}
@@ -269,7 +269,7 @@ bit_array_is_bit_set(U32Array bit_arr, U64 bit_pos)
Assert(word_idx < bit_arr.count);
U32 word = bit_arr.v[word_idx];
U64 bit_idx = bit_pos % 32;
B32 is_set = !!(word & (1 << bit_idx));
B32 is_set = !!(word & (1u << bit_idx));
return is_set;
}
+24 -21
View File
@@ -170,17 +170,18 @@ cv_deserial_leaf(String8 raw_data, U64 off, U64 align, CV_Leaf *leaf_out)
// do we have enough bytes to read header?
Assert(raw_data.size >= sizeof(CV_LeafHeader));
CV_LeafHeader *header = (CV_LeafHeader*)(raw_data.str + off);
StaticAssert(sizeof(CV_LeafHeader) == 4, g_leaf_header_size_check);
CV_LeafHeader header = { .v = memory_read32(raw_data.str + off) };
// leaf size must have enough bytes for the kind enum
Assert(header->size >= sizeof(CV_LeafKind));
Assert(header.size >= sizeof(CV_LeafKind));
// do we have enough bytes to read leaf data?
Assert(sizeof(CV_LeafSize) + header->size <= raw_data.size);
Assert(sizeof(CV_LeafSize) + header.size <= raw_data.size);
// fill out leaf
leaf_out->kind = header->kind;
leaf_out->data = str8(raw_data.str + sizeof(CV_LeafHeader), header->size - sizeof(CV_LeafKind));
leaf_out->kind = header.kind;
leaf_out->data = str8(raw_data.str + sizeof(CV_LeafHeader), header.size - sizeof(CV_LeafKind));
U64 leaf_size = AlignPow2(sizeof(CV_LeafHeader) + leaf_out->data.size, align);
Assert(leaf_size <= raw_data.size);
@@ -449,12 +450,20 @@ cv_parse_debug_s_c13_list(Arena *arena, String8List raw_debug_s)
return debug_s;
}
internal force_inline UBSAN_NO_ALIGN CV_Signature
cv_signature_from_debug_s(String8 raw_debug_s)
{
CV_Signature sig;
MemoryCopy(&sig, raw_debug_s.str, sizeof(sig));
return sig;
}
internal CV_DebugS
cv_parse_debug_s(Arena *arena, String8 raw_debug_s)
{
CV_DebugS result; MemoryZeroStruct(&result);
if (raw_debug_s.size >= sizeof(CV_Signature)) {
CV_Signature sig = *(CV_Signature *)raw_debug_s.str;
CV_Signature sig = cv_signature_from_debug_s(raw_debug_s);
switch (sig) {
case CV_Signature_C13: {
String8 raw_debug_s_past_sig = str8_substr(raw_debug_s, r1u64(sizeof(sig), raw_debug_s.size));
@@ -1130,11 +1139,9 @@ internal String8
cv_debug_t_get_raw_leaf(CV_DebugT debug_t, U64 leaf_idx)
{
Assert(leaf_idx < debug_t.count);
U8 *leaf_ptr = debug_t.v[leaf_idx];
CV_LeafSize *size_ptr = (CV_LeafSize *)leaf_ptr;
CV_LeafSize total_size = sizeof(*size_ptr) + *size_ptr;
String8 raw_leaf = str8(leaf_ptr, total_size);
return raw_leaf;
U8 *leaf_ptr = debug_t.v[leaf_idx];
CV_LeafSize size = memory_read16(debug_t.v[leaf_idx]);
return str8(leaf_ptr, sizeof(size) + size);
}
internal CV_LeafHeader *
@@ -1474,19 +1481,16 @@ cv_symbol_tree_from_symbol_list(Arena *arena, CV_SymbolList list)
internal U64
cv_patch_symbol_tree_offsets(CV_SymbolList list, U64 base_offset, U64 align)
{
Temp scratch = scratch_begin(0, 0);
struct Stack {
struct Stack *next;
CV_Symbol *symbol;
U64 offset;
};
Temp scratch = scratch_begin(0, 0);
struct Stack *stack = 0;
struct Stack *free_list = 0;
U64 cursor = base_offset;
for (CV_SymbolNode *symbol_n = list.first; symbol_n != 0; symbol_n = symbol_n->next) {
U32 cursor = safe_cast_u32(base_offset);
for EachNode(symbol_n, CV_SymbolNode, list.first) {
CV_Symbol symbol = symbol_n->data;
if (cv_is_scope_symbol(symbol.kind)) {
// NOTE: We don't patch 'next' offset in PROC symbols because
@@ -1494,10 +1498,9 @@ cv_patch_symbol_tree_offsets(CV_SymbolList list, U64 base_offset, U64 align)
// zeroed. LLD is on the same page.
Assert(symbol.data.size >= sizeof(U32)*2);
// patch symbol parent
// patch parent symbol offset
if (stack) {
U32 *parent_off_ptr = (U32 *)symbol.data.str;
*parent_off_ptr = stack->offset;
memory_write32(symbol.data.str, stack->offset);
}
// reuse/alloc frame
@@ -1516,7 +1519,7 @@ cv_patch_symbol_tree_offsets(CV_SymbolList list, U64 base_offset, U64 align)
} else if (cv_is_end_symbol(symbol.kind)) {
// patch symbol end
U32 *end_off_ptr = (U32 *)stack->symbol->data.str + /* skip parent off */ 1;
*end_off_ptr = cursor;
memory_write32(end_off_ptr, cursor);
// recycle frame
struct Stack *free_frame = stack;
+7 -3
View File
@@ -5,10 +5,13 @@
//- Symbol and Leaf Headers
typedef struct CV_LeafHeader
typedef union CV_LeafHeader
{
CV_LeafSize size;
CV_LeafKind kind;
struct {
CV_LeafSize size;
CV_LeafKind kind;
};
U32 v;
} CV_LeafHeader;
typedef struct CV_SymbolHeader
@@ -404,6 +407,7 @@ internal CV_SymbolList cv_make_proc_refs(Arena *arena, CV_ModIndex imod, CV_Symb
internal CV_DebugS cv_parse_debug_s_c13(Arena *arena, String8 raw_debug_s);
internal CV_DebugS cv_parse_debug_s_c13_list(Arena *arena, String8List raw_debug_s);
internal CV_Signature cv_signature_from_debug_s(String8 raw_debug_s);
internal CV_DebugS cv_parse_debug_s(Arena *arena, String8 raw_debug_s);
internal void cv_debug_s_concat_in_place(CV_DebugS *dst, CV_DebugS *src);
internal String8List cv_data_c13_from_debug_s(Arena *arena, CV_DebugS *debug_s, B32 write_sig);
+10 -7
View File
@@ -1635,9 +1635,10 @@ lnk_link_inputs(TP_Context *tp,
LNK_Lib *lib = member_ref->lib;
LNK_Symbol *link_symbol = member_ref->link_symbol;
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, lib->member_offsets[member_ref->member_idx]);
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
String8 member_name = coff_decode_member_name(lib->long_names, member_info.header.name);
U32 member_offset = memory_read32(lib->member_offsets + member_ref->member_idx);
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, member_offset);
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
String8 member_name = coff_decode_member_name(lib->long_names, member_info.header.name);
U64 refs_count = 0;
LNK_ObjSymbolRef **refs = lnk_ref_from_symbol_many(temp.arena, link_symbol, &refs_count);
@@ -1656,9 +1657,10 @@ lnk_link_inputs(TP_Context *tp,
U64 member_idx = member_ref->member_idx;
// parse member info
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, lib->member_offsets[member_idx]);
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
String8 member_name = coff_decode_member_name(lib->long_names, member_info.header.name);
U32 member_offset = memory_read32(lib->member_offsets + member_idx);
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, member_offset);
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
String8 member_name = coff_decode_member_name(lib->long_names, member_info.header.name);
switch (member_type) {
case COFF_DataType_Import: {
@@ -1809,7 +1811,8 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
LNK_LibMemberInfo *member_infos = hash_table_search_raw_raw(link->lib_member_infos_ht, lib);
LNK_Symbol *link_symbol = member_infos[member_idx].link;
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, lib->member_offsets[member_idx]);
U32 member_offset = memory_read32(lib->member_offsets + member_idx);
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, member_offset);
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
String8 member_name = coff_decode_member_name(lib->long_names, member_info.header.name);
COFF_ParsedArchiveImportHeader import_header = coff_archive_import_from_data(member_info.data);
+44 -38
View File
@@ -80,8 +80,8 @@ THREAD_POOL_TASK_FUNC(lnk_check_debug_t_sig_and_get_data_task)
lnk_error_obj(LNK_Error_IllData, obj, ".debug$T must have at least 4 bytes for CodeView signature");
}
CV_Signature *sig_ptr = (CV_Signature *)data_ptr->str;
switch (*sig_ptr) {
CV_Signature sig = cv_signature_from_debug_s(*data_ptr);
switch (sig) {
default: {
lnk_error_obj(LNK_Warning_IllData, obj, "unknown CodeView type signature in section (TODO: print section index)");
*data_ptr = str8(0,0);
@@ -1172,7 +1172,7 @@ lnk_hash_cv_leaf(Arena *arena,
// mix-in sub leaf hashes
for (CV_TypeIndexInfo *ti_n = ti_info_list.first; ti_n != 0; ti_n = ti_n->next) {
CV_TypeIndex sub_ti = *(CV_TypeIndex *) (leaf.data.str + ti_n->offset);
CV_TypeIndex sub_ti = memory_read32(leaf.data.str + ti_n->offset);
// is type index complex?
if (sub_ti >= ti_ranges[ti_n->source].min) {
@@ -1278,12 +1278,13 @@ lnk_hash_cv_leaf_deep(Arena *arena,
// get type index info
CV_TypeIndex *ti_ptr = (CV_TypeIndex *) (stack->data.str + curr_ti_info->offset);
CV_TypeIndex ti = memory_read32(ti_ptr);
// is index complex?
if (*ti_ptr >= ti_ranges[curr_ti_info->source].min) {
if (ti >= ti_ranges[curr_ti_info->source].min) {
// TODO: handle malformed index
AssertAlways(*ti_ptr < ti_ranges[curr_ti_info->source].max);
U64 ti_idx = (*ti_ptr - ti_ranges[curr_ti_info->source].min);
AssertAlways(ti < ti_ranges[curr_ti_info->source].max);
U64 ti_idx = (ti - ti_ranges[curr_ti_info->source].min);
// was leaf hashed?
if (curr_hashes[curr_ti_info->source][ti_idx] == 0) { // :zero_hash_array
@@ -1301,7 +1302,7 @@ lnk_hash_cv_leaf_deep(Arena *arena,
frame->ti_info = sub_ti_info_list.first;
frame->leaf = leaf;
frame->data = leaf.data;
frame->ti = *ti_ptr;
frame->ti = ti;
frame->ti_source = curr_ti_info->source;
// recurse to sub leaf
@@ -1443,7 +1444,8 @@ THREAD_POOL_TASK_FUNC(lnk_count_per_source_leaf_task)
CV_DebugT debug_t = *leaf_range->debug_t;
for EachInRange(leaf_idx, leaf_range->range) {
CV_LeafHeader *leaf_header = cv_debug_t_get_leaf_header(debug_t, leaf_idx);
CV_TypeIndexSource leaf_source = cv_type_index_source_from_leaf_kind(leaf_header->kind);
CV_LeafKind kind = memory_read16(MemberFromPtr(CV_LeafHeader, leaf_header, kind));
CV_TypeIndexSource leaf_source = cv_type_index_source_from_leaf_kind(kind);
counts[leaf_source] += 1;
}
}
@@ -1550,7 +1552,8 @@ THREAD_POOL_TASK_FUNC(lnk_leaf_dedup_internal_task)
LNK_LeafRef *bucket = 0;
for EachIndex(leaf_idx, debug_t.count) {
CV_LeafHeader *leaf_header = cv_debug_t_get_leaf_header(debug_t, leaf_idx);
CV_TypeIndexSource ti_source = cv_type_index_source_from_leaf_kind(leaf_header->kind);
CV_LeafKind leaf_kind = memory_read16(MemberFromPtr(CV_LeafHeader, leaf_header, kind));
CV_TypeIndexSource ti_source = cv_type_index_source_from_leaf_kind(leaf_kind);
LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr[ti_source];
LNK_LeafRef leaf_ref = lnk_obj_leaf_ref(obj_idx, leaf_idx);
@@ -1974,25 +1977,26 @@ THREAD_POOL_TASK_FUNC(lnk_cv_patcher_symbols_task)
// overwrite type indices in symbol
for EachNode(ti_info, CV_TypeIndexInfo, ti_info_list.first) {
CV_TypeIndex *ti_ptr = (CV_TypeIndex *)(symbol_n->data.data.str + ti_info->offset);
CV_TypeIndex ti = memory_read32(ti_ptr);
// skip simple type indices
if (*ti_ptr < ti_lo_arr[ti_info->source]) { continue; }
if (ti < ti_lo_arr[ti_info->source]) { continue; }
U64 assigned_types_cap = task->assigned_type_caps[ti_info->source];
CV_TypeIndex *assigned_types_ht = task->assigned_type_hts[ti_info->source];
CV_TypeIndex min_type_index = task->min_type_indices[ti_info->source];
LNK_LeafRefArray unique_leaf_refs = task->unique_leaf_refs_arr[ti_info->source];
U64 assigned_types_cap = task->assigned_type_caps [ti_info->source];
CV_TypeIndex *assigned_types_ht = task->assigned_type_hts [ti_info->source];
CV_TypeIndex min_type_index = task->min_type_indices [ti_info->source];
LNK_LeafRefArray unique_leaf_refs = task->unique_leaf_refs_arr[ti_info->source];
LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr [ti_info->source];
// find unique leaf refernece
LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr[ti_info->source];
LNK_LeafRef leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(task->input, loc_type, ti_info->source, loc_idx, *ti_ptr);
LNK_LeafRef leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(task->input, loc_type, ti_info->source, loc_idx, ti);
LNK_LeafRef *leaf_ref_unique = lnk_leaf_hash_table_search(leaf_ht, task->input, task->hashes, leaf_ref);
U64 leaf_ref_unique_hash = u64_hash_from_str8(str8_struct(&leaf_ref_unique));
CV_TypeIndex type_index = lnk_assigned_type_ht_search(assigned_types_cap, assigned_types_ht, min_type_index, unique_leaf_refs, leaf_ref_unique, leaf_ref_unique_hash);
CV_TypeIndex final_ti = lnk_assigned_type_ht_search(assigned_types_cap, assigned_types_ht, min_type_index, unique_leaf_refs, leaf_ref_unique, leaf_ref_unique_hash);
// we overwrite section memory directly
*ti_ptr = type_index;
memory_write32(ti_ptr, final_ti);
}
temp_end(temp);
@@ -2022,26 +2026,27 @@ THREAD_POOL_TASK_FUNC(lnk_cv_patcher_inlines_task)
for EachNode(ti_info, CV_TypeIndexInfo, ti_info_list.first) {
CV_TypeIndex *ti_ptr = (CV_TypeIndex *)(inline_data_node->string.str + ti_info->offset);
CV_TypeIndex ti_lo = lnk_ti_lo_from_loc(task->input, loc_type, loc_idx, ti_info->source);
CV_TypeIndex ti = memory_read32(ti_ptr);
// skip simple type indices
if (*ti_ptr < ti_lo) { continue; }
CV_TypeIndex ti_lo = lnk_ti_lo_from_loc(task->input, loc_type, loc_idx, ti_info->source);
if (ti < ti_lo) { continue; }
U64 assigned_types_cap = task->assigned_type_caps[ti_info->source];
CV_TypeIndex *assigned_types_ht = task->assigned_type_hts[ti_info->source];
CV_TypeIndex min_type_index = task->min_type_indices[ti_info->source];
LNK_LeafRefArray unique_leaf_refs = task->unique_leaf_refs_arr[ti_info->source];
U64 assigned_types_cap = task->assigned_type_caps [ti_info->source];
CV_TypeIndex *assigned_types_ht = task->assigned_type_hts [ti_info->source];
CV_TypeIndex min_type_index = task->min_type_indices [ti_info->source];
LNK_LeafRefArray unique_leaf_refs = task->unique_leaf_refs_arr[ti_info->source];
LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr [ti_info->source];
// find unique leaf refernece
LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr[ti_info->source];
LNK_LeafRef leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(task->input, loc_type, ti_info->source, loc_idx, *ti_ptr);
LNK_LeafRef leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(task->input, loc_type, ti_info->source, loc_idx, ti);
LNK_LeafRef *leaf_ref_unique = lnk_leaf_hash_table_search(leaf_ht, task->input, task->hashes, leaf_ref);
U64 leaf_ref_unique_hash = u64_hash_from_str8(str8_struct(&leaf_ref_unique));
CV_TypeIndex type_index = lnk_assigned_type_ht_search(assigned_types_cap, assigned_types_ht, min_type_index, unique_leaf_refs, leaf_ref_unique, leaf_ref_unique_hash);
CV_TypeIndex final_ti = lnk_assigned_type_ht_search(assigned_types_cap, assigned_types_ht, min_type_index, unique_leaf_refs, leaf_ref_unique, leaf_ref_unique_hash);
// patch index
*ti_ptr = type_index;
memory_write32(ti_ptr, final_ti);
}
temp_end(temp);
@@ -2074,25 +2079,26 @@ THREAD_POOL_TASK_FUNC(lnk_cv_patcher_leaves_task)
for EachNode(ti_info, CV_TypeIndexInfo, ti_info_list.first) {
CV_TypeIndex *ti_ptr = (CV_TypeIndex *)(leaf.data.str + ti_info->offset);
CV_TypeIndex ti = memory_read32(ti_ptr);
// skip simple type indices
if (*ti_ptr < ti_lo) { continue; }
if (ti < ti_lo) { continue; }
U64 assigned_types_cap = task->assigned_type_caps[ti_info->source];
CV_TypeIndex *assigned_types_ht = task->assigned_type_hts[ti_info->source];
CV_TypeIndex min_type_index = task->min_type_indices[ti_info->source];
LNK_LeafRefArray unique_leaf_refs = task->unique_leaf_refs_arr[ti_info->source];
U64 assigned_types_cap = task->assigned_type_caps [ti_info->source];
CV_TypeIndex *assigned_types_ht = task->assigned_type_hts [ti_info->source];
CV_TypeIndex min_type_index = task->min_type_indices [ti_info->source];
LNK_LeafRefArray unique_leaf_refs = task->unique_leaf_refs_arr[ti_info->source];
LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr [ti_info->source];
// find unique leaf refernece
LNK_LeafHashTable *leaf_ht = &task->leaf_ht_arr[ti_info->source];
LNK_LeafRef leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(task->input, loc_type, ti_info->source, loc_idx, *ti_ptr);
// find unique leaf ref
LNK_LeafRef leaf_ref = lnk_leaf_ref_from_loc_idx_and_ti(task->input, loc_type, ti_info->source, loc_idx, ti);
LNK_LeafRef *leaf_ref_unique = lnk_leaf_hash_table_search(leaf_ht, task->input, task->hashes, leaf_ref);
U64 leaf_ref_unique_hash = u64_hash_from_str8(str8_struct(&leaf_ref_unique));
CV_TypeIndex type_index = lnk_assigned_type_ht_search(assigned_types_cap, assigned_types_ht, min_type_index, unique_leaf_refs, leaf_ref_unique, leaf_ref_unique_hash);
CV_TypeIndex final_ti = lnk_assigned_type_ht_search(assigned_types_cap, assigned_types_ht, min_type_index, unique_leaf_refs, leaf_ref_unique, leaf_ref_unique_hash);
// patch index
*ti_ptr = type_index;
memory_write32(ti_ptr, final_ti);
}
temp_end(temp);
+2 -2
View File
@@ -69,8 +69,8 @@ typedef enum
LNK_LeafLocType_Count
} LNK_LeafLocType;
#define LNK_LeafRefFlag_LocIdxExternal (1 << 31)
#define LNK_LeafRefFlag_LeafIdxIPI (1 << 31)
#define LNK_LeafRefFlag_LocIdxExternal (1u << 31)
#define LNK_LeafRefFlag_LeafIdxIPI (1u << 31)
typedef struct
{
U32 enc_loc_idx;
+1 -1
View File
@@ -66,5 +66,5 @@ internal LNK_Lib ** lnk_array_from_lib_list(Arena *arena, LNK_LibList list
internal void lnk_lib_list_push_node(LNK_LibList *list, LNK_LibNode *node);
internal LNK_LibNodeArray lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, U64 inputs_count, struct LNK_Input **inputs);
internal B32 lnk_search_lib(LNK_Lib *lib, String8 symbol_name, U32 *member_idx_out);
internal force_inline B32 lnk_search_lib(LNK_Lib *lib, String8 symbol_name, U32 *member_idx_out);
+1 -1
View File
@@ -2384,7 +2384,7 @@ gsi_build_ex(TP_Context *tp, Arena *arena, PDB_GsiContext *gsi, U64 symbol_data_
if (bucket_list.count) {
U64 word_idx = bucket_idx / gsi->word_size;
Assert(word_idx < bitmap_count);
bitmap[word_idx] |= 1 << (bucket_idx % gsi->word_size);
bitmap[word_idx] |= 1u << (bucket_idx % gsi->word_size);
compressed_offset_arr[compressed_offset_count] = hash_idx * sizeof(PDB_GsiHashRecordOffsetCalc); // store in-memory offset for first bucket
compressed_offset_count += 1;
}