Author: Pavel Labath Date: 2024-10-02T11:13:43+02:00 New Revision: 15f90203bcbc685e8d63a7e52e60adff02bf5499
URL: https://github.com/llvm/llvm-project/commit/15f90203bcbc685e8d63a7e52e60adff02bf5499 DIFF: https://github.com/llvm/llvm-project/commit/15f90203bcbc685e8d63a7e52e60adff02bf5499.diff LOG: [lldb/DWARF] Respect member layout for types parsed through declarations (#110648) LLDB code for using the type layout data from DWARF was not kicking in for types which were initially parsed from a declaration. The problem was in these lines of code: ``` if (type) layout_info.bit_size = type->GetByteSize(nullptr).value_or(0) * 8; ``` which determine the types layout size by getting the size from the lldb_private::Type object. The problem is that if the type object does not have this information cached, this request can trigger another (recursive) request to lay out/complete the type. This one, somewhat surprisingly, succeeds, but does that without the type layout information (because it hasn't been computed yet). The reasons why this hasn't been noticed so far are: - this is a relatively new bug. I haven't checked but I suspect it was introduced in the "delay type definition search" patchset from this summer -- if we search for the definition eagerly, we will always have a cached size value. - it requires the presence of another bug/issue, as otherwise the automatically computed layout will match the real thing. - it reproduces (much) more easily with -flimit-debug-info (though it is possible to trigger it without that flag). My fix consists of always fetching type size information from DWARF (which so far existed as a fallback path). I'm not quite sure why this code was there in the first place (the code goes back to before the Great LLDB Reformat), but I don't believe it is necessary, as the type size (for types parsed from definition DIEs) is set exactly from this attribute (in ParseStructureLikeDIE). Added: lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-unusual-layout.s Modified: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s Removed: ################################################################################ diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 70540fe7fada68..a30d898a93cc4d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2128,14 +2128,10 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, TypeSystemClang::BuildIndirectFields(clang_type); TypeSystemClang::CompleteTagDeclarationDefinition(clang_type); - if (type) - layout_info.bit_size = type->GetByteSize(nullptr).value_or(0) * 8; - if (layout_info.bit_size == 0) - layout_info.bit_size = - die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; - if (layout_info.alignment == 0) - layout_info.alignment = - die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_alignment, 0) * 8; + layout_info.bit_size = + die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8; + layout_info.alignment = + die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_alignment, 0) * 8; clang::CXXRecordDecl *record_decl = m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-unusual-layout.s b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-unusual-layout.s new file mode 100644 index 00000000000000..27715c5004720a --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-unusual-layout.s @@ -0,0 +1,132 @@ +## Test that lldb respects the layout defined in DWARF even when starting out +## with a declaration of the class. + +# RUN: split-file %s %t +# RUN: llvm-mc --triple x86_64-pc-linux %t/asm --filetype=obj -o %t.o +# RUN: %lldb -s %t/commands -o exit %t.o 2>&1 | FileCheck %s + +#--- commands +target var a -fx +# CHECK-LABEL: target var a +# CHECK: (A) a = (i = 0xbaadf00d) + +#--- asm + .data + .p2align 4 + .long 0 +a: + .long 0xdeadbeef + .long 0xbaadf00d + + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 8 # DW_FORM_string + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 8 # DW_FORM_string + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .asciz "Hand-written DWARF" # DW_AT_producer + + .byte 2 # Abbrev [2] DW_TAG_variable + .asciz "a" # DW_AT_name + .long .LA_decl-.Lcu_begin0 # DW_AT_type + .byte 9 # DW_AT_location + .byte 3 + .quad a +.LA_decl: + .byte 3 # Abbrev [3] DW_TAG_structure_type + .asciz "A" # DW_AT_name + # DW_AT_declaration + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + +.Lcu_begin1: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .asciz "Hand-written DWARF" # DW_AT_producer + + .byte 4 # Abbrev [4] DW_TAG_structure_type + .asciz "A" # DW_AT_name + # DW_AT_declaration + .byte 8 # DW_AT_byte_size + .byte 5 # Abbrev [5] DW_TAG_member + .asciz "i" # DW_AT_name + .long .Lint-.Lcu_begin1 # DW_AT_type +## NB: empty padding before this member + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + +.Lint: + .byte 6 # Abbrev [6] DW_TAG_base_type + .asciz "int" # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + + .byte 0 # End Of Children Mark +.Ldebug_info_end1: diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s index 8633d02f492e67..16bdbd3cfaad6e 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/DW_AT_declaration-with-children.s @@ -105,6 +105,8 @@ c1: .byte 1 # DW_CHILDREN_yes .byte 3 # DW_AT_name .byte 8 # DW_FORM_string + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 .byte 0 # EOM(1) .byte 0 # EOM(2) .byte 7 # Abbreviation Code @@ -251,6 +253,7 @@ c1: .LB1: .byte 6 # Abbrev [6] DW_TAG_class_type .asciz "B1" # DW_AT_name + .byte 8 # DW_AT_byte_size .byte 7 # Abbrev [5] 0x58:0xc DW_TAG_member .asciz "ptr" # DW_AT_name .long .LAptr # DW_AT_type _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits