forked from OSchip/llvm-project
Recommit r270547 ([llvm-dwarfdump] - Teach dwarfdump to decompress debug sections in zlib style.)
Fix was: 1) Had to regenerate dwarfdump-test-zlib.elf-x86-64, dwarfdump-test-zlib-gnu.elf-x86-64 (because llvm-symbolizer-zlib.test uses that inputs for its purposes and failed). 2) Updated llvm-symbolizer-zlib.test (updated used call function address to match new files + added one more check for newly created dwarfdump-test-zlib-gnu.elf-x86-64 binary input). 3) Updated comment in dwarfdump-test-zlib.cc. Original commit message: [llvm-dwarfdump] - Teach dwarfdump to decompress debug sections in zlib style. Before this llvm-dwarfdump only recognized zlib-gnu compression style of headers, this patch adds support for zlib style. It looks reasonable to support both styles for dumping, even if we are not going to suport generating of deprecated gnu one. Differential revision: http://reviews.llvm.org/D20470 llvm-svn: 270557
This commit is contained in:
parent
11de370cca
commit
401e4e570e
|
@ -694,6 +694,7 @@ protected:
|
||||||
std::error_code getSectionContents(DataRefImpl Sec,
|
std::error_code getSectionContents(DataRefImpl Sec,
|
||||||
StringRef &Res) const override;
|
StringRef &Res) const override;
|
||||||
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
|
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
|
||||||
|
bool isSectionCompressed(DataRefImpl Sec) const override;
|
||||||
bool isSectionText(DataRefImpl Sec) const override;
|
bool isSectionText(DataRefImpl Sec) const override;
|
||||||
bool isSectionData(DataRefImpl Sec) const override;
|
bool isSectionData(DataRefImpl Sec) const override;
|
||||||
bool isSectionBSS(DataRefImpl Sec) const override;
|
bool isSectionBSS(DataRefImpl Sec) const override;
|
||||||
|
|
|
@ -222,6 +222,7 @@ protected:
|
||||||
std::error_code getSectionContents(DataRefImpl Sec,
|
std::error_code getSectionContents(DataRefImpl Sec,
|
||||||
StringRef &Res) const override;
|
StringRef &Res) const override;
|
||||||
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
|
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
|
||||||
|
bool isSectionCompressed(DataRefImpl Sec) const override;
|
||||||
bool isSectionText(DataRefImpl Sec) const override;
|
bool isSectionText(DataRefImpl Sec) const override;
|
||||||
bool isSectionData(DataRefImpl Sec) const override;
|
bool isSectionData(DataRefImpl Sec) const override;
|
||||||
bool isSectionBSS(DataRefImpl Sec) const override;
|
bool isSectionBSS(DataRefImpl Sec) const override;
|
||||||
|
@ -583,6 +584,11 @@ uint64_t ELFObjectFile<ELFT>::getSectionAlignment(DataRefImpl Sec) const {
|
||||||
return getSection(Sec)->sh_addralign;
|
return getSection(Sec)->sh_addralign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
bool ELFObjectFile<ELFT>::isSectionCompressed(DataRefImpl Sec) const {
|
||||||
|
return getSection(Sec)->sh_flags & ELF::SHF_COMPRESSED;
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
|
bool ELFObjectFile<ELFT>::isSectionText(DataRefImpl Sec) const {
|
||||||
return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR;
|
return getSection(Sec)->sh_flags & ELF::SHF_EXECINSTR;
|
||||||
|
|
|
@ -222,6 +222,7 @@ public:
|
||||||
std::error_code getSectionContents(DataRefImpl Sec,
|
std::error_code getSectionContents(DataRefImpl Sec,
|
||||||
StringRef &Res) const override;
|
StringRef &Res) const override;
|
||||||
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
|
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
|
||||||
|
bool isSectionCompressed(DataRefImpl Sec) const override;
|
||||||
bool isSectionText(DataRefImpl Sec) const override;
|
bool isSectionText(DataRefImpl Sec) const override;
|
||||||
bool isSectionData(DataRefImpl Sec) const override;
|
bool isSectionData(DataRefImpl Sec) const override;
|
||||||
bool isSectionBSS(DataRefImpl Sec) const override;
|
bool isSectionBSS(DataRefImpl Sec) const override;
|
||||||
|
|
|
@ -89,6 +89,7 @@ public:
|
||||||
/// @brief Get the alignment of this section as the actual value (not log 2).
|
/// @brief Get the alignment of this section as the actual value (not log 2).
|
||||||
uint64_t getAlignment() const;
|
uint64_t getAlignment() const;
|
||||||
|
|
||||||
|
bool isCompressed() const;
|
||||||
bool isText() const;
|
bool isText() const;
|
||||||
bool isData() const;
|
bool isData() const;
|
||||||
bool isBSS() const;
|
bool isBSS() const;
|
||||||
|
@ -214,6 +215,7 @@ protected:
|
||||||
virtual std::error_code getSectionContents(DataRefImpl Sec,
|
virtual std::error_code getSectionContents(DataRefImpl Sec,
|
||||||
StringRef &Res) const = 0;
|
StringRef &Res) const = 0;
|
||||||
virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
|
virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0;
|
||||||
|
virtual bool isSectionCompressed(DataRefImpl Sec) const = 0;
|
||||||
virtual bool isSectionText(DataRefImpl Sec) const = 0;
|
virtual bool isSectionText(DataRefImpl Sec) const = 0;
|
||||||
virtual bool isSectionData(DataRefImpl Sec) const = 0;
|
virtual bool isSectionData(DataRefImpl Sec) const = 0;
|
||||||
virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
|
virtual bool isSectionBSS(DataRefImpl Sec) const = 0;
|
||||||
|
@ -380,6 +382,10 @@ inline uint64_t SectionRef::getAlignment() const {
|
||||||
return OwningObject->getSectionAlignment(SectionPimpl);
|
return OwningObject->getSectionAlignment(SectionPimpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool SectionRef::isCompressed() const {
|
||||||
|
return OwningObject->isSectionCompressed(SectionPimpl);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool SectionRef::isText() const {
|
inline bool SectionRef::isText() const {
|
||||||
return OwningObject->isSectionText(SectionPimpl);
|
return OwningObject->isSectionText(SectionPimpl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
|
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
|
||||||
#include "llvm/Support/Compression.h"
|
#include "llvm/Support/Compression.h"
|
||||||
#include "llvm/Support/Dwarf.h"
|
#include "llvm/Support/Dwarf.h"
|
||||||
|
#include "llvm/Support/ELF.h"
|
||||||
#include "llvm/Support/Format.h"
|
#include "llvm/Support/Format.h"
|
||||||
#include "llvm/Support/Path.h"
|
#include "llvm/Support/Path.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
@ -590,8 +591,8 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
|
||||||
return InliningInfo;
|
return InliningInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool consumeCompressedDebugSectionHeader(StringRef &data,
|
static bool consumeCompressedGnuHeader(StringRef &data,
|
||||||
uint64_t &OriginalSize) {
|
uint64_t &OriginalSize) {
|
||||||
// Consume "ZLIB" prefix.
|
// Consume "ZLIB" prefix.
|
||||||
if (!data.startswith("ZLIB"))
|
if (!data.startswith("ZLIB"))
|
||||||
return false;
|
return false;
|
||||||
|
@ -606,6 +607,50 @@ static bool consumeCompressedDebugSectionHeader(StringRef &data,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool consumeCompressedZLibHeader(StringRef &Data, uint64_t &OriginalSize,
|
||||||
|
bool IsLE, bool Is64Bit) {
|
||||||
|
using namespace ELF;
|
||||||
|
uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
|
||||||
|
if (Data.size() < HdrSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
DataExtractor Extractor(Data, IsLE, 0);
|
||||||
|
uint32_t Offset = 0;
|
||||||
|
if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word)
|
||||||
|
: sizeof(Elf32_Word)) !=
|
||||||
|
ELFCOMPRESS_ZLIB)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Skip Elf64_Chdr::ch_reserved field.
|
||||||
|
if (Is64Bit)
|
||||||
|
Offset += sizeof(Elf64_Word);
|
||||||
|
|
||||||
|
OriginalSize = Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Xword)
|
||||||
|
: sizeof(Elf32_Word));
|
||||||
|
Data = Data.substr(HdrSize);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tryDecompress(StringRef &Name, StringRef &Data,
|
||||||
|
SmallString<32> &Out, bool ZLibStyle, bool IsLE,
|
||||||
|
bool Is64Bit) {
|
||||||
|
if (!zlib::isAvailable())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint64_t OriginalSize;
|
||||||
|
bool Result =
|
||||||
|
ZLibStyle ? consumeCompressedZLibHeader(Data, OriginalSize, IsLE, Is64Bit)
|
||||||
|
: consumeCompressedGnuHeader(Data, OriginalSize);
|
||||||
|
|
||||||
|
if (!Result || zlib::uncompress(Data, Out, OriginalSize) != zlib::StatusOK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// gnu-style names are started from "z", consume that.
|
||||||
|
if (!ZLibStyle)
|
||||||
|
Name = Name.substr(1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
|
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
|
||||||
const LoadedObjectInfo *L)
|
const LoadedObjectInfo *L)
|
||||||
: IsLittleEndian(Obj.isLittleEndian()),
|
: IsLittleEndian(Obj.isLittleEndian()),
|
||||||
|
@ -631,20 +676,13 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
|
||||||
|
|
||||||
name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
|
name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
|
||||||
|
|
||||||
// Check if debug info section is compressed with zlib.
|
bool ZLibStyleCompressed = Section.isCompressed();
|
||||||
if (name.startswith("zdebug_")) {
|
if (ZLibStyleCompressed || name.startswith("zdebug_")) {
|
||||||
uint64_t OriginalSize;
|
SmallString<32> Out;
|
||||||
if (!zlib::isAvailable() ||
|
if (!tryDecompress(name, data, Out, ZLibStyleCompressed, IsLittleEndian,
|
||||||
!consumeCompressedDebugSectionHeader(data, OriginalSize))
|
AddressSize == 8))
|
||||||
continue;
|
continue;
|
||||||
UncompressedSections.resize(UncompressedSections.size() + 1);
|
UncompressedSections.emplace_back(std::move(Out));
|
||||||
if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) !=
|
|
||||||
zlib::StatusOK) {
|
|
||||||
UncompressedSections.pop_back();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Make data point to uncompressed section contents and save its contents.
|
|
||||||
name = name.substr(1);
|
|
||||||
data = UncompressedSections.back();
|
data = UncompressedSections.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -292,6 +292,10 @@ uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const {
|
||||||
return Sec->getAlignment();
|
return Sec->getAlignment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
|
bool COFFObjectFile::isSectionText(DataRefImpl Ref) const {
|
||||||
const coff_section *Sec = toSec(Ref);
|
const coff_section *Sec = toSec(Ref);
|
||||||
return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
|
return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;
|
||||||
|
|
|
@ -653,6 +653,10 @@ uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
|
||||||
return uint64_t(1) << Align;
|
return uint64_t(1) << Align;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
|
bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
|
||||||
uint32_t Flags = getSectionFlags(this, Sec);
|
uint32_t Flags = getSectionFlags(this, Sec);
|
||||||
return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
|
return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
|
||||||
|
|
|
@ -16,9 +16,12 @@ int main() {
|
||||||
return f(2, 3);
|
return f(2, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Built with Clang 3.2 and ld.gold linker:
|
// Built with Clang 3.9 and GNU gold (GNU Binutils for Ubuntu 2.26) 1.11:
|
||||||
|
// Note: llvm-symbolizer-zlib.test relies on the path and filename used !
|
||||||
// $ mkdir -p /tmp/dbginfo
|
// $ mkdir -p /tmp/dbginfo
|
||||||
// $ cp dwarfdump-test-zlib.cc /tmp/dbginfo
|
// $ cp dwarfdump-test-zlib.cc /tmp/dbginfo
|
||||||
// $ cd /tmp/dbginfo
|
// $ cd /tmp/dbginfo
|
||||||
// $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib \
|
// $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib -o dwarfdump-test-zlib.elf-x86-64
|
||||||
// -o <output>
|
// $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib-gnu -o dwarfdump-test-zlibgnu.elf-x86-64
|
||||||
|
// llvm-readobj -sections can be used to see that outputs really contain the compressed sections, also output in both
|
||||||
|
// cases is slightly smaller, that is because of compression.
|
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,12 @@
|
||||||
REQUIRES: zlib
|
REQUIRES: zlib
|
||||||
|
|
||||||
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlib.elf-x86-64 | FileCheck %s
|
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlib.elf-x86-64 | FileCheck %s
|
||||||
|
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlibgnu.elf-x86-64 | FileCheck %s
|
||||||
|
|
||||||
CHECK: .debug_abbrev contents
|
CHECK: .debug_abbrev contents
|
||||||
|
|
||||||
|
// Dump content of a little section to check that both zlib and zlib gnu styles do
|
||||||
|
// the decompression correctly and result is the same. This and above also checks
|
||||||
|
// that sections names are properly shown in zlib-gnu style (without additional 'z' prefix).
|
||||||
CHECK: .debug_info contents
|
CHECK: .debug_info contents
|
||||||
|
CHECK: 0x00000000: Compile Unit: length = 0x00000144 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000148)
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
REQUIRES: zlib
|
REQUIRES: zlib
|
||||||
|
|
||||||
RUN: echo "%p/Inputs/dwarfdump-test-zlib.elf-x86-64 0x400559" > %t.input
|
RUN: echo "%p/Inputs/dwarfdump-test-zlib.elf-x86-64 0x4005e9" > %t1.input
|
||||||
RUN: llvm-symbolizer < %t.input | FileCheck %s
|
RUN: llvm-symbolizer < %t1.input | FileCheck %s
|
||||||
|
|
||||||
|
RUN: echo "%p/Inputs/dwarfdump-test-zlibgnu.elf-x86-64 0x4005e9" > %t2.input
|
||||||
|
RUN: llvm-symbolizer < %t2.input | FileCheck %s
|
||||||
|
|
||||||
CHECK: main
|
CHECK: main
|
||||||
CHECK-NEXT: /tmp/dbginfo{{[/\\]}}dwarfdump-test-zlib.cc:16
|
CHECK-NEXT: /tmp/dbginfo{{[/\\]}}dwarfdump-test-zlib.cc:16
|
||||||
|
|
Loading…
Reference in New Issue