labath created this revision.
Herald added subscribers: aprantl, mgorny, emaste.
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.
https://reviews.llvm.org/D40616
Files:
source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
source/Plugins/ObjectFile/ELF/ObjectFileELF.h
unittests/ObjectFile/ELF/CMakeLists.txt
unittests/ObjectFile/ELF/Inputs/compressed-sections.yaml
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"
@@ -97,3 +98,42 @@
ASSERT_NE(nullptr, start);
EXPECT_EQ(text_sp, start->GetAddress().GetSection());
}
+
+TEST_F(ObjectFileELFTest, CompressedSections) {
+ if (!llvm::zlib::isAvailable()) {
+ GTEST_LOG_(WARNING)
+ << "Test skipped because the decompression library is not available.";
+ return;
+ }
+ std::string yaml = GetInputFilePath("compressed-sections.yaml");
+ llvm::SmallString<128> obj;
+ ASSERT_NO_ERROR(llvm::sys::fs::createTemporaryFile(
+ "compressed-sections-%%%%%%", "obj", obj));
+
+ llvm::FileRemover remover(obj);
+ const char *args[] = {YAML2OBJ, yaml.c_str(), nullptr};
+ llvm::StringRef obj_ref = obj;
+ const llvm::Optional<llvm::StringRef> redirects[] = {llvm::None, obj_ref,
+ llvm::None};
+ ASSERT_EQ(0, llvm::sys::ExecuteAndWait(YAML2OBJ, args, nullptr, redirects));
+ uint64_t size;
+ ASSERT_NO_ERROR(llvm::sys::fs::file_size(obj, size));
+ ASSERT_GT(size, 0u);
+
+ ModuleSpec spec{FileSpec(obj, false)};
+ spec.GetSymbolFileSpec().SetFile(obj, false);
+ auto module_sp = std::make_shared<Module>(spec);
+ SectionList *list = module_sp->GetSectionList();
+ ASSERT_NE(nullptr, list);
+
+ auto hello_elf_sp = list->FindSectionByName(ConstString(".hello_elf"));
+ ASSERT_NE(nullptr, hello_elf_sp);
+ DataExtractor data;
+ ASSERT_EQ(9u, hello_elf_sp->GetSectionData(data));
+ offset_t offset = 0;
+ EXPECT_STREQ("Hello ELF", data.GetCStr(&offset));
+
+ auto bogus_sp = list->FindSectionByName(ConstString(".bogus"));
+ ASSERT_NE(nullptr, bogus_sp);
+ EXPECT_EQ(0u, bogus_sp->GetByteSize());
+}
Index: unittests/ObjectFile/ELF/Inputs/compressed-sections.yaml
===================================================================
--- /dev/null
+++ unittests/ObjectFile/ELF/Inputs/compressed-sections.yaml
@@ -0,0 +1,15 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_386
+Sections:
+ - Name: .hello_elf
+ Type: SHT_PROGBITS
+ Flags: [ SHF_COMPRESSED ]
+ Content: 010000000900000001000000789cf348cdc9c95770f57103000f8d02ec
+ - Name: .bogus
+ Type: SHT_PROGBITS
+ Flags: [ SHF_COMPRESSED ]
+ Content: deadbeefbaadf00d
Index: unittests/ObjectFile/ELF/CMakeLists.txt
===================================================================
--- unittests/ObjectFile/ELF/CMakeLists.txt
+++ unittests/ObjectFile/ELF/CMakeLists.txt
@@ -14,5 +14,6 @@
set(test_inputs
sections-resolve-consistently.yaml
+ compressed-sections.yaml
)
add_unittest_inputs(ObjectFileELFTests "${test_inputs}")
Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.h
===================================================================
--- source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -140,6 +140,9 @@
ObjectFile::Strata CalculateStrata() 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: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -23,14 +23,16 @@
#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"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
#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"
@@ -3452,3 +3454,35 @@
}
return eStrataUnknown;
}
+
+size_t ObjectFileELF::ReadSectionData(Section *section,
+ DataExtractor §ion_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 0;
+ }
+
+ 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();
+}
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits