summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Labath <labath@google.com>2017-12-15 14:23:58 +0000
committerPavel Labath <labath@google.com>2017-12-15 14:23:58 +0000
commite2867bc4a07b942724fa3be95c6c671b196fe1ae (patch)
tree28b1d7e03a3c5313a17f7ae6ff86e31b920cc7d8
parent786431231f8916e36477d4fba07ce158adddce4e (diff)
downloadbcm5719-llvm-e2867bc4a07b942724fa3be95c6c671b196fe1ae.tar.gz
bcm5719-llvm-e2867bc4a07b942724fa3be95c6c671b196fe1ae.zip
ObjectFileELF: Add support for compressed sections
Summary: We use the llvm decompressor to decompress SHF_COMPRESSED sections. This enables us to read data from debug info sections, which are sometimes compressed, particuarly in the split-dwarf case. This functionality is only available if llvm is compiled with zlib support. Reviewers: clayborg, zturner Subscribers: emaste, mgorny, aprantl, lldb-commits Differential Revision: https://reviews.llvm.org/D40616 llvm-svn: 320813
-rw-r--r--lldb/include/lldb/Symbol/ObjectFile.h9
-rw-r--r--lldb/lit/CMakeLists.txt3
-rw-r--r--lldb/lit/Modules/compressed-sections.yaml30
-rw-r--r--lldb/lit/Modules/lit.local.cfg1
-rw-r--r--lldb/lit/lit.cfg7
-rw-r--r--lldb/lit/lit.site.cfg.in1
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp55
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h7
-rw-r--r--lldb/tools/lldb-test/lldb-test.cpp3
-rw-r--r--lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp3
10 files changed, 116 insertions, 3 deletions
diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h
index 0708b7c47f3..3f9250af7e0 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -793,15 +793,24 @@ public:
static lldb::DataBufferSP ReadMemory(const lldb::ProcessSP &process_sp,
lldb::addr_t addr, size_t byte_size);
+ // This function returns raw file contents. Do not use it if you want
+ // transparent decompression of section contents.
size_t GetData(lldb::offset_t offset, size_t length,
DataExtractor &data) const;
+ // This function returns raw file contents. Do not use it if you want
+ // transparent decompression of section contents.
size_t CopyData(lldb::offset_t offset, size_t length, void *dst) const;
+ // This function will transparently decompress section data if the section if
+ // compressed.
virtual size_t ReadSectionData(Section *section,
lldb::offset_t section_offset, void *dst,
size_t dst_len);
+ // 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(Section *section,
DataExtractor &section_data);
diff --git a/lldb/lit/CMakeLists.txt b/lldb/lit/CMakeLists.txt
index 925b833d594..5488154318a 100644
--- a/lldb/lit/CMakeLists.txt
+++ b/lldb/lit/CMakeLists.txt
@@ -22,10 +22,11 @@ configure_lit_site_cfg(
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.
diff --git a/lldb/lit/Modules/compressed-sections.yaml b/lldb/lit/Modules/compressed-sections.yaml
new file mode 100644
index 00000000000..0eabd99f2d6
--- /dev/null
+++ b/lldb/lit/Modules/compressed-sections.yaml
@@ -0,0 +1,30 @@
+# REQUIRES: zlib
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test module-sections --contents %t | FileCheck %s
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_386
+Sections:
+ - Name: .hello_elf
+ Type: SHT_PROGBITS
+ Flags: [ SHF_COMPRESSED ]
+ Content: 010000000800000001000000789c5330700848286898000009c802c1
+ - Name: .bogus
+ Type: SHT_PROGBITS
+ Flags: [ SHF_COMPRESSED ]
+ Content: deadbeefbaadf00d
+
+# CHECK: Name: .hello_elf
+# CHECK-NEXT: VM size: 0
+# CHECK-NEXT: File size: 28
+# CHECK-NEXT: Data:
+# CHECK-NEXT: 20304050 60708090
+
+# CHECK: Name: .bogus
+# CHECK-NEXT: VM size: 0
+# CHECK-NEXT: File size: 8
+# CHECK-NEXT: Data:
+# CHECK-NEXT: DEADBEEF BAADF00D
diff --git a/lldb/lit/Modules/lit.local.cfg b/lldb/lit/Modules/lit.local.cfg
new file mode 100644
index 00000000000..8169b9f95e1
--- /dev/null
+++ b/lldb/lit/Modules/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = ['.yaml']
diff --git a/lldb/lit/lit.cfg b/lldb/lit/lit.cfg
index 51f795313f3..402d03947ca 100644
--- a/lldb/lit/lit.cfg
+++ b/lldb/lit/lit.cfg
@@ -9,6 +9,9 @@ import locale
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 @@ if debugserver is not None:
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'gcc', config.cc):
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
diff --git a/lldb/lit/lit.site.cfg.in b/lldb/lit/lit.site.cfg.in
index 4088bce470f..2cfa677651a 100644
--- a/lldb/lit/lit.site.cfg.in
+++ b/lldb/lit/lit.site.cfg.in
@@ -12,6 +12,7 @@ config.target_triple = "@TARGET_TRIPLE@"
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.
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index fc42dde8284..9869a94f06b 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/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"
@@ -31,6 +32,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/Decompressor.h"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -3460,3 +3462,56 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
}
return eStrataUnknown;
}
+
+size_t ObjectFileELF::ReadSectionData(Section *section,
+ lldb::offset_t section_offset, void *dst,
+ size_t dst_len) {
+ // If some other objectfile owns this data, pass this to them.
+ if (section->GetObjectFile() != this)
+ return section->GetObjectFile()->ReadSectionData(section, section_offset,
+ dst, dst_len);
+
+ if (!section->Test(SHF_COMPRESSED))
+ return ObjectFile::ReadSectionData(section, section_offset, dst, dst_len);
+
+ // For compressed sections we need to read to full data to be able to
+ // decompress.
+ DataExtractor data;
+ ReadSectionData(section, data);
+ return data.CopyData(section_offset, dst_len, dst);
+}
+
+size_t ObjectFileELF::ReadSectionData(Section *section,
+ DataExtractor &section_data) {
+ // If some other objectfile owns this data, pass this to them.
+ if (section->GetObjectFile() != this)
+ return section->GetObjectFile()->ReadSectionData(section, section_data);
+
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
+
+ size_t result = ObjectFile::ReadSectionData(section, section_data);
+ if (result == 0 || !section->Test(SHF_COMPRESSED))
+ return result;
+
+ auto Decompressor = llvm::object::Decompressor::create(
+ section->GetName().GetStringRef(),
+ {reinterpret_cast<const char *>(section_data.GetDataStart()),
+ section_data.GetByteSize()},
+ GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
+ if (!Decompressor) {
+ LLDB_LOG(log, "Unable to initialize decompressor for section {0}: {1}",
+ section->GetName(), llvm::toString(Decompressor.takeError()));
+ return result;
+ }
+ 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 result;
+ }
+ section_data.SetData(buffer_sp);
+ return buffer_sp->GetByteSize();
+}
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index e3a267a8d85..2909f4e52e4 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -140,6 +140,13 @@ public:
ObjectFile::Strata CalculateStrata() override;
+ size_t ReadSectionData(lldb_private::Section *section,
+ lldb::offset_t section_offset, void *dst,
+ size_t dst_len) 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();
diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp
index 723093dee05..1fe2f5b6385 100644
--- a/lldb/tools/lldb-test/lldb-test.cpp
+++ b/lldb/tools/lldb-test/lldb-test.cpp
@@ -89,7 +89,8 @@ static void dumpModules(Debugger &Dbg) {
assert(S);
Printer.formatLine("Index: {0}", I);
Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
- Printer.formatLine("Length: {0}", S->GetByteSize());
+ Printer.formatLine("VM size: {0}", S->GetByteSize());
+ Printer.formatLine("File size: {0}", S->GetFileSize());
if (opts::module::SectionContents) {
DataExtractor Data;
diff --git a/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp b/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
index 16fa5f000a9..056799ee919 100644
--- a/lldb/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
+++ b/lldb/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"
OpenPOWER on IntegriCloud