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,@object               # @X
+       .comm   X,63,16
+       .section        .debug_str,"MS",@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,"",@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,"",@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


_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to