Index: lldb/trunk/include/lldb/Symbol/ObjectFile.h =================================================================== --- lldb/trunk/include/lldb/Symbol/ObjectFile.h +++ lldb/trunk/include/lldb/Symbol/ObjectFile.h @@ -793,15 +793,24 @@ 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); Index: lldb/trunk/lit/CMakeLists.txt =================================================================== --- lldb/trunk/lit/CMakeLists.txt +++ lldb/trunk/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. Index: lldb/trunk/lit/Modules/compressed-sections.yaml =================================================================== --- lldb/trunk/lit/Modules/compressed-sections.yaml +++ lldb/trunk/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 Index: lldb/trunk/lit/Modules/lit.local.cfg =================================================================== --- lldb/trunk/lit/Modules/lit.local.cfg +++ lldb/trunk/lit/Modules/lit.local.cfg @@ -0,0 +1 @@ +config.suffixes = ['.yaml'] Index: lldb/trunk/lit/lit.cfg =================================================================== --- lldb/trunk/lit/lit.cfg +++ lldb/trunk/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: lldb/trunk/lit/lit.site.cfg.in =================================================================== --- lldb/trunk/lit/lit.site.cfg.in +++ lldb/trunk/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: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -140,6 +140,13 @@ 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(); Index: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ lldb/trunk/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 @@ } 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(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(Decompressor->getDecompressedSize(), 0); + if (auto Error = Decompressor->decompress( + {reinterpret_cast(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(); +} Index: lldb/trunk/tools/lldb-test/lldb-test.cpp =================================================================== --- lldb/trunk/tools/lldb-test/lldb-test.cpp +++ lldb/trunk/tools/lldb-test/lldb-test.cpp @@ -89,7 +89,8 @@ 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; Index: lldb/trunk/unittests/ObjectFile/ELF/TestObjectFileELF.cpp =================================================================== --- lldb/trunk/unittests/ObjectFile/ELF/TestObjectFileELF.cpp +++ lldb/trunk/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"