diff --git a/src/dwarf/dwarf_writer.c b/src/dwarf/dwarf_writer.c index 6b0835a9..b7de4503 100644 --- a/src/dwarf/dwarf_writer.c +++ b/src/dwarf/dwarf_writer.c @@ -327,9 +327,30 @@ dw_make_abbrev_entry(Arena *arena, DW_WriterTag *tag) internal DW_WriterTag * dw_writer_tag_begin(DW_Writer *writer, DW_TagKind kind) +{ + DW_WriterTag *tag = dw_writer_tag_reserve(writer, kind); + dw_writer_tag_begin_reserved(writer, tag); + return tag; +} + +internal void +dw_writer_tag_end(DW_Writer *writer) +{ + // pop to parent + writer->current = writer->current->parent; +} + +internal DW_WriterTag * +dw_writer_tag_reserve(DW_Writer *writer, DW_TagKind kind) { DW_WriterTag *tag = dw_writer_tag_chunk_list_push(writer->arena, &writer->tag_chunk_list, 512); tag->kind = kind; + return tag; +} + +internal void +dw_writer_tag_begin_reserved(DW_Writer *writer, DW_WriterTag *tag) +{ tag->parent = writer->current; // add tag to the tree @@ -339,15 +360,6 @@ dw_writer_tag_begin(DW_Writer *writer, DW_TagKind kind) writer->root = tag; } writer->current = tag; - - return tag; -} - -internal void -dw_writer_tag_end(DW_Writer *writer) -{ - // pop to parent - writer->current = writer->current->parent; } internal DW_WriterAttrib * diff --git a/src/dwarf/dwarf_writer.h b/src/dwarf/dwarf_writer.h index c4e78b94..eb8a3e84 100644 --- a/src/dwarf/dwarf_writer.h +++ b/src/dwarf/dwarf_writer.h @@ -259,8 +259,10 @@ internal U64 dw_serial_push_form(Arena *arena, String8List *srl, DW_Version vers //////////////////////////////// // Info -internal DW_WriterTag * dw_writer_tag_begin(DW_Writer *writer, DW_TagKind kind); -internal void dw_writer_tag_end (DW_Writer *writer); +internal DW_WriterTag * dw_writer_tag_reserve (DW_Writer *writer, DW_TagKind kind); +internal DW_WriterTag * dw_writer_tag_begin (DW_Writer *writer, DW_TagKind kind); +internal void dw_writer_tag_begin_reserved(DW_Writer *writer, DW_WriterTag *tag); +internal void dw_writer_tag_end (DW_Writer *writer); internal DW_WriterAttrib * dw_writer_push_attrib (DW_Writer *writer, DW_AttribKind kind, DW_WriterForm form ); internal DW_WriterAttrib * dw_writer_push_attrib_address (DW_Writer *writer, DW_AttribKind kind, U64 address ); diff --git a/src/rdi/rdi_local.c b/src/rdi/rdi_local.c index e69eb90c..73fa3c11 100644 --- a/src/rdi/rdi_local.c +++ b/src/rdi/rdi_local.c @@ -1363,7 +1363,7 @@ lane_sync(); if(flags & RDI_DumpSubsetFlag_##name) ProfScope(#name) return result_strings; } -#if 0 +#if SUBPROGRAM_CONVERSION_TEST internal String8 rdi_string_from_type(Arena *arena, RDI_Parsed *rdi, RDI_Procedure *proc, RDI_TypeNode *type) { diff --git a/src/rdi_from_dwarf/rdi_from_dwarf.c b/src/rdi_from_dwarf/rdi_from_dwarf.c index d0db1640..1919a722 100644 --- a/src/rdi_from_dwarf/rdi_from_dwarf.c +++ b/src/rdi_from_dwarf/rdi_from_dwarf.c @@ -1706,6 +1706,11 @@ d2r_convert_types(Arena *arena, type->direct_type = enum_base_type; } } break; + case DW_TagKind_SubProgram: { + if ( ! dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Declaration)) { + break; + } + } // fall-through case DW_TagKind_SubroutineType: { RDIM_Type *ret_type = d2r_find_or_convert_type(arena, type_table, input, cu, cu_lang, arch, tag, DW_AttribKind_Type); @@ -1721,10 +1726,13 @@ d2r_convert_types(Arena *arena, log_user_errorf("unexpected tag @ .debug_info+%llx", tag.info_off); } } + + DW_TagNode *parent = d2r_tag_iterator_parent_tag_node(it); + B32 is_method = parent->tag.kind == DW_TagKind_StructureType || parent->tag.kind == DW_TagKind_ClassType; // init proceudre type RDIM_Type *type = d2r_create_type_from_offset(arena, type_table, tag.info_off); - type->kind = RDI_TypeKind_Function; + type->kind = is_method ? RDI_TypeKind_Method : RDI_TypeKind_Function; type->byte_size = cu->address_size; type->direct_type = ret_type; type->count = param_list.count; @@ -2330,6 +2338,12 @@ d2r_convert_symbols(Arena *arena, d2r_tag_iterator_skip_children(it); } break; case DW_TagKind_SubProgram: { + // handled during type conversion step + if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Declaration)) { + d2r_tag_iterator_skip_children(it); + break; + } + DW_InlKind inl = DW_Inl_NotInlined; if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Inline)) { inl = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Inline); } @@ -2354,6 +2368,12 @@ d2r_convert_symbols(Arena *arena, RDIM_Type *container_type = 0; if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_ContainingType)) { container_type = d2r_type_from_attrib(type_table, input, cu, tag, DW_AttribKind_ContainingType); + } else { + DW_TagNode *parent = d2r_tag_iterator_parent_tag_node(it); + container_type = d2r_type_from_offset(type_table, parent->tag.info_off); + if (container_type == 0) { + log_user_errorf("ERROR: failed to infer parent type of subprogram from .debug_info+0x%llx\n", parent->tag.info_off); + } } // get frame base expression @@ -2380,13 +2400,19 @@ d2r_convert_symbols(Arena *arena, // sub program with user-defined parent tag is a method DW_Tag parent_tag = d2r_tag_iterator_parent_tag(it); if (parent_tag.kind == DW_TagKind_ClassType || parent_tag.kind == DW_TagKind_StructureType) { - RDI_MemberKind member_kind = RDI_MemberKind_NULL; - DW_VirtualityKind virtuality = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Virtuality); - switch (virtuality) { - case DW_VirtualityKind_None: member_kind = RDI_MemberKind_Method; break; - case DW_VirtualityKind_Virtual: member_kind = RDI_MemberKind_VirtualMethod; break; - case DW_VirtualityKind_PureVirtual: member_kind = RDI_MemberKind_VirtualMethod; break; // TODO: create kind for pure virutal - default: { log_user_errorf("unhandled virtuality kind"); } break; + // DW_VirtualityKind -> RDI_MemberKind + RDI_MemberKind member_kind = RDI_MemberKind_NULL; + { + DW_VirtualityKind virtuality = DW_VirtualityKind_None; + if (dw_tag_has_attrib(input, cu, tag, DW_AttribKind_Virtuality)) { + virtuality = dw_const_u64_from_tag_attrib_kind(input, cu, tag, DW_AttribKind_Virtuality); + switch (virtuality) { + case DW_VirtualityKind_None: member_kind = RDI_MemberKind_Method; break; + case DW_VirtualityKind_Virtual: member_kind = RDI_MemberKind_VirtualMethod; break; + case DW_VirtualityKind_PureVirtual: member_kind = RDI_MemberKind_VirtualMethod; break; // TODO: create kind for pure virutal + default: { log_user_errorf("unhandled virtuality kind"); } break; + } + } } RDIM_Type *type = d2r_type_from_offset(type_table, parent_tag.info_off); @@ -2504,7 +2530,6 @@ d2r_convert_symbols(Arena *arena, var->type = type; var->offset = voff; var->container_symbol = 0; - var->container_type = 0; // TODO: NotImplemented; } } break; case DW_TagKind_FormalParameter: { diff --git a/src/torture/torture_d2r.c b/src/torture/torture_d2r.c index c929eb59..1255e1c1 100644 --- a/src/torture/torture_d2r.c +++ b/src/torture/torture_d2r.c @@ -320,7 +320,7 @@ T_BeginTest(d2r_checksums) } T_EndTest; -#if 0 +#if SUBPROGRAM_CONVERSION_TEST T_BeginTest(d2r_subprogram) { DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64); @@ -404,17 +404,17 @@ T_BeginTest(d2r_subprogram) // -------------------------------------------------------------------------------- - DW_WriterTag *my_struct_type = dw_writer_declare_tag(writer); + DW_WriterTag *my_struct_type = dw_writer_tag_reserve(writer, DW_TagKind_StructureType); DW_WriterTag *const_my_struct_type = dw_writer_tag_begin(writer, DW_TagKind_ConstType); dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_type); dw_writer_tag_end(writer); - dw_writer_tag_begin(writer, DW_TagKind_PointerType); + DW_WriterTag *my_struct_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType); dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, const_my_struct_type); dw_writer_tag_end(writer); - dw_writer_tag_begin_define(writer, DW_TagKind_StructureType, my_struct_type); + dw_writer_tag_begin_reserved(writer, my_struct_type); dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "MyStructure"); dw_writer_push_attrib_uint (writer, DW_AttribKind_ByteSize, 0x100); @@ -423,7 +423,7 @@ T_BeginTest(d2r_subprogram) dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_ptr_type); dw_writer_tag_begin(writer, DW_TagKind_FormalParameter); - dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_method_this_type); + dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_ptr_type); dw_writer_tag_end(writer); dw_writer_tag_end(writer); dw_writer_tag_end(writer);