[LLDB] - Add basic support for .debug_rnglists section (DWARF5)
authorGeorge Rimar <grimar@accesssoftek.com>
Wed, 10 Oct 2018 08:11:15 +0000 (08:11 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Wed, 10 Oct 2018 08:11:15 +0000 (08:11 +0000)
This adds a basic support of the .debug_rnglists section.
Only the DW_RLE_start_length and DW_RLE_end_of_list entries are supported.

Differential revision: https://reviews.llvm.org/D52981

llvm-svn: 344119

12 files changed:
lldb/include/lldb/lldb-enumerations.h
lldb/lit/Breakpoint/Inputs/debug_rnglist_basic.yaml [new file with mode: 0644]
lldb/lit/Breakpoint/debug_rnglist_basic.test [new file with mode: 0644]
lldb/source/Core/Section.cpp
lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
lldb/source/Symbol/ObjectFile.cpp

index 6e3d85f..8a7cff4 100644 (file)
@@ -675,6 +675,7 @@ enum SectionType {
   eSectionTypeDWARFDebugNames, // DWARF v5 .debug_names
   eSectionTypeOther,
   eSectionTypeDWARFDebugLineStr, // DWARF v5 .debug_line_str
+  eSectionTypeDWARFDebugRngLists, // DWARF v5 .debug_rnglists
 };
 
 FLAGS_ENUM(EmulateInstructionOptions){
diff --git a/lldb/lit/Breakpoint/Inputs/debug_rnglist_basic.yaml b/lldb/lit/Breakpoint/Inputs/debug_rnglist_basic.yaml
new file mode 100644 (file)
index 0000000..6a6db28
--- /dev/null
@@ -0,0 +1,50 @@
+--- !ELF
+FileHeader:      
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+  Entry:           0x0000000000400440
+Sections:        
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    Address:         0x0000000000400440
+    AddressAlign:    0x0000000000000010
+    Content:         31ED4989D15E4889E24883E4F0505449C7C0C005400048C7C15005400048C7C730054000E8B7FFFFFFF4660F1F44000055B820204000483D202040004889E57417B8000000004885C0740D5DBF20204000FFE00F1F4400005DC3660F1F440000BE20204000554881EE202040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF20204000FFE00F1F005DC3660F1F440000803D391B0000007517554889E5E87EFFFFFFC605271B0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89900F1F840000000000554889E5B8010000005DC30F1F440000554889E54883EC10C745FC00000000E8DCFFFFFF4883C4105DC3660F1F440000415741564189FF415541544C8D25A618000055488D2DA6180000534989F64989D54C29E54883EC0848C1FD03E86FFEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+  - Name:            .debug_str_offsets
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         200000000500000000000000230000002C0000005D00000065000000690000006D000000
+  - Name:            .debug_str
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    Content:         636C616E672076657273696F6E20382E302E3020287472756E6B203334333438372900746573742E637070002F686F6D652F756D622F74657374735F323031382F313033726E676C697374732F6C6C64622F63726561746574657374005F5A337A656476007A656400696E74006D61696E00
+  - Name:            .debug_abbrev
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         011101252513050325721710171B251101551774170000022E001101120640186E2503253A0B3B0B49133F190000032E0011011206401803253A0B3B0B49133F19000004240003253E0B0B0B000000
+  - Name:            .debug_info
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         580000000500010800000000010004000108000000000000000200000000000000000C0000000C0000000220054000000000000B000000015603040101570000000330054000000000001A0000000156060105570000000405050400
+  - Name:            .debug_rnglists
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         1D00000005000800000000000720054000000000000B0730054000000000001A00
+  - Name:            .debug_macinfo
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         '00'
+  - Name:            .debug_line
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x0000000000000001
+    Content:         82000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E023100000000F7B7492A97F18E69F7EC76B19E9024873100000000F7B7492A97F18E69F7EC76B19E90248700090220054000000000000105020A4B020700010100090230054000000000001605090AE5050206580206000101
+  - Name:            .debug_line_str
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_MERGE, SHF_STRINGS ]
+    AddressAlign:    0x0000000000000001
+    Content:         2F686F6D652F756D622F74657374735F323031382F313033726E676C697374732F6C6C64622F6372656174657465737400746573742E63707000
+Symbols:         
+...
diff --git a/lldb/lit/Breakpoint/debug_rnglist_basic.test b/lldb/lit/Breakpoint/debug_rnglist_basic.test
new file mode 100644 (file)
index 0000000..268e4a0
--- /dev/null
@@ -0,0 +1,30 @@
+# RUN: yaml2obj %p/Inputs/debug_rnglist_basic.yaml > %ttest
+# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
+
+# The following code and invocation were used to produce yaml file,
+# which was manually reduced after that.
+# clang -O0 -gdwarf-5 test.cpp -o test -fuse-ld=lld -ffunction-sections
+#
+# //test.cpp:
+# int zed() { 
+#  return 1;
+# }
+#
+# int main() {
+#  return zed();
+# }
+#
+# clang and LLD versions were 8.0.0 (trunk 343487)
+#
+# Output file contains .debug_rnglists section with basic entries:
+# DW_RLE_start_length and DW_RLE_end_of_list.
+# If LLDB would not be able to parse the section and entries correctly,
+# then reported location would be incorrect.
+
+b main
+# CHECK-LABEL: b main
+# CHECK: Address: {{.*}}`main + 15 at test.cpp:6:9
+
+b zed
+# CHECK-LABEL: b zed
+# CHECK: Address: {{.*}}`zed() + 4 at test.cpp:2:2
index 0a26203..d516b63 100644 (file)
@@ -87,6 +87,8 @@ const char *Section::GetTypeAsCString() const {
     return "dwarf-pubtypes";
   case eSectionTypeDWARFDebugRanges:
     return "dwarf-ranges";
+  case eSectionTypeDWARFDebugRngLists:
+    return "dwarf-rnglists";
   case eSectionTypeDWARFDebugStr:
     return "dwarf-str";
   case eSectionTypeDWARFDebugStrOffsets:
index 01ef583..2958503 100644 (file)
@@ -1796,6 +1796,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
       static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
       static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
       static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
+      static ConstString g_sect_name_dwarf_debug_rnglists(".debug_rnglists");
       static ConstString g_sect_name_dwarf_debug_str(".debug_str");
       static ConstString g_sect_name_dwarf_debug_str_offsets(
           ".debug_str_offsets");
@@ -1879,6 +1880,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
         sect_type = eSectionTypeDWARFDebugPubTypes;
       else if (name == g_sect_name_dwarf_debug_ranges)
         sect_type = eSectionTypeDWARFDebugRanges;
+      else if (name == g_sect_name_dwarf_debug_rnglists)
+        sect_type = eSectionTypeDWARFDebugRngLists;
       else if (name == g_sect_name_dwarf_debug_str)
         sect_type = eSectionTypeDWARFDebugStr;
       else if (name == g_sect_name_dwarf_debug_types)
index f92c994..57226bc 100644 (file)
@@ -1205,6 +1205,7 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
           case eSectionTypeDWARFDebugPubNames:
           case eSectionTypeDWARFDebugPubTypes:
           case eSectionTypeDWARFDebugRanges:
+          case eSectionTypeDWARFDebugRngLists:
           case eSectionTypeDWARFDebugStr:
           case eSectionTypeDWARFDebugStrOffsets:
           case eSectionTypeDWARFDebugTypes:
@@ -1494,7 +1495,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
   if (section_name == g_sect_name_dwarf_debug_pubtypes)
     return eSectionTypeDWARFDebugPubTypes;
   if (section_name == g_sect_name_dwarf_debug_ranges)
-    return eSectionTypeDWARFDebugRanges;
+    return eSectionTypeDWARFDebugRanges; 
   if (section_name == g_sect_name_dwarf_debug_str)
     return eSectionTypeDWARFDebugStr;
   if (section_name == g_sect_name_dwarf_debug_types)
index 26ca8c3..f42164d 100644 (file)
@@ -1067,9 +1067,9 @@ size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
       dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET,
       check_specification_or_abstract_origin);
   if (debug_ranges_offset != DW_INVALID_OFFSET) {
-    DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
-
-    debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges);
+    if (DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges())
+      debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset,
+                               ranges);
     ranges.Slide(cu->GetBaseAddress());
   } else if (check_hi_lo_pc) {
     dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
index 89e27ef..e891fce 100644 (file)
@@ -123,3 +123,71 @@ bool DWARFDebugRanges::FindRanges(dw_addr_t debug_ranges_base,
   }
   return false;
 }
+
+bool DWARFDebugRngLists::ExtractRangeList(const DWARFDataExtractor &data,
+                                          uint8_t addrSize,
+                                          lldb::offset_t *offset_ptr,
+                                          DWARFRangeList &rangeList) {
+  rangeList.Clear();
+
+  bool error = false;
+  while (!error) {
+    switch (data.GetU8(offset_ptr)) {
+    case DW_RLE_end_of_list:
+      return true;
+
+    case DW_RLE_start_length: {
+      dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
+      dw_addr_t len = data.GetULEB128(offset_ptr);
+      rangeList.Append(DWARFRangeList::Entry(begin, len));
+      break;
+    }
+
+    default:
+      // Next encodings are not yet supported:
+      // DW_RLE_base_addressx, DW_RLE_startx_endx, DW_RLE_startx_length,
+      // DW_RLE_offset_pair, DW_RLE_base_address, DW_RLE_start_end
+      lldbassert(0 && "unknown range list entry encoding");
+      error = true;
+    }
+  }
+
+  return false;
+}
+
+void DWARFDebugRngLists::Extract(SymbolFileDWARF *dwarf2Data) {
+  const DWARFDataExtractor &data = dwarf2Data->get_debug_rnglists_data();
+  lldb::offset_t offset = 0;
+
+  uint64_t length = data.GetU32(&offset);
+  bool isDwarf64 = false;
+  if (length == 0xffffffff) {
+    length = data.GetU64(&offset);
+    isDwarf64 = true;
+  }
+  lldb::offset_t end = offset + length;
+
+  // Check version.
+  if (data.GetU16(&offset) < 5)
+    return;
+
+  uint8_t addrSize = data.GetU8(&offset);
+
+  // We do not support non-zero segment selector size.
+  if (data.GetU8(&offset) != 0) {
+    lldbassert(0 && "not implemented");
+    return;
+  }
+
+  uint32_t offsetsAmount = data.GetU32(&offset);
+  for (uint32_t i = 0; i < offsetsAmount; ++i)
+    Offsets.push_back(data.GetPointer(&offset));
+
+  lldb::offset_t listOffset = offset;
+  DWARFRangeList rangeList;
+  while (offset < end && ExtractRangeList(data, addrSize, &offset, rangeList)) {
+    rangeList.Sort();
+    m_range_map[listOffset] = rangeList;
+    listOffset = offset;
+  }
+}
index f514359..e239bc5 100644 (file)
@@ -18,8 +18,9 @@
 class DWARFDebugRanges {
 public:
   DWARFDebugRanges();
-  ~DWARFDebugRanges();
-  void Extract(SymbolFileDWARF *dwarf2Data);
+  virtual ~DWARFDebugRanges();
+  virtual void Extract(SymbolFileDWARF *dwarf2Data);
+
   static void Dump(lldb_private::Stream &s,
                    const lldb_private::DWARFDataExtractor &debug_ranges_data,
                    lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr);
@@ -37,4 +38,17 @@ protected:
   range_map m_range_map;
 };
 
+// DWARF v5 .debug_rnglists section.
+class DWARFDebugRngLists : public DWARFDebugRanges {
+public:
+  void Extract(SymbolFileDWARF *dwarf2Data) override;
+
+protected:
+  bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data,
+                        uint8_t addrSize, lldb::offset_t *offset_ptr,
+                        DWARFRangeList &list);
+
+  std::vector<uint64_t> Offsets;
+};
+
 #endif // SymbolFileDWARF_DWARFDebugRanges_h_
index 4f9e726..59163a9 100644 (file)
@@ -410,9 +410,9 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile)
       m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(),
       m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(),
       m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(),
-      m_data_debug_ranges(), m_data_debug_str(), m_data_apple_names(),
-      m_data_apple_types(), m_data_apple_namespaces(), m_abbr(), m_info(),
-      m_line(), m_fetched_external_modules(false),
+      m_data_debug_ranges(), m_data_debug_rnglists(), m_data_debug_str(),
+      m_data_apple_names(), m_data_apple_types(), m_data_apple_namespaces(),
+      m_abbr(), m_info(), m_line(), m_fetched_external_modules(false),
       m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(),
       m_unique_ast_type_map() {}
 
@@ -659,6 +659,11 @@ const DWARFDataExtractor &SymbolFileDWARF::get_debug_ranges_data() {
                               m_data_debug_ranges);
 }
 
+const DWARFDataExtractor &SymbolFileDWARF::get_debug_rnglists_data() {
+  return GetCachedSectionData(eSectionTypeDWARFDebugRngLists,
+                              m_data_debug_rnglists);
+}
+
 const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_data() {
   return GetCachedSectionData(eSectionTypeDWARFDebugStr, m_data_debug_str);
 }
@@ -753,11 +758,14 @@ DWARFDebugRanges *SymbolFileDWARF::DebugRanges() {
     static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
     Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
                        static_cast<void *>(this));
-    if (get_debug_ranges_data().GetByteSize() > 0) {
+
+    if (get_debug_ranges_data().GetByteSize() > 0)
       m_ranges.reset(new DWARFDebugRanges());
-      if (m_ranges.get())
-        m_ranges->Extract(this);
-    }
+    else if (get_debug_rnglists_data().GetByteSize() > 0)
+      m_ranges.reset(new DWARFDebugRngLists());
+
+    if (m_ranges.get())
+      m_ranges->Extract(this);
   }
   return m_ranges.get();
 }
index abf4e39..b3d087f 100644 (file)
@@ -54,6 +54,7 @@ class DWARFDebugInfo;
 class DWARFDebugInfoEntry;
 class DWARFDebugLine;
 class DWARFDebugRanges;
+class DWARFDebugRngLists;
 class DWARFDeclContext;
 class DWARFDIECollection;
 class DWARFFormValue;
@@ -244,6 +245,7 @@ public:
   const lldb_private::DWARFDataExtractor &get_debug_macro_data();
   const lldb_private::DWARFDataExtractor &get_debug_loc_data();
   const lldb_private::DWARFDataExtractor &get_debug_ranges_data();
+  const lldb_private::DWARFDataExtractor &get_debug_rnglists_data();
   const lldb_private::DWARFDataExtractor &get_debug_str_data();
   const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data();
   const lldb_private::DWARFDataExtractor &get_debug_types_data();
@@ -474,6 +476,7 @@ protected:
   DWARFDataSegment m_data_debug_macro;
   DWARFDataSegment m_data_debug_loc;
   DWARFDataSegment m_data_debug_ranges;
+  DWARFDataSegment m_data_debug_rnglists;
   DWARFDataSegment m_data_debug_str;
   DWARFDataSegment m_data_debug_str_offsets;
   DWARFDataSegment m_data_debug_types;
index fe80b25..3711a66 100644 (file)
@@ -358,6 +358,7 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
           case eSectionTypeDWARFDebugPubNames:
           case eSectionTypeDWARFDebugPubTypes:
           case eSectionTypeDWARFDebugRanges:
+          case eSectionTypeDWARFDebugRngLists:
           case eSectionTypeDWARFDebugStr:
           case eSectionTypeDWARFDebugStrOffsets:
           case eSectionTypeDWARFDebugTypes: