[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