forked from OSchip/llvm-project
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
This commit is contained in:
parent
786431231f
commit
e2867bc4a0
|
@ -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 §ion_data);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
config.suffixes = ['.yaml']
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 §ion_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();
|
||||
}
|
||||
|
|
|
@ -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 §ion_data) override;
|
||||
|
||||
// Returns number of program headers found in the ELF file.
|
||||
size_t GetProgramHeaderCount();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue