[Lldb-commits] [lldb] 4515d35 - [lldb] Fix DW_TAG_GNU_call_site-DW_AT_low_pc as produced by GCC

Jan Kratochvil via lldb-commits lldb-commits at lists.llvm.org
Tue Jun 9 04:45:03 PDT 2020


Author: Jan Kratochvil
Date: 2020-06-09T13:41:41+02:00
New Revision: 4515d35f5c9e2bdcdbcb9fe9028d4a84871958c5

URL: https://github.com/llvm/llvm-project/commit/4515d35f5c9e2bdcdbcb9fe9028d4a84871958c5
DIFF: https://github.com/llvm/llvm-project/commit/4515d35f5c9e2bdcdbcb9fe9028d4a84871958c5.diff

LOG: [lldb] Fix DW_TAG_GNU_call_site-DW_AT_low_pc as produced by GCC

D80519 <https://reviews.llvm.org/D80519>
added support for `DW_TAG_GNU_call_site` but
Bug 45886 <https://bugs.llvm.org/show_bug.cgi?id=45886>
found one case did not work.

There is:

  0x000000b1:     DW_TAG_GNU_call_site
                    DW_AT_low_pc  (0x000000000040111e)
                    DW_AT_abstract_origin (0x000000cc "a")
  ...
  0x000000cc:   DW_TAG_subprogram
                  DW_AT_name      ("a")
                  DW_AT_prototyped        (true)
                  DW_AT_low_pc    (0x0000000000401109)
                  ^^^^^^^^^^^^ - here it did overwrite the 'low_pc' variable containing value 0x40111e we wanted
                  DW_AT_high_pc   (0x0000000000401114)
                  DW_AT_frame_base        (DW_OP_call_frame_cfa)
                  DW_AT_GNU_all_call_sites        (true)

DW_TAG_GNU_call_site attributes order as produced by GCC:
0x000000b1:     DW_TAG_GNU_call_site
                  DW_AT_low_pc  (0x000000000040111e)
                  DW_AT_abstract_origin (0x000000cc "a")

clang produces the attributes in opposite order:
0x00000064:     DW_TAG_GNU_call_site
                  DW_AT_abstract_origin (0x0000002a "a")
                  DW_AT_low_pc  (0x0000000000401146)

Differential Revision: https://reviews.llvm.org/D81334

Added: 
    lldb/test/Shell/SymbolFile/DWARF/DW_TAG_GNU_call_site-DW_AT_low_pc.s

Modified: 
    lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
    lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
    lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
    lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
    lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
index c330effc080b..fcb424029f5a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
@@ -104,9 +104,10 @@ bool DWARFBaseDIE::Supports_DW_AT_APPLE_objc_complete_type() const {
   return IsValid() && GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu);
 }
 
-size_t DWARFBaseDIE::GetAttributes(DWARFAttributes &attributes) const {
+size_t DWARFBaseDIE::GetAttributes(DWARFAttributes &attributes,
+                                   Recurse recurse) const {
   if (IsValid())
-    return m_die->GetAttributes(m_cu, attributes);
+    return m_die->GetAttributes(m_cu, attributes, recurse);
   attributes.Clear();
   return 0;
 }

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
index 0bad53ff4329..059b84864be7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
@@ -110,7 +110,9 @@ class DWARFBaseDIE {
   uint64_t GetAttributeValueAsAddress(const dw_attr_t attr,
                                       uint64_t fail_value) const;
 
-  size_t GetAttributes(DWARFAttributes &attributes) const;
+  enum class Recurse : bool { no, yes };
+  size_t GetAttributes(DWARFAttributes &attributes,
+                       Recurse recurse = Recurse::yes) const;
 
 protected:
   DWARFUnit *m_cu;

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index a133ce126027..f6425a889da8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -399,9 +399,10 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
 // specification or abstract origin attributes and including those in the
 // results. Any duplicate attributes will have the first instance take
 // precedence (this can happen for declaration attributes).
-size_t DWARFDebugInfoEntry::GetAttributes(
-    const DWARFUnit *cu, DWARFAttributes &attributes,
-    uint32_t curr_depth) const {
+size_t DWARFDebugInfoEntry::GetAttributes(const DWARFUnit *cu,
+                                          DWARFAttributes &attributes,
+                                          Recurse recurse,
+                                          uint32_t curr_depth) const {
   const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
   if (abbrevDecl) {
     const DWARFDataExtractor &data = cu->GetData();
@@ -432,12 +433,13 @@ size_t DWARFDebugInfoEntry::GetAttributes(
         break;
       }
 
-      if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin)) {
+      if (recurse == Recurse::yes &&
+          ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))) {
         if (form_value.ExtractValue(data, &offset)) {
           DWARFDIE spec_die = form_value.Reference();
           if (spec_die)
             spec_die.GetDIE()->GetAttributes(spec_die.GetCU(), attributes,
-                                             curr_depth + 1);
+                                             recurse, curr_depth + 1);
         }
       } else {
         llvm::Optional<uint8_t> fixed_skip_size = DWARFFormValue::GetFixedSize(form, cu);
@@ -730,7 +732,7 @@ DWARFDeclContext DWARFDebugInfoEntry::GetDWARFDeclContext(DWARFUnit *cu) const {
 DWARFDIE
 DWARFDebugInfoEntry::GetParentDeclContextDIE(DWARFUnit *cu) const {
   DWARFAttributes attributes;
-  GetAttributes(cu, attributes);
+  GetAttributes(cu, attributes, Recurse::yes);
   return GetParentDeclContextDIE(cu, attributes);
 }
 
@@ -780,7 +782,7 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE(
 const char *DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu,
                                                   std::string &storage) const {
   DWARFAttributes attributes;
-  GetAttributes(cu, attributes);
+  GetAttributes(cu, attributes, Recurse::yes);
   return GetQualifiedName(cu, attributes, storage);
 }
 

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 7bcff312b1c5..3019e1767f18 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/SmallVector.h"
 
 #include "DWARFAbbreviationDeclaration.h"
+#include "DWARFBaseDIE.h"
 #include "DWARFDebugAbbrev.h"
 #include "DWARFDebugRanges.h"
 #include <map>
@@ -47,8 +48,10 @@ class DWARFDebugInfoEntry {
   bool Extract(const lldb_private::DWARFDataExtractor &data,
                const DWARFUnit *cu, lldb::offset_t *offset_ptr);
 
-  size_t GetAttributes(const DWARFUnit *cu, DWARFAttributes &attrs) const {
-    return GetAttributes(cu, attrs, 0 /* curr_depth */);
+  using Recurse = DWARFBaseDIE::Recurse;
+  size_t GetAttributes(const DWARFUnit *cu, DWARFAttributes &attrs,
+                       Recurse recurse = Recurse::yes) const {
+    return GetAttributes(cu, attrs, recurse, 0 /* curr_depth */);
   }
 
   dw_offset_t
@@ -178,7 +181,7 @@ class DWARFDebugInfoEntry {
 
 private:
   size_t GetAttributes(const DWARFUnit *cu, DWARFAttributes &attrs,
-                       uint32_t curr_depth) const;
+                       Recurse recurse, uint32_t curr_depth) const;
 };
 
 #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index b6ae9e200f22..6f2444b698ce 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3677,8 +3677,12 @@ SymbolFileDWARF::CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
     addr_t low_pc = LLDB_INVALID_ADDRESS;
     bool tail_call = false;
 
+    // Second DW_AT_low_pc may come from DW_TAG_subprogram referenced by
+    // DW_TAG_GNU_call_site's DW_AT_abstract_origin overwriting our 'low_pc'.
+    // So do not inherit attributes from DW_AT_abstract_origin.
     DWARFAttributes attributes;
-    const size_t num_attributes = child.GetAttributes(attributes);
+    const size_t num_attributes =
+        child.GetAttributes(attributes, DWARFDIE::Recurse::no);
     for (size_t i = 0; i < num_attributes; ++i) {
       DWARFFormValue form_value;
       if (!attributes.ExtractFormValueAtIndex(i, form_value)) {

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/DW_TAG_GNU_call_site-DW_AT_low_pc.s b/lldb/test/Shell/SymbolFile/DWARF/DW_TAG_GNU_call_site-DW_AT_low_pc.s
new file mode 100644
index 000000000000..29cafebaa440
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/DW_TAG_GNU_call_site-DW_AT_low_pc.s
@@ -0,0 +1,230 @@
+# This tests that lldb is compatible with DWARF-4 entry values GNU extension
+# with DW_TAG_GNU_call_site attributes order as produced by GCC:
+# 0x000000b1:     DW_TAG_GNU_call_site
+#                   DW_AT_low_pc  (0x000000000040111e)
+#                   DW_AT_abstract_origin (0x000000cc "a")
+# clang produces the attributes in opposite order:
+# 0x00000064:     DW_TAG_GNU_call_site
+#                   DW_AT_abstract_origin (0x0000002a "a")
+#                   DW_AT_low_pc  (0x0000000000401146)
+
+# REQUIRES: target-x86_64, system-linux, lld
+
+# RUN: %clang_host -o %t %s
+# RUN: %lldb %t -o r -o 'p p' -o exit | FileCheck %s
+
+# CHECK: (int) $0 = 1
+
+# The DWARF has been produced and modified from:
+# static __attribute__((noinline, noclone)) void b(int x) {
+#   asm("");
+# }
+# static __attribute__((noinline, noclone)) void a(int p) {
+#   b(2);
+# }
+# int main() {
+#   a(1);
+#   return 0;
+# }
+
+	.text
+.Ltext0:
+	.type	b, @function
+b:
+	.cfi_startproc
+	ret
+	.cfi_endproc
+	.size	b, .-b
+	.type	a, @function
+a:
+.LVL1:
+.LFB1:
+	.cfi_startproc
+	movl	$2, %edi
+.LVL2:
+	call	b
+	int3
+	ret
+	.cfi_endproc
+.LFE1:
+	.size	a, .-a
+	.globl	main
+	.type	main, @function
+main:
+.LFB2:
+	.cfi_startproc
+	movl	$1, %edi
+	call	a
+.LVL4:
+	movl	$0, %eax
+	ret
+	.cfi_endproc
+.LFE2:
+	.size	main, .-main
+.Letext0:
+	.section	.debug_info,"", at progbits
+.Ldebug_info0:
+	.long	.Ldebuginfo_end - .Ldebuginfo_start	# Length of Compilation Unit Info
+.Ldebuginfo_start:
+	.value	0x4	# DWARF version number
+	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+	.byte	0x8	# Pointer Size (in bytes)
+	.uleb128 0x1	# (DIE (0xb) DW_TAG_compile_unit)
+	.asciz "GNU C17 10.1.1 20200507 (Red Hat 10.1.1-1) -mtune=generic -march=x86-64 -g -Og"	# DW_AT_producer: "GNU C17 10.1.1 20200507 (Red Hat 10.1.1-1) -mtune=generic -march=x86-64 -g -Og"
+	.byte	0xc	# DW_AT_language
+	.asciz "DW_TAG_GNU_call_site-DW_AT_low_pc.c"	# DW_AT_name
+	.asciz ""	# DW_AT_comp_dir: "/home/jkratoch/t"
+	.quad	.Ltext0	# DW_AT_low_pc
+	.quad	.Letext0-.Ltext0	# DW_AT_high_pc
+	.uleb128 0x2	# (DIE (0x2d) DW_TAG_subprogram)
+			# DW_AT_external
+	.asciz "main"	# DW_AT_name: "main"
+	.long	.Ltype_int	# DW_AT_type
+	.quad	.LFB2	# DW_AT_low_pc
+	.quad	.LFE2-.LFB2	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.uleb128 0x3	# (DIE (0x4f) DW_TAG_GNU_call_site)
+	.quad	.LVL4	# DW_AT_low_pc
+	.long	.Lfunc_a	# DW_AT_abstract_origin
+	.uleb128 0x4	# (DIE (0x5c) DW_TAG_GNU_call_site_parameter)
+	.uleb128 0x1	# DW_AT_location
+	.byte	0x55	# DW_OP_reg5
+	.uleb128 0x1	# DW_AT_GNU_call_site_value
+	.byte	0x31	# DW_OP_lit1
+	.byte	0	# end of children of DIE 0x4f
+	.byte	0	# end of children of DIE 0x2d
+.Ltype_int:
+	.uleb128 0x5	# (DIE (0x63) DW_TAG_base_type)
+	.byte	0x4	# DW_AT_byte_size
+	.byte	0x5	# DW_AT_encoding
+	.asciz "int"	# DW_AT_name
+.Lfunc_a:
+	.uleb128 0x6	# (DIE (0x6a) DW_TAG_subprogram)
+	.asciz "a"	# DW_AT_name
+			# DW_AT_prototyped
+	.quad	.LFB1	# DW_AT_low_pc
+	.quad	.LFE1-.LFB1	# DW_AT_high_pc
+	.uleb128 0x1	# DW_AT_frame_base
+	.byte	0x9c	# DW_OP_call_frame_cfa
+			# DW_AT_GNU_all_call_sites
+	.uleb128 0x7	# (DIE (0x86) DW_TAG_formal_parameter)
+	.asciz "p"	# DW_AT_name
+	.long	.Ltype_int	# DW_AT_type
+	.long	.LLST0	# DW_AT_location
+	.byte	0	# end of children of DIE 0x6a
+	.byte	0	# end of children of DIE 0xb
+.Ldebuginfo_end:
+	.section	.debug_abbrev,"", at progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1	# (abbrev code)
+	.uleb128 0x11	# (TAG: DW_TAG_compile_unit)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x25	# (DW_AT_producer)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x13	# (DW_AT_language)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x1b	# (DW_AT_comp_dir)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.byte	0
+	.byte	0
+	.uleb128 0x2	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3f	# (DW_AT_external)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x3	# (abbrev code)
+	.uleb128 0x4109	# (TAG: DW_TAG_GNU_call_site)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x31	# (DW_AT_abstract_origin)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.byte	0
+	.byte	0
+	.uleb128 0x4	# (abbrev code)
+	.uleb128 0x410a	# (TAG: DW_TAG_GNU_call_site_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2111	# (DW_AT_GNU_call_site_value)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.byte	0
+	.byte	0
+	.uleb128 0x5	# (abbrev code)
+	.uleb128 0x24	# (TAG: DW_TAG_base_type)
+	.byte	0	# DW_children_no
+	.uleb128 0xb	# (DW_AT_byte_size)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3e	# (DW_AT_encoding)
+	.uleb128 0xb	# (DW_FORM_data1)
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.byte	0
+	.byte	0
+	.uleb128 0x6	# (abbrev code)
+	.uleb128 0x2e	# (TAG: DW_TAG_subprogram)
+	.byte	0x1	# DW_children_yes
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x27	# (DW_AT_prototyped)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.uleb128 0x11	# (DW_AT_low_pc)
+	.uleb128 0x1	# (DW_FORM_addr)
+	.uleb128 0x12	# (DW_AT_high_pc)
+	.uleb128 0x7	# (DW_FORM_data8)
+	.uleb128 0x40	# (DW_AT_frame_base)
+	.uleb128 0x18	# (DW_FORM_exprloc)
+	.uleb128 0x2117	# (DW_AT_GNU_all_call_sites)
+	.uleb128 0x19	# (DW_FORM_flag_present)
+	.byte	0
+	.byte	0
+	.uleb128 0x7	# (abbrev code)
+	.uleb128 0x5	# (TAG: DW_TAG_formal_parameter)
+	.byte	0	# DW_children_no
+	.uleb128 0x3	# (DW_AT_name)
+	.uleb128 0x8	# (DW_FORM_string)
+	.uleb128 0x49	# (DW_AT_type)
+	.uleb128 0x13	# (DW_FORM_ref4)
+	.uleb128 0x2	# (DW_AT_location)
+	.uleb128 0x17	# (DW_FORM_sec_offset)
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_loc,"", at progbits
+.LLST0:
+	.quad	.LVL1-.Ltext0	# Location list begin address (*.LLST0)
+	.quad	.LVL2-.Ltext0	# Location list end address (*.LLST0)
+	.value	0x1	# Location expression size
+	.byte	0x55	# DW_OP_reg5
+	.quad	.LVL2-.Ltext0	# Location list begin address (*.LLST0)
+	.quad	.LFE1-.Ltext0	# Location list end address (*.LLST0)
+	.value	0x4	# Location expression size
+	.byte	0xf3	# DW_OP_GNU_entry_value
+	.uleb128 0x1
+	.byte	0x55	# DW_OP_reg5
+	.byte	0x9f	# DW_OP_stack_value
+	.quad	0	# Location list terminator begin (*.LLST0)
+	.quad	0	# Location list terminator end (*.LLST0)
+	.section	.note.GNU-stack,"", at progbits


        


More information about the lldb-commits mailing list