jankratochvil updated this revision to Diff 187169.
jankratochvil added a comment.

> So if we have 3GB of .debug_info and 1GB of .debug_types, we are expecting to 
> allocate a heap based buffer and copy all the data into this? This will fail.

That fallback code path is used only when there is no way to access 
`.debug_info` and `.debug_types` from mmapped area.  I was thinking that 
fallback would be used for example for Linux vDSO which needs to be read by 
`Process::ReadModuleFromMemory()` but that has only about 16KB so its size does 
not matter.  But maybe on OSX (or for GDB JIT modules) the data can be bigger 
so in this patch I have implemented the most effective merging of non-mmapped 
sections.


Repository:
  rLLDB LLDB

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D51578/new/

https://reviews.llvm.org/D51578

Files:
  lldb/include/lldb/Symbol/ObjectFile.h
  lldb/include/lldb/lldb-enumerations.h
  lldb/source/Core/Section.cpp
  lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
  lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
  lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
  lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
  lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
  lldb/source/Symbol/ObjectFile.cpp

Index: lldb/source/Symbol/ObjectFile.cpp
===================================================================
--- lldb/source/Symbol/ObjectFile.cpp
+++ lldb/source/Symbol/ObjectFile.cpp
@@ -365,6 +365,7 @@
           case eSectionTypeDWARFDebugStrOffsets:
           case eSectionTypeDWARFDebugStrOffsetsDwo:
           case eSectionTypeDWARFDebugTypes:
+          case eSectionTypeDWARFDebugTypesDwo:
           case eSectionTypeDWARFAppleNames:
           case eSectionTypeDWARFAppleTypes:
           case eSectionTypeDWARFAppleNamespaces:
@@ -533,19 +534,54 @@
   return 0;
 }
 
-//----------------------------------------------------------------------
-// Get the section data the file on disk
-//----------------------------------------------------------------------
-size_t ObjectFile::ReadSectionData(
-    const SectionPart &section_part, DataExtractor &section_data) {
+size_t ObjectFile::ReadSectionData(const SectionPart &section_part,
+                                   DataExtractor &section_data) {
   Section *section = section_part.GetSection();
   // If some other objectfile owns this data, pass this to them.
   if (section->GetObjectFile() != this)
     return section->GetObjectFile()->ReadSectionData(
         section_part, section_data);
 
-  if (IsInMemory()) {
-    ProcessSP process_sp(m_process_wp.lock());
+  auto reader_up = SectionReaderFactory(section_part);
+  if (!reader_up)
+    return 0;
+  return reader_up->read(section_data);
+}
+
+ObjectFile::SectionReader::SectionReader(const SectionPart &section_part_)
+    : section_part(section_part_) {}
+
+std::unique_ptr<ObjectFile::SectionReader>
+ObjectFile::SectionReaderFactory(const SectionPart &section_part) {
+  // llvm::make_unique() is not a friend like we are.
+  return std::unique_ptr<SectionReader>(new SectionReader(section_part));
+}
+
+ObjectFile::SectionReader::~SectionReader() {}
+
+uint64_t ObjectFile::SectionReader::getDecompressedSize() {
+  return !section_part ? 0 : section_part.GetSection()->GetFileSize();
+}
+
+size_t ObjectFile::SectionReader::read(uint8_t *dst) {
+  if (!section_part)
+    return 0;
+  Section *section = section_part.GetSection();
+  return section->GetObjectFile()->ObjectFile::ReadSectionData(section,
+      section_part.GetOffsetInSection(), dst, section_part.GetLength());
+}
+
+//----------------------------------------------------------------------
+// Get the section data the file on disk
+//----------------------------------------------------------------------
+size_t ObjectFile::SectionReader::read(DataExtractor &section_data) {
+  if (!section_part)
+    return 0;
+  Section *section = section_part.GetSection();
+  ObjectFile *obj_file = section->GetObjectFile();
+
+  if (obj_file->IsInMemory()) {
+    ProcessSP process_sp(obj_file->GetProcessWP().lock());
     if (process_sp) {
       const addr_t base_load_addr =
           section->GetLoadBaseAddress(&process_sp->GetTarget());
@@ -566,10 +602,10 @@
     // The object file now contains a full mmap'ed copy of the object file
     // data, so just use this
     if (!section->IsRelocated())
-      RelocateSection(section);
+      obj_file->RelocateSection(section);
   }
-  return GetData(section_part.GetOffsetInFile(), section_part.GetLength(),
-                 section_data);
+  return obj_file->GetData(section_part.GetOffsetInFile(),
+      section_part.GetLength(), section_data);
 }
 
 bool ObjectFile::SplitArchivePathWithObject(const char *path_with_object,
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -47,9 +47,10 @@
 
   const lldb_private::DWARFDataExtractor &get_debug_abbrev_data() override;
   const lldb_private::DWARFDataExtractor &get_debug_addr_data() override;
-  const lldb_private::DWARFDataExtractor &get_debug_info_data() override;
+  lldb_private::SectionPart get_debug_info_section_part() override;
   const lldb_private::DWARFDataExtractor &get_debug_str_data() override;
   const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data() override;
+  lldb_private::SectionPart get_debug_types_section_part() override;
 
 protected:
   lldb_private::SectionPart GetSectionPart(
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -124,8 +124,8 @@
   return m_data_debug_addr.m_data;
 }
 
-const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_info_data() {
-  return GetCachedSectionData(eSectionTypeDWARFDebugInfoDwo, m_data_debug_info);
+SectionPart SymbolFileDWARFDwo::get_debug_info_section_part() {
+  return GetSectionPart(eSectionTypeDWARFDebugInfoDwo);
 }
 
 const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_str_data() {
@@ -137,6 +137,10 @@
                               m_data_debug_str_offsets);
 }
 
+SectionPart SymbolFileDWARFDwo::get_debug_types_section_part() {
+  return GetSectionPart(eSectionTypeDWARFDebugTypesDwo);
+}
+
 SymbolFileDWARF *SymbolFileDWARFDwo::GetBaseSymbolFile() {
   return m_base_dwarf_cu->GetSymbolFileDWARF();
 }
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -234,7 +234,8 @@
   virtual const lldb_private::DWARFDataExtractor &get_debug_addr_data();
   const lldb_private::DWARFDataExtractor &get_debug_aranges_data();
   const lldb_private::DWARFDataExtractor &get_debug_frame_data();
-  virtual const lldb_private::DWARFDataExtractor &get_debug_info_data();
+  const lldb_private::DWARFDataExtractor &get_debug_info_data();
+  virtual lldb_private::SectionPart get_debug_info_section_part();
   const lldb_private::DWARFDataExtractor &get_debug_line_data();
   const lldb_private::DWARFDataExtractor &get_debug_line_str_data();
   const lldb_private::DWARFDataExtractor &get_debug_macro_data();
@@ -244,7 +245,7 @@
   const lldb_private::DWARFDataExtractor &get_debug_rnglists_data();
   virtual const lldb_private::DWARFDataExtractor &get_debug_str_data();
   virtual const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data();
-  const lldb_private::DWARFDataExtractor &get_debug_types_data();
+  virtual lldb_private::SectionPart get_debug_types_section_part();
   const lldb_private::DWARFDataExtractor &get_apple_names_data();
   const lldb_private::DWARFDataExtractor &get_apple_types_data();
   const lldb_private::DWARFDataExtractor &get_apple_namespaces_data();
@@ -324,6 +325,13 @@
 
   void DumpClangAST(lldb_private::Stream &s) override;
 
+  uint64_t get_debug_info_size() const {
+    return m_debug_info_concatenated_info_size;
+  }
+  uint64_t get_debug_types_offset() const {
+    return m_debug_info_concatenated_types_offset;
+  }
+
 protected:
   typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
       DIEToTypePtr;
@@ -474,7 +482,6 @@
   DWARFDataSegment m_data_debug_addr;
   DWARFDataSegment m_data_debug_aranges;
   DWARFDataSegment m_data_debug_frame;
-  DWARFDataSegment m_data_debug_info;
   DWARFDataSegment m_data_debug_line;
   DWARFDataSegment m_data_debug_line_str;
   DWARFDataSegment m_data_debug_macro;
@@ -484,13 +491,21 @@
   DWARFDataSegment m_data_debug_rnglists;
   DWARFDataSegment m_data_debug_str;
   DWARFDataSegment m_data_debug_str_offsets;
-  DWARFDataSegment m_data_debug_types;
   DWARFDataSegment m_data_apple_names;
   DWARFDataSegment m_data_apple_types;
   DWARFDataSegment m_data_apple_namespaces;
   DWARFDataSegment m_data_apple_objc;
   DWARFDataSegment m_data_gnu_debugaltlink;
 
+  llvm::once_flag m_concatenated_data_once;
+  // For get_debug_info_data() containing both '.debug_info' and '.debug_types'.
+  lldb_private::DWARFDataExtractor m_data_debug_info_concatenated;
+  // First part of m_data_debug_info_concatenated containing '.debug_info'.
+  uint64_t m_debug_info_concatenated_info_size;
+  // Start of second part of m_data_debug_info_concatenated containing
+  // '.debug_types'.  There may be a gap between those two sections.
+  uint64_t m_debug_info_concatenated_types_offset;
+
   // The unique pointer items below are generated on demand if and when someone
   // accesses
   // them through a non const version of this class.
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -8,6 +8,7 @@
 
 #include "SymbolFileDWARF.h"
 
+#include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Threading.h"
 
@@ -356,7 +357,7 @@
                                           // when this class parses .o files to
                                           // contain the .o file index/ID
       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_aranges(), m_data_debug_frame(),
       m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(),
       m_data_debug_ranges(), m_data_debug_rnglists(), m_data_debug_str(),
       m_data_apple_names(), m_data_apple_types(), m_data_apple_namespaces(),
@@ -550,7 +551,8 @@
   const SectionList *section_list = module_sp->GetSectionList();
   if (section_list) {
     Section *section = section_list->FindSectionByType(sect_type, true).get();
-    if (section)
+    // The size check is just a performance optimization.
+    if (section && (section->GetByteSize() || section->GetFileSize()))
       return section;
   }
   return SectionPart();
@@ -594,8 +596,8 @@
   return GetCachedSectionData(eSectionTypeDWARFDebugFrame, m_data_debug_frame);
 }
 
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_info_data() {
-  return GetCachedSectionData(eSectionTypeDWARFDebugInfo, m_data_debug_info);
+SectionPart SymbolFileDWARF::get_debug_info_section_part() {
+  return GetSectionPart(eSectionTypeDWARFDebugInfo);
 }
 
 const DWARFDataExtractor &SymbolFileDWARF::get_debug_line_data() {
@@ -645,8 +647,8 @@
                               m_data_debug_str_offsets);
 }
 
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_types_data() {
-  return GetCachedSectionData(eSectionTypeDWARFDebugTypes, m_data_debug_types);
+SectionPart SymbolFileDWARF::get_debug_types_section_part() {
+  return GetSectionPart(eSectionTypeDWARFDebugTypes);
 }
 
 const DWARFDataExtractor &SymbolFileDWARF::get_apple_names_data() {
@@ -671,6 +673,64 @@
                               m_data_gnu_debugaltlink);
 }
 
+const DWARFDataExtractor &SymbolFileDWARF::get_debug_info_data() {
+  llvm::call_once(m_concatenated_data_once, [&] {
+    const SectionPart debug_info_part = get_debug_info_section_part();
+    const SectionPart debug_types_part = get_debug_types_section_part();
+    if (!debug_info_part && !debug_types_part)
+      return;
+    // For this optimization of mmapped sections we do not handle .debug_types
+    // present without .debug_info as that should not happen.
+    if (!m_obj_file->IsInMemory() && debug_info_part
+        && !debug_info_part.GetSection()->Test(llvm::ELF::SHF_COMPRESSED)
+        && (!debug_types_part
+            || (!debug_types_part.GetSection()->Test(llvm::ELF::SHF_COMPRESSED)
+                && debug_info_part.GetOffsetInFile()
+                        + debug_info_part.GetLength()
+                    <= debug_types_part.GetOffsetInFile()))) {
+      m_debug_info_concatenated_info_size = debug_info_part.GetLength();
+      uint64_t length;
+      if (debug_types_part) {
+        m_debug_info_concatenated_types_offset =
+            debug_types_part.GetOffsetInFile()
+            - debug_info_part.GetOffsetInFile();
+        length = debug_types_part.GetOffsetInFile()
+            + debug_types_part.GetLength() - debug_info_part.GetOffsetInFile();
+      } else {
+        m_debug_info_concatenated_types_offset = debug_info_part.GetLength();
+        length = debug_info_part.GetLength();
+      }
+      if (m_dwarf_data.GetByteSize())
+        m_data_debug_info_concatenated.SetData(m_dwarf_data,
+            debug_info_part.GetOffsetInParentSection(), length);
+      else
+        m_obj_file->GetData(debug_info_part.GetOffsetInFile(),
+            length, m_data_debug_info_concatenated);
+      if (m_data_debug_info_concatenated.GetByteSize() != length)
+        m_data_debug_info_concatenated.Clear();
+      return;
+    }
+    auto debug_info_reader = m_obj_file->SectionReaderFactory(debug_info_part);
+    auto debug_types_reader = m_obj_file->SectionReaderFactory(
+        debug_types_part);
+    const auto info_len = debug_info_reader->getDecompressedSize();
+    const auto types_len = debug_types_reader->getDecompressedSize();
+    DataBufferSP databuffer = DataBufferSP(
+        new DataBufferHeap(info_len + types_len, 0));
+    if (debug_info_reader->read(databuffer->GetBytes()) != info_len
+        || debug_types_reader->read(databuffer->GetBytes() + info_len)
+            != types_len)
+      return;
+    m_debug_info_concatenated_info_size = info_len;
+    m_debug_info_concatenated_types_offset = info_len;
+    m_data_debug_info_concatenated.SetData(databuffer);
+    m_data_debug_info_concatenated.SetByteOrder(m_obj_file->GetByteOrder());
+    m_data_debug_info_concatenated.SetAddressByteSize(
+        m_obj_file->GetAddressByteSize());
+  });
+  return m_data_debug_info_concatenated;
+}
+
 DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
   if (m_abbr == NULL) {
     const DWARFDataExtractor &debug_abbrev_data = get_debug_abbrev_data();
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -69,7 +69,7 @@
   /// @return
   ///   The correct data for the DIE information in this unit.
   //------------------------------------------------------------------
-  virtual const lldb_private::DWARFDataExtractor &GetData() const = 0;
+  const lldb_private::DWARFDataExtractor &GetData() const;
   //------------------------------------------------------------------
   /// Get the size in bytes of the compile unit header.
   ///
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -873,3 +873,6 @@
   return *m_func_aranges_up;
 }
 
+const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const {
+  return m_dwarf->get_debug_info_data();
+}
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -98,7 +98,8 @@
       lldb::offset_t offset = 0;
       DWARFUnitSP cu_sp;
       const auto &debug_info_data = m_dwarf2Data->get_debug_info_data();
-      while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data,
+      while (offset < m_dwarf2Data->get_debug_info_size()
+          && (cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data,
                                                 &offset))) {
         m_compile_units.push_back(cu_sp);
 
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -18,16 +18,6 @@
                              lldb::offset_t *offset_ptr);
   void Dump(lldb_private::Stream *s) const override;
 
-  //------------------------------------------------------------------
-  /// Get the data that contains the DIE information for this unit.
-  ///
-  /// @return
-  ///   The correct data (.debug_types for DWARF 4 and earlier, and
-  ///   .debug_info for DWARF 5 and later) for the DIE information in
-  ///   this unit.
-  //------------------------------------------------------------------
-  const lldb_private::DWARFDataExtractor &GetData() const override;
-
   //------------------------------------------------------------------
   /// Get the size in bytes of the header.
   ///
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -89,7 +89,3 @@
   }
   llvm_unreachable("invalid UnitType.");
 }
-
-const lldb_private::DWARFDataExtractor &DWARFCompileUnit::GetData() const {
-  return m_dwarf->get_debug_info_data();
-}
Index: lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -1212,6 +1212,7 @@
           case eSectionTypeDWARFDebugStrOffsets:
           case eSectionTypeDWARFDebugStrOffsetsDwo:
           case eSectionTypeDWARFDebugTypes:
+          case eSectionTypeDWARFDebugTypesDwo:
           case eSectionTypeDWARFAppleNames:
           case eSectionTypeDWARFAppleTypes:
           case eSectionTypeDWARFAppleNamespaces:
Index: lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
===================================================================
--- lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
+++ lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
@@ -82,9 +82,10 @@
                          lldb::offset_t section_offset, void *dst,
                          size_t dst_len) override;
 
-  size_t
-  ReadSectionData(const lldb_private::SectionPart &section_part,
-                  lldb_private::DataExtractor &section_data) override;
+  std::unique_ptr<SectionReader> SectionReaderFactory(
+      const lldb_private::SectionPart &section_part) override;
+
+  class SectionReaderJIT;
 
   lldb_private::Address GetEntryPointAddress() override;
 
Index: lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
+++ lldb/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -242,21 +242,44 @@
   return 0;
 }
 
-size_t ObjectFileJIT::ReadSectionData(
-    const lldb_private::SectionPart &section_part,
-    lldb_private::DataExtractor &section_data) {
-  if (section_part.GetLength()) {
-    const void *src = (void *)(uintptr_t)section_part.GetOffsetInFile();
-
-    DataBufferSP data_sp(
-        new lldb_private::DataBufferHeap(src, section_part.GetLength()));
-    if (data_sp) {
-      section_data.SetData(data_sp, 0, data_sp->GetByteSize());
-      section_data.SetByteOrder(GetByteOrder());
-      section_data.SetAddressByteSize(GetAddressByteSize());
-      return section_data.GetByteSize();
-    }
+class ObjectFileJIT::SectionReaderJIT : public ObjectFile::SectionReader {
+public:
+  SectionReaderJIT(const SectionPart &section_part_);
+  size_t read(DataExtractor &section_data) override;
+  size_t read(uint8_t *dst) override;
+};
+
+ObjectFileJIT::SectionReaderJIT::SectionReaderJIT(
+    const SectionPart &section_part_)
+    : ObjectFile::SectionReader(section_part_) {
+  assert(section_part.GetLength());
+}
+
+size_t ObjectFileJIT::SectionReaderJIT::read(DataExtractor &section_data) {
+  const void *src = (void *)(uintptr_t)section_part.GetOffsetInFile();
+
+  DataBufferSP data_sp(new DataBufferHeap(src, section_part.GetLength()));
+  if (data_sp) {
+    Section *section = section_part.GetSection();
+    ObjectFile *obj_file = section->GetObjectFile();
+
+    section_data.SetData(data_sp, 0, data_sp->GetByteSize());
+    section_data.SetByteOrder(obj_file->GetByteOrder());
+    section_data.SetAddressByteSize(obj_file->GetAddressByteSize());
+    return section_data.GetByteSize();
   }
   section_data.Clear();
   return 0;
 }
+
+size_t ObjectFileJIT::SectionReaderJIT::read(uint8_t *dst) {
+  Section *section = section_part.GetSection();
+  ObjectFile *obj_file = section->GetObjectFile();
+  return obj_file->ReadSectionData(section, section_part.GetOffsetInSection(),
+      dst, section_part.GetLength());
+}
+
+std::unique_ptr<ObjectFile::SectionReader>
+ObjectFileJIT::SectionReaderFactory(const SectionPart &section_part) {
+  return llvm::make_unique<SectionReaderJIT>(section_part);
+}
Index: lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
===================================================================
--- lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -139,13 +139,11 @@
 
   ObjectFile::Strata CalculateStrata() override;
 
+  using lldb_private::ObjectFile::ReadSectionData;
   size_t ReadSectionData(lldb_private::Section *section,
                          lldb::offset_t section_offset, void *dst,
                          size_t dst_len) override;
 
-  size_t ReadSectionData(const lldb_private::SectionPart &section_part,
-                         lldb_private::DataExtractor &section_data) override;
-
   llvm::ArrayRef<elf::ELFProgramHeader> ProgramHeaders();
   lldb_private::DataExtractor GetSegmentData(const elf::ELFProgramHeader &H);
 
@@ -154,6 +152,11 @@
 
   void RelocateSection(lldb_private::Section *section) override;
 
+  std::unique_ptr<SectionReader> SectionReaderFactory(
+      const lldb_private::SectionPart &section_part) override;
+
+  class SectionReaderCompressed;
+
 protected:
 
   std::vector<LoadableData>
Index: lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -34,6 +34,7 @@
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/Decompressor.h"
+#include "llvm/Object/ELF.h"
 #include "llvm/Support/ARMBuildAttributes.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -1768,6 +1769,7 @@
       .Case(".debug_str_offsets", eSectionTypeDWARFDebugStrOffsets)
       .Case(".debug_str_offsets.dwo", eSectionTypeDWARFDebugStrOffsetsDwo)
       .Case(".debug_types", eSectionTypeDWARFDebugTypes)
+      .Case(".debug_types.dwo", eSectionTypeDWARFDebugTypesDwo)
       .Case(".eh_frame", eSectionTypeEHFrame)
       .Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink)
       .Case(".gosymtab", eSectionTypeGoSymtab)
@@ -3391,58 +3393,113 @@
   return data.CopyData(section_offset, dst_len, dst);
 }
 
-size_t ObjectFileELF::ReadSectionData(const SectionPart &section_part,
-                                      DataExtractor &section_data) {
-  Section *section = section_part.GetSection();
-  // If some other objectfile owns this data, pass this to them.
-  if (section->GetObjectFile() != this)
-    return section->GetObjectFile()->ReadSectionData(
-        section_part, section_data);
+class ObjectFileELF::SectionReaderCompressed
+    : public ObjectFile::SectionReader {
+public:
+  SectionReaderCompressed(const SectionPart &section_part_);
+  uint64_t getDecompressedSize() override;
+  size_t read(DataExtractor &section_data) override;
+  size_t read(uint8_t *dst) override;
+  ~SectionReaderCompressed();
+private:
+  static llvm::Expected<llvm::object::Decompressor> Initialize(
+      const SectionPart &section_part, DataExtractor &compressed_data);
+  DataExtractor compressed_data;
+  // 'decompressor' Initialize() requires already initialized 'compressed_data'.
+  llvm::Expected<llvm::object::Decompressor> decompressor;
+};
 
-  size_t result = ObjectFile::ReadSectionData(section, section_data);
-  if (result == 0 || !section->Test(SHF_COMPRESSED))
-    return result;
+ObjectFileELF::SectionReaderCompressed::SectionReaderCompressed(
+    const SectionPart &section_part_)
+    : ObjectFile::SectionReader(section_part_),
+    decompressor(Initialize(section_part_, compressed_data)) {}
 
+ObjectFileELF::SectionReaderCompressed::~SectionReaderCompressed() {
+  if (decompressor.takeError()) {}
+}
+
+llvm::Expected<llvm::object::Decompressor>
+ObjectFileELF::SectionReaderCompressed::Initialize(
+    const SectionPart &section_part, DataExtractor &compressed_data) {
+  Section *section = section_part.GetSection();
+  ObjectFile *obj_file = section->GetObjectFile();
   if (section_part.GetOffsetInSection() != 0
       || section_part.GetLength() != section->GetFileSize()) {
-    GetModule()->ReportWarning(
+    obj_file->GetModule()->ReportWarning(
         "Unable to read only part %" PRIu64 "+%" PRIu64
         " of compressed section '%s'",
         section_part.GetOffsetInSection(), section_part.GetLength(),
         section->GetName().GetCString());
-    section_data.Clear();
-    return 0;
+    return llvm::object::createError(
+        "Unable to read only part of compressed section");
   }
-
-  auto Decompressor = llvm::object::Decompressor::create(
+  {
+    auto reader_up = obj_file->ObjectFile::SectionReaderFactory(section_part);
+    if (!reader_up
+        || reader_up->read(compressed_data) != section->GetFileSize())
+      return llvm::object::createError("ReadSectionData failed");
+  }
+  auto decompressor = llvm::object::Decompressor::create(
       section->GetName().GetStringRef(),
-      {reinterpret_cast<const char *>(section_data.GetDataStart()),
-       size_t(section_data.GetByteSize())},
-      GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
-  if (!Decompressor) {
-    GetModule()->ReportWarning(
+      {reinterpret_cast<const char *>(compressed_data.GetDataStart()),
+       size_t(compressed_data.GetByteSize())},
+      obj_file->GetByteOrder() == eByteOrderLittle,
+      obj_file->GetAddressByteSize() == 8);
+  if (!decompressor)
+    obj_file->GetModule()->ReportWarning(
         "Unable to initialize decompressor for section '%s': %s",
         section->GetName().GetCString(),
-        llvm::toString(Decompressor.takeError()).c_str());
-    section_data.Clear();
+        llvm::toString(decompressor.takeError()).c_str());
+  return decompressor;
+}
+
+uint64_t ObjectFileELF::SectionReaderCompressed::getDecompressedSize() {
+  if (!decompressor)
     return 0;
+  return decompressor->getDecompressedSize();
+}
+
+size_t ObjectFileELF::SectionReaderCompressed::read(
+    DataExtractor &section_data) {
+  auto buffer_sp = std::make_shared<DataBufferHeap>(getDecompressedSize(), 0);
+  size_t retval = read(buffer_sp->GetBytes());
+  if (retval == 0)
+    section_data.Clear();
+  else {
+    Section *section = section_part.GetSection();
+    ObjectFile *obj_file = section->GetObjectFile();
+
+    section_data.SetData(buffer_sp);
+    section_data.SetByteOrder(obj_file->GetByteOrder());
+    section_data.SetAddressByteSize(obj_file->GetAddressByteSize());
   }
+  return retval;
+}
 
-  auto buffer_sp =
-      std::make_shared<DataBufferHeap>(Decompressor->getDecompressedSize(), 0);
-  if (auto error = Decompressor->decompress(
-          {reinterpret_cast<char *>(buffer_sp->GetBytes()),
-           size_t(buffer_sp->GetByteSize())})) {
-    GetModule()->ReportWarning(
+size_t ObjectFileELF::SectionReaderCompressed::read(uint8_t *dst) {
+  if (!decompressor)
+    return 0;
+  if (auto error = decompressor->decompress(
+          {reinterpret_cast<char *>(dst), size_t(getDecompressedSize())})) {
+    Section *section = section_part.GetSection();
+    ObjectFile *obj_file = section->GetObjectFile();
+    obj_file->GetModule()->ReportWarning(
         "Decompression of section '%s' failed: %s",
         section->GetName().GetCString(),
         llvm::toString(std::move(error)).c_str());
-    section_data.Clear();
     return 0;
   }
+  return getDecompressedSize();
+}
 
-  section_data.SetData(buffer_sp);
-  return buffer_sp->GetByteSize();
+std::unique_ptr<ObjectFile::SectionReader>
+ObjectFileELF::SectionReaderFactory(const SectionPart &section_part) {
+  if (!section_part)
+    return ObjectFile::SectionReaderFactory(section_part);
+  Section *section = section_part.GetSection();
+  if (section->GetFileSize() == 0 || !section->Test(SHF_COMPRESSED))
+    return ObjectFile::SectionReaderFactory(section_part);
+  return llvm::make_unique<SectionReaderCompressed>(section_part);
 }
 
 llvm::ArrayRef<ELFProgramHeader> ObjectFileELF::ProgramHeaders() {
Index: lldb/source/Core/Section.cpp
===================================================================
--- lldb/source/Core/Section.cpp
+++ lldb/source/Core/Section.cpp
@@ -104,6 +104,8 @@
     return "dwarf-str-offsets-dwo";
   case eSectionTypeDWARFDebugTypes:
     return "dwarf-types";
+  case eSectionTypeDWARFDebugTypesDwo:
+    return "dwarf-types-dwo";
   case eSectionTypeDWARFDebugNames:
     return "dwarf-names";
   case eSectionTypeELFSymbolTable:
Index: lldb/include/lldb/lldb-enumerations.h
===================================================================
--- lldb/include/lldb/lldb-enumerations.h
+++ lldb/include/lldb/lldb-enumerations.h
@@ -718,6 +718,7 @@
   eSectionTypeDWARFDebugInfoDwo,
   eSectionTypeDWARFDebugStrDwo,
   eSectionTypeDWARFDebugStrOffsetsDwo,
+  eSectionTypeDWARFDebugTypesDwo,
 };
 
 FLAGS_ENUM(EmulateInstructionOptions){
Index: lldb/include/lldb/Symbol/ObjectFile.h
===================================================================
--- lldb/include/lldb/Symbol/ObjectFile.h
+++ lldb/include/lldb/Symbol/ObjectFile.h
@@ -736,8 +736,8 @@
   // This function will transparently decompress section data if the section if
   // compressed. Note that for compressed section the resulting data size may
   // be larger than what Section::GetFileSize reports.
-  virtual size_t ReadSectionData(const SectionPart &section_part,
-                                 DataExtractor &section_data);
+  size_t ReadSectionData(const SectionPart &section_part,
+                         DataExtractor &section_data);
 
   bool IsInMemory() const { return m_memory_addr != LLDB_INVALID_ADDRESS; }
 
@@ -765,6 +765,26 @@
   //------------------------------------------------------------------
   virtual std::vector<LoadableData> GetLoadableData(Target &target);
 
+  // Similar to ReadSectionData() but you can ask final (decompressed for
+  // compressed sections) size before really reading the data to an adress.
+  class SectionReader;
+  virtual std::unique_ptr<SectionReader> SectionReaderFactory(
+      const SectionPart &section_part);
+  class SectionReader {
+  public:
+    virtual uint64_t getDecompressedSize();
+    virtual size_t read(DataExtractor &section_data);
+    virtual size_t read(uint8_t *dst);
+    virtual ~SectionReader();
+  protected:
+    friend std::unique_ptr<SectionReader> ObjectFile::SectionReaderFactory(
+	const SectionPart &section_part);
+    SectionReader(const SectionPart &section_part_);
+    const SectionPart &section_part;
+  };
+
+  lldb::ProcessWP &GetProcessWP() { return m_process_wp; }
+
 protected:
   //------------------------------------------------------------------
   // Member variables.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
  • [Lldb-commits] [PATCH] ... Jan Kratochvil via Phabricator via lldb-commits

Reply via email to