detect variable length array in upper bound and lower bound

This commit is contained in:
Nikita Smith
2026-02-05 17:43:19 -08:00
parent 2071e31f29
commit 82169462a4
6 changed files with 87 additions and 20 deletions
+19
View File
@@ -256,6 +256,25 @@ dw_are_attrib_class_and_form_kind_compatible(DW_Version ver, DW_AttribClass attr
return are_compat;
}
internal B32
dw_is_form_kind_ref(DW_Version ver, DW_Ext ext, DW_FormKind form_kind)
{
B32 is_ref = 0;
if (form_kind == DW_Form_RefAddr ||
form_kind == DW_Form_Ref1 ||
form_kind == DW_Form_Ref2 ||
form_kind == DW_Form_Ref4 ||
form_kind == DW_Form_Ref8 ||
form_kind == DW_Form_RefUData) {
is_ref = 1;
} else {
if (ext == DW_Ext_GNU) {
is_ref = DW_Form_GNU_RefAlt;
}
}
return is_ref;
}
internal String8
dw_name_string_from_section_kind(DW_SectionKind k)
{
+2
View File
@@ -1724,6 +1724,8 @@ internal DW_AttribClass dw_attrib_class_from_form_kind(DW_Version ver, DW_FormKi
internal B32 dw_are_attrib_class_and_form_kind_compatible(DW_Version ver, DW_AttribClass attrib_class, DW_FormKind form_kind);
internal B32 dw_is_form_kind_ref(DW_Version ver, DW_Ext ext, DW_FormKind form_kind);
//- Section Names
internal String8 dw_name_string_from_section_kind (DW_SectionKind k);
+19 -3
View File
@@ -1139,7 +1139,7 @@ dw_interp_ref(DW_Input *input, DW_CompUnit *cu, DW_FormKind form_kind, DW_Form f
form_kind == DW_Form_Ref4 || form_kind == DW_Form_Ref8 ||
form_kind == DW_Form_RefUData) {
ref.cu = cu;
ref.info_off = form.ref;
ref.info_off = cu->info_range.min + form.ref;
} else if (form_kind == DW_Form_RefAddr) {
NotImplemented;
} else if (form_kind == DW_Form_RefSig8) {
@@ -1987,7 +1987,7 @@ dw_u64_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind k
if (attrib_class == DW_AttribClass_Const || attrib_class == DW_AttribClass_Block) {
if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Type)) {
Temp scratch = scratch_begin(0,0);
DW_Reference type_ref = dw_ref_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Type);
DW_Reference type_ref = dw_ref_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Type);
DW_Tag type_tag = {0};
dw_read_tag_cu(scratch.arena, input, type_ref.cu, type_ref.info_off, &type_tag);
U64 type_byte_size = dw_byte_size_from_tag(input, cu, type_tag);
@@ -2009,6 +2009,22 @@ dw_u64_from_attrib(DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind k
return result;
}
internal B32
dw_is_attrib_var_ref(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib)
{
B32 is_var_ref = 0;
if (dw_is_form_kind_ref(cu->version, cu->ext, attrib->form_kind)) {
Temp scratch = scratch_begin(0,0);
DW_Reference ref = dw_ref_from_attrib(input, cu, attrib);
DW_Tag ref_tag = {0};
if (dw_read_tag_cu(scratch.arena, input, ref.cu, ref.info_off, &ref_tag)) {
is_var_ref = ref_tag.kind == DW_TagKind_Variable;
}
scratch_end(scratch);
}
return is_var_ref;
}
internal DW_CompUnit
dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U64 offset, B32 relaxed)
{
@@ -2164,7 +2180,7 @@ dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U6
cu.address_size = address_size;
cu.abbrev_off = abbrev_base;
cu.info_range = range;
cu.first_tag_info_off = range.min + cursor;
cu.first_tag_info_off = cursor;
cu.abbrev_table = abbrev_table;
cu.abbrev_data = abbrev_data;
cu.addr_lu = addr_lu;
+3 -1
View File
@@ -317,7 +317,7 @@ typedef struct DW_PubStringsTable
typedef struct DW_Reference
{
DW_CompUnit *cu;
U64 info_off;
U64 info_off; // global .debug_info offset
} DW_Reference;
////////////////////////////////
@@ -521,6 +521,8 @@ internal DW_Reference dw_ref_from_tag_attrib_kind (DW_Input *input, DW_Co
internal DW_LocList dw_loclist_from_tag_attrib_kind (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal Rng1U64List dw_rnglist_from_tag_attrib_kind (Arena *arena, DW_Input *input, DW_CompUnit *cu, DW_Tag tag, DW_AttribKind kind);
internal B32 dw_is_attrib_var_ref(DW_Input *input, DW_CompUnit *cu, DW_Attrib *attrib);
// compile unit
internal DW_CompUnit dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U64 offset, B32 relaxed);
+36 -16
View File
@@ -1,11 +1,9 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
// TODO:
//
// [ ] Currently converter relies on clang's -gdwarf-aranges to generate compile unit ranges,
// however it is optional and in case it is missing converter has to generate the ranges from scopes.
// [ ] Error handling
////////////////////////////////
thread_static D2R_Log g_d2r_log;
////////////////////////////////
@@ -2092,6 +2090,8 @@ d2r_convert_types(Arena *arena,
type->direct_type = direct_type;
} break;
case DW_TagKind_ArrayType: {
B32 error = 1;
// * DWARF vs RDI Array Type Graph *
//
// For example lets take following decl:
@@ -2118,15 +2118,19 @@ d2r_convert_types(Arena *arena,
struct SubrangeNode *subrange_stack = 0;
for (DW_TagNode *n = tag_node->first_child; n != 0; n = n->sibling) {
if (n->tag.kind != DW_TagKind_SubrangeType) {
// TODO: error handling
AssertAlways(!"unexpected tag");
continue;
d2r_log("[%llx] while scanning for DW_TagKind_SubrangeType found an unexpected child tag %S @ %llx\n", tag.info_off, dw_string_from_tag_kind(g_d2r_log.arena, n->tag.kind), n->tag.info_off);
goto array_type_exit;
}
// resolve lower bound
U64 lower_bound = 0;
if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_LowerBound)) {
lower_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_LowerBound);
B32 is_vla = dw_is_attrib_var_ref(input, cu, dw_attrib_from_tag(input, cu, n->tag, DW_AttribKind_LowerBound));
if (is_vla) {
d2r_log("[%llx] TODO: lower bound is a variable\n", n->tag.info_off);
} else {
lower_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_LowerBound);
}
} else {
lower_bound = dw_pick_default_lower_bound(cu_lang);
}
@@ -2137,9 +2141,14 @@ d2r_convert_types(Arena *arena,
U64 count = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_Count);
upper_bound = lower_bound + count;
} else if (dw_tag_has_attrib(input, cu, n->tag, DW_AttribKind_UpperBound)) {
upper_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_UpperBound);
// turn upper bound into exclusive range
upper_bound += 1;
B32 is_vla = dw_is_attrib_var_ref(input, cu, dw_attrib_from_tag(input, cu, n->tag, DW_AttribKind_UpperBound));
if (is_vla) {
d2r_log("[%llx] TODO: upper bound is a variable\n", n->tag.info_off);
goto array_type_exit;
} else {
upper_bound = dw_u64_from_attrib(input, cu, n->tag, DW_AttribKind_UpperBound);
upper_bound += 1; // turn upper bound into exclusive range
}
} else {
// zero sized array
}
@@ -2167,6 +2176,15 @@ d2r_convert_types(Arena *arena,
direct_type = t;
}
error = 0;
array_type_exit:;
// in case of an error, assign null to the array type
if (error) {
Assert(d2r_type_from_offset(type_table, tag.info_off) == 0); // this should the first time this type is being parsed
hash_table_push_u64_raw(arena, type_table->ht, tag.info_off, type_table->builtin_types[RDI_TypeKind_NULL]);
}
d2r_tag_iterator_skip_children(it);
} break;
case DW_TagKind_SubrangeType: {
@@ -2577,6 +2595,8 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
{
Temp scratch = scratch_begin(&arena, 1);
if (lane_idx() == 0) {
g_d2r_log.arena = arena_alloc();
////////////////////////////////
ProfBegin("compute exe hash");
@@ -2786,10 +2806,7 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
Temp comp_temp = temp_begin(scratch.arena);
DW_CompUnit *cu = &cu_arr[cu_idx];
// parse and build tag tree
DW_TagTree tag_tree = dw_tag_tree_from_cu(comp_temp.arena, &input, cu);
// skip DWO
{
if (cu->dwo_id) { goto next_cu; }
@@ -2801,6 +2818,9 @@ d2r_convert(Arena *arena, D2R_ConvertParams *params)
if (gnu_dwo_name.size) { goto next_cu; }
}
// parse and build tag tree
DW_TagTree tag_tree = dw_tag_tree_from_cu(comp_temp.arena, &input, cu);
// build (info offset -> tag) hash table to resolve tags with abstract origin
cu->tag_ht = dw_make_tag_hash_table(comp_temp.arena, tag_tree);
+8
View File
@@ -3,6 +3,14 @@
#pragma once
typedef struct D2R_Log
{
Arena *arena;
String8List v;
} D2R_Log;
#define d2r_log(...) str8_list_pushf(g_d2r_log.arena, &g_d2r_log.v, __FILE__ ":" Stringify(__LINE__) " " __VA_ARGS__)
typedef struct D2R_ConvertParams D2R_ConvertParams;
struct D2R_ConvertParams
{