[Lldb-commits] [lldb] r350086 - DWARF: Fix a bug in array size computation
Pavel Labath via lldb-commits
lldb-commits at lists.llvm.org
Thu Dec 27 01:25:34 PST 2018
Author: labath
Date: Thu Dec 27 01:25:34 2018
New Revision: 350086
URL: http://llvm.org/viewvc/llvm-project?rev=350086&view=rev
Log:
DWARF: Fix a bug in array size computation
Summary:
r346165 introduced a bug, where we would fail to parse the size of an
array if that size happened to match an existing die offset.
The logic was:
if (DWARFDIE count = die.GetReferencedDie(DW_AT_count))
num_elements = compute_vla_size(count);
else
num_elements = die.GetUsigned(DW_AT_count); // a fixed-size array
The problem with this logic was that GetReferencedDie did not take the
form class of the attribute into account, and would happily return a die
reference for any form, if its value happened to match some die.
As this behavior is inconsistent with how llvm's DWARFFormValue class
operates, I chose to fix the problem by making our version of this class
match the llvm behavior. For this to work, I had to add an explicit form
class check to the .apple_XXX tables parsing code, because they do
(incorrectly?) use data forms as die references.
Reviewers: aprantl, clayborg
Subscribers: JDevlieghere, lldb-commits
Differential Revision: https://reviews.llvm.org/D55991
Added:
lldb/trunk/lit/SymbolFile/DWARF/array-sizes.s
Modified:
lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
Added: lldb/trunk/lit/SymbolFile/DWARF/array-sizes.s
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/DWARF/array-sizes.s?rev=350086&view=auto
==============================================================================
--- lldb/trunk/lit/SymbolFile/DWARF/array-sizes.s (added)
+++ lldb/trunk/lit/SymbolFile/DWARF/array-sizes.s Thu Dec 27 01:25:34 2018
@@ -0,0 +1,147 @@
+# This tests a bug where we would incorrectly parse the size of an array if that
+# size happened to match an existing DIE offset. This happened because we
+# misinterpreted that value as a reference to a DIE specifying the VLA size even
+# though the form was a data form (as it should be).
+
+# REQUIRES: lld
+
+# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: lldb-test symbols %t | FileCheck %s
+
+# CHECK: Variable{0xffffffff0000001e}, name = "X"
+# CHECK-SAME: type = {ffffffff00000033} 0x{{[0-9a-f]*}} (char [56])
+
+
+# Generated from "char X[47];"
+# The array size was modified by hand.
+
+ .text
+ .file "-"
+ .file 1 "/tmp" "<stdin>"
+ .type X, at object # @X
+ .comm X,63,16
+ .section .debug_str,"MS", at progbits,1
+.Linfo_string0:
+ .asciz "clang version 8.0.0 (trunk 349604) (llvm/trunk 349608)" # string offset=0
+.Linfo_string1:
+ .asciz "-" # string offset=55
+.Linfo_string2:
+ .asciz "/tmp" # string offset=57
+.Linfo_string3:
+ .asciz "X" # string offset=62
+.Linfo_string4:
+ .asciz "char" # string offset=64
+.Linfo_string5:
+ .asciz "__ARRAY_SIZE_TYPE__" # string offset=69
+ .section .debug_abbrev,"", at progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 14 # DW_FORM_strp
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 14 # DW_FORM_strp
+ .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 14 # DW_FORM_strp
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 1 # DW_TAG_array_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 33 # DW_TAG_subrange_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 55 # DW_AT_count
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .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 6 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"", at 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] 0xb:0x43 DW_TAG_compile_unit
+ .long .Linfo_string0 # DW_AT_producer
+ .short 12 # DW_AT_language
+ .long .Linfo_string1 # DW_AT_name
+ .long 0 # DW_AT_stmt_list
+ .long .Linfo_string2 # DW_AT_comp_dir
+ .byte 2 # Abbrev [2] 0x1e:0x15 DW_TAG_variable
+ .long .Linfo_string3 # DW_AT_name
+ .long 51 # DW_AT_type
+ # DW_AT_external
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 9 # DW_AT_location
+ .byte 3
+ .quad X
+ .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_array_type
+ .long 63 # DW_AT_type
+.Ldie:
+ .byte 4 # Abbrev [4] 0x38:0x6 DW_TAG_subrange_type
+ .long 70 # DW_AT_type
+ .byte .Ldie-.Lcu_begin0 # DW_AT_count - should match the offset of an existing die
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x3f:0x7 DW_TAG_base_type
+ .long .Linfo_string4 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 6 # Abbrev [6] 0x46:0x7 DW_TAG_base_type
+ .long .Linfo_string5 # DW_AT_name
+ .byte 8 # DW_AT_byte_size
+ .byte 7 # DW_AT_encoding
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp?rev=350086&r1=350085&r2=350086&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp Thu Dec 27 01:25:34 2018
@@ -604,7 +604,7 @@ dw_addr_t DWARFFormValue::Address() cons
}
uint64_t DWARFFormValue::Reference() const {
- uint64_t die_offset = m_value.value.uval;
+ uint64_t value = m_value.value.uval;
switch (m_form) {
case DW_FORM_ref1:
case DW_FORM_ref2:
@@ -613,32 +613,36 @@ uint64_t DWARFFormValue::Reference() con
case DW_FORM_ref_udata:
assert(m_cu); // CU must be valid for DW_FORM_ref forms that are compile
// unit relative or we will get this wrong
- die_offset += m_cu->GetOffset();
- break;
+ return value + m_cu->GetOffset();
+
+ case DW_FORM_ref_addr:
+ case DW_FORM_ref_sig8:
+ case DW_FORM_GNU_ref_alt:
+ return value;
default:
- break;
+ return DW_INVALID_OFFSET;
}
-
- return die_offset;
}
uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
- uint64_t die_offset = m_value.value.uval;
+ uint64_t value = m_value.value.uval;
switch (m_form) {
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- die_offset += base_offset;
- break;
+ return value + base_offset;
+
+ case DW_FORM_ref_addr:
+ case DW_FORM_ref_sig8:
+ case DW_FORM_GNU_ref_alt:
+ return value;
default:
- break;
+ return DW_INVALID_OFFSET;
}
-
- return die_offset;
}
const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp?rev=350086&r1=350085&r2=350086&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp Thu Dec 27 01:25:34 2018
@@ -279,7 +279,9 @@ bool DWARFMappedHash::Header::Read(const
switch (header_data.atoms[i].type) {
case eAtomTypeDIEOffset: // DIE offset, check form for encoding
hash_data.offset =
- (dw_offset_t)form_value.Reference(header_data.die_base_offset);
+ DWARFFormValue::IsDataForm(form_value.Form())
+ ? form_value.Unsigned()
+ : form_value.Reference(header_data.die_base_offset);
break;
case eAtomTypeTag: // DW_TAG value for the DIE
More information about the lldb-commits
mailing list