labath updated this revision to Diff 124926.
labath added a comment.

This rewrites the test in terms on the new lldb-test utility. It should be 
applied on top of https://reviews.llvm.org/D40636.

While doing that, I noticed a discrepancy in the data presented by the object
file interface -- for GetFileSize(), it would return the compressed size, but,
when reading the data, it would return the decompressed size. This seemed odd
and unwanted.

So now I fetch the decompressed size when constructing the Section object, and
make sure GetFileSize result matches what the GetSectionData returns. This is
slightly odd as well, because now if someone looks at individual section file
offsets and sizes, it will seem that multiple sections overlap. While
unfortunate, this is a situation that can arise in without the presence of
compressed sections (no linker will produce a file like that, but you can
certainly hand-craft one), and our elf parser will hapily accept these files.


https://reviews.llvm.org/D40616

Files:
  lit/CMakeLists.txt
  lit/Modules/compressed-sections.yaml
  lit/Modules/lit.local.cfg
  lit/lit.cfg
  lit/lit.site.cfg.in
  source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
  source/Plugins/ObjectFile/ELF/ObjectFileELF.h
  tools/lldb-test/lldb-test.cpp
  unittests/ObjectFile/ELF/TestObjectFileELF.cpp

Index: unittests/ObjectFile/ELF/TestObjectFileELF.cpp
===================================================================
--- unittests/ObjectFile/ELF/TestObjectFileELF.cpp
+++ unittests/ObjectFile/ELF/TestObjectFileELF.cpp
@@ -10,12 +10,13 @@
 
 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
 #include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
+#include "TestingSupport/TestUtilities.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Host/HostInfo.h"
-#include "TestingSupport/TestUtilities.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/Support/Compression.h"
 #include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
Index: tools/lldb-test/lldb-test.cpp
===================================================================
--- tools/lldb-test/lldb-test.cpp
+++ tools/lldb-test/lldb-test.cpp
@@ -47,12 +47,16 @@
       assert(S);
       llvm::outs() << "  Section " << I << "\n";
       llvm::outs() << "  Name: " << S->GetName().GetStringRef() << "\n";
-      llvm::outs() << "  Length: " << S->GetByteSize() << "\n";
+      llvm::outs() << "  VM size: " << S->GetByteSize() << "\n";
+      llvm::outs() << "  File size: " << S->GetFileSize() << "\n";
 
-      lldb::offset_t Offset = 0;
       DataExtractor Data;
       S->GetSectionData(Data);
-      llvm::outs() << "  Data: " << Data.GetCStr(&Offset) << "\n\n";
+      llvm::outs() << "  Data: ";
+      for (const uint8_t *B = Data.GetDataStart(); B < Data.GetDataEnd(); ++B)
+        llvm::outs() << llvm::hexdigit(*B >> 4, true)
+                     << llvm::hexdigit(*B & 0xf, true);
+      llvm::outs() << "\n\n";
     }
   }
 }
Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.h
===================================================================
--- source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -21,6 +21,7 @@
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/UUID.h"
 #include "lldb/lldb-private.h"
+#include "llvm/Object/Decompressor.h"
 
 #include "ELFHeader.h"
 
@@ -140,6 +141,9 @@
 
   ObjectFile::Strata CalculateStrata() override;
 
+  size_t ReadSectionData(lldb_private::Section *section,
+                         lldb_private::DataExtractor &section_data) override;
+
   // Returns number of program headers found in the ELF file.
   size_t GetProgramHeaderCount();
 
@@ -244,6 +248,11 @@
   /// Returns the number of headers parsed.
   size_t ParseSectionHeaders();
 
+  llvm::Expected<llvm::object::Decompressor>
+  GetSectionDecompressor(const ELFSectionHeaderInfo &sect);
+
+  llvm::Expected<uint64_t> GetSectionFileSize(const ELFSectionHeaderInfo &sect);
+
   static void ParseARMAttributes(lldb_private::DataExtractor &data,
                                  uint64_t length,
                                  lldb_private::ArchSpec &arch_spec);
Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -23,6 +23,7 @@
 #include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/DataBufferHeap.h"
 #include "lldb/Utility/DataBufferLLVM.h"
 #include "lldb/Utility/Log.h"
 #include "lldb/Utility/Status.h"
@@ -1814,7 +1815,38 @@
   return 0;
 }
 
+llvm::Expected<llvm::object::Decompressor>
+ObjectFileELF::GetSectionDecompressor(const ELFSectionHeaderInfo &sect) {
+  const uint8_t *start = m_data.PeekData(sect.sh_offset, sect.sh_size);
+  if (!start)
+    return llvm::make_error<llvm::StringError>(
+        "Invalid section file address or size.",
+        llvm::inconvertibleErrorCode());
+  llvm::StringRef data(reinterpret_cast<const char *>(start), sect.sh_size);
+
+  return llvm::object::Decompressor::create(
+      sect.section_name.GetStringRef(), data,
+      GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
+}
+
+llvm::Expected<uint64_t>
+ObjectFileELF::GetSectionFileSize(const ELFSectionHeaderInfo &sect) {
+  if (sect.sh_type == SHT_NOBITS)
+    return 0;
+
+  if (!(sect.sh_flags & SHF_COMPRESSED))
+    return sect.sh_size;
+
+  auto Decompressor = GetSectionDecompressor(sect);
+  if (!Decompressor)
+    return Decompressor.takeError();
+
+  return Decompressor->getDecompressedSize();
+}
+
 void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
+  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
+
   if (!m_sections_ap.get() && ParseSectionHeaders()) {
     m_sections_ap.reset(new SectionList());
 
@@ -1829,8 +1861,12 @@
       const ELFSectionHeaderInfo &header = *I;
 
       ConstString &name = I->section_name;
-      const uint64_t file_size =
-          header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
+      auto file_size = GetSectionFileSize(header);
+      if (!file_size) {
+        LLDB_LOG(log, "Ignoring section {0}: {1}", name,
+                 llvm::toString(file_size.takeError()));
+        continue;
+      }
       const uint64_t vm_size = header.sh_flags & SHF_ALLOC ? header.sh_size : 0;
 
       static ConstString g_sect_name_text(".text");
@@ -2018,7 +2054,7 @@
           addr,                // VM address.
           vm_size,             // VM size in bytes of this section.
           header.sh_offset,    // Offset of this section in the file.
-          file_size,           // Size of the section as found in the file.
+          *file_size,          // Size of the section as found in the file.
           log2align,           // Alignment of the section
           header.sh_flags,     // Flags for this section.
           target_bytes_size)); // Number of host bytes per target byte
@@ -3452,3 +3488,32 @@
   }
   return eStrataUnknown;
 }
+
+size_t ObjectFileELF::ReadSectionData(Section *section,
+                                      DataExtractor &section_data) {
+  Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
+
+  if (section->GetObjectFile() != this)
+    return section->GetObjectFile()->ReadSectionData(section, section_data);
+  if (section->GetFileSize() == 0)
+    return 0;
+  if (!section->Test(SHF_COMPRESSED))
+    return ObjectFile::ReadSectionData(section, section_data);
+
+  const ELFSectionHeaderInfo *info = GetSectionHeaderByIndex(section->GetID());
+  // Decompressor construction checked in GetSectionFileSize. Only valid
+  // sections are created.
+  auto Decompressor = llvm::cantFail(GetSectionDecompressor(*info));
+  auto buffer_sp =
+      std::make_shared<DataBufferHeap>(Decompressor.getDecompressedSize(), 0);
+  if (auto Error = Decompressor.decompress(
+          {reinterpret_cast<char *>(buffer_sp->GetBytes()),
+           buffer_sp->GetByteSize()})) {
+    LLDB_LOG(log, "Decompression of section {0} failed: {1}",
+             section->GetName(), llvm::toString(std::move(Error)));
+    return 0;
+  }
+
+  section_data.SetData(buffer_sp);
+  return buffer_sp->GetByteSize();
+}
Index: lit/lit.site.cfg.in
===================================================================
--- lit/lit.site.cfg.in
+++ lit/lit.site.cfg.in
@@ -12,6 +12,7 @@
 config.python_executable = "@PYTHON_EXECUTABLE@"
 config.cc = "@LLDB_TEST_C_COMPILER@"
 config.cxx = "@LLDB_TEST_CXX_COMPILER@"
+config.have_zlib = @HAVE_LIBZ@
 
 # Support substitution of the tools and libs dirs with user parameters. This is
 # used when we can't determine the tool dir at configuration time.
Index: lit/lit.cfg
===================================================================
--- lit/lit.cfg
+++ lit/lit.cfg
@@ -9,6 +9,9 @@
 import lit.formats
 import lit.util
 
+def binary_feature(on, feature, off_prefix):
+  return feature if on else off_prefix + feature
+
 # Configuration file for the 'lit' test runner.
 
 # name: The name of this test suite.
@@ -81,6 +84,8 @@
     config.substitutions.append(('%debugserver', debugserver))
 
 for pattern in [r"\bFileCheck\b",
+                r"\blldb-test\b",
+                r"\byaml2obj\b",
                 r"\| \bnot\b"]:
     tool_match = re.match(r"^(\\)?((\| )?)\W+b([0-9A-Za-z-_]+)\\b\W*$",
                           pattern)
@@ -125,6 +130,8 @@
 elif re.match(r'cl', config.cc):
     config.available_features.add("compiler-msvc")
 
+config.available_features.add(binary_feature(config.have_zlib, "zlib", "no"))
+
 # llvm-config knows whether it is compiled with asserts (and)
 # whether we are operating in release/debug mode.
 import subprocess
Index: lit/Modules/lit.local.cfg
===================================================================
--- /dev/null
+++ lit/Modules/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = ['.yaml']
Index: lit/Modules/compressed-sections.yaml
===================================================================
--- /dev/null
+++ lit/Modules/compressed-sections.yaml
@@ -0,0 +1,23 @@
+# REQUIRES: zlib
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test module %t | FileCheck %s
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS32
+  Data:            ELFDATA2LSB
+  Type:            ET_REL
+  Machine:         EM_386
+Sections:
+  - Name:            .hello_elf
+# CHECK: Section 1
+# CHECK: Name: .hello_elf
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_COMPRESSED ]
+    Content:         010000000800000001000000789c5330700848286898000009c802c1
+# CHECK: File size: 8
+# CHECK: Data: 2030405060708090
+  - Name:            .bogus
+# CHECK-NOT: .bogus
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_COMPRESSED ]
+    Content:         deadbeefbaadf00d
Index: lit/CMakeLists.txt
===================================================================
--- lit/CMakeLists.txt
+++ lit/CMakeLists.txt
@@ -22,10 +22,11 @@
 set(LLDB_TEST_DEPS
   LLDBUnitTests
   lldb
+  lldb-test
   )
 
 if(NOT LLDB_BUILT_STANDALONE)
-  list(APPEND LLDB_TEST_DEPS FileCheck not)
+  list(APPEND LLDB_TEST_DEPS FileCheck not yaml2obj)
 endif()
   
 # lldb-server is not built on every platform.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to