mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 14:10:41 +00:00
[llvm-mc] - Teach llvm-mc to generate zlib styled compression sections.
This patch is strongly based on previously reverted D20331. (because of gnuutils < 2.26 does not support compressed debug sections in non zlib-gnu style) Difference that this patch supports both zlib and zlib-gnu styles. -compress-debug-sections option now supports next values: -compress-debug-sections=zlib-gnu -compress-debug-sections=zlib -compress-debug-sections=none Previously specifying -compress-debug-sections enabled zlib-gnu compression, so anyone can put "-compress-debug-sections=zlib-gnu" to restore the behavior that was before this patch for case when compression was enabled. Differential revision: http://reviews.llvm.org/D20676 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270977 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3808026456
commit
dd4101a976
@ -53,6 +53,12 @@ namespace LCOMM {
|
||||
enum LCOMMType { NoAlignment, ByteAlignment, Log2Alignment };
|
||||
}
|
||||
|
||||
enum class DebugCompressionType {
|
||||
DCT_None, // no compression
|
||||
DCT_Zlib, // zlib style complession
|
||||
DCT_ZlibGnu // zlib-gnu style compression
|
||||
};
|
||||
|
||||
/// This class is intended to be used as a base class for asm
|
||||
/// properties and features specific to the target.
|
||||
class MCAsmInfo {
|
||||
@ -356,8 +362,8 @@ protected:
|
||||
/// construction (see LLVMTargetMachine::initAsmInfo()).
|
||||
bool UseIntegratedAssembler;
|
||||
|
||||
/// Compress DWARF debug sections. Defaults to false.
|
||||
bool CompressDebugSections;
|
||||
/// Compress DWARF debug sections. Defaults to no compression.
|
||||
DebugCompressionType CompressDebugSections;
|
||||
|
||||
/// True if the integrated assembler should interpret 'a >> b' constant
|
||||
/// expressions as logical rather than arithmetic.
|
||||
@ -565,9 +571,11 @@ public:
|
||||
UseIntegratedAssembler = Value;
|
||||
}
|
||||
|
||||
bool compressDebugSections() const { return CompressDebugSections; }
|
||||
DebugCompressionType compressDebugSections() const {
|
||||
return CompressDebugSections;
|
||||
}
|
||||
|
||||
void setCompressDebugSections(bool CompressDebugSections) {
|
||||
void setCompressDebugSections(DebugCompressionType CompressDebugSections) {
|
||||
this->CompressDebugSections = CompressDebugSections;
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@ public:
|
||||
unsigned getType() const { return Type; }
|
||||
unsigned getFlags() const { return Flags; }
|
||||
unsigned getEntrySize() const { return EntrySize; }
|
||||
void setFlags(unsigned F) { Flags = F; }
|
||||
const MCSymbolELF *getGroup() const { return Group; }
|
||||
|
||||
void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS,
|
||||
|
@ -71,7 +71,7 @@ void LLVMTargetMachine::initAsmInfo() {
|
||||
TmpAsmInfo->setUseIntegratedAssembler(false);
|
||||
|
||||
if (Options.CompressDebugSections)
|
||||
TmpAsmInfo->setCompressDebugSections(true);
|
||||
TmpAsmInfo->setCompressDebugSections(DebugCompressionType::DCT_ZlibGnu);
|
||||
|
||||
AsmInfo = TmpAsmInfo;
|
||||
}
|
||||
|
@ -136,6 +136,10 @@ class ELFObjectWriter : public MCObjectWriter {
|
||||
|
||||
void align(unsigned Alignment);
|
||||
|
||||
bool maybeWriteCompression(uint64_t Size,
|
||||
SmallVectorImpl<char> &CompressedContents,
|
||||
bool ZLibStyle, unsigned Alignment);
|
||||
|
||||
public:
|
||||
ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS,
|
||||
bool IsLittleEndian)
|
||||
@ -979,23 +983,38 @@ ELFObjectWriter::createRelocationSection(MCContext &Ctx,
|
||||
return RelaSection;
|
||||
}
|
||||
|
||||
// Include the debug info compression header:
|
||||
// "ZLIB" followed by 8 bytes representing the uncompressed size of the section,
|
||||
// useful for consumers to preallocate a buffer to decompress into.
|
||||
static bool
|
||||
prependCompressionHeader(uint64_t Size,
|
||||
SmallVectorImpl<char> &CompressedContents) {
|
||||
// Include the debug info compression header.
|
||||
bool ELFObjectWriter::maybeWriteCompression(
|
||||
uint64_t Size, SmallVectorImpl<char> &CompressedContents, bool ZLibStyle,
|
||||
unsigned Alignment) {
|
||||
if (ZLibStyle) {
|
||||
uint64_t HdrSize =
|
||||
is64Bit() ? sizeof(ELF::Elf32_Chdr) : sizeof(ELF::Elf64_Chdr);
|
||||
if (Size <= HdrSize + CompressedContents.size())
|
||||
return false;
|
||||
// Platform specific header is followed by compressed data.
|
||||
if (is64Bit()) {
|
||||
// Write Elf64_Chdr header.
|
||||
write(static_cast<ELF::Elf64_Word>(ELF::ELFCOMPRESS_ZLIB));
|
||||
write(static_cast<ELF::Elf64_Word>(0)); // ch_reserved field.
|
||||
write(static_cast<ELF::Elf64_Xword>(Size));
|
||||
write(static_cast<ELF::Elf64_Xword>(Alignment));
|
||||
} else {
|
||||
// Write Elf32_Chdr header otherwise.
|
||||
write(static_cast<ELF::Elf32_Word>(ELF::ELFCOMPRESS_ZLIB));
|
||||
write(static_cast<ELF::Elf32_Word>(Size));
|
||||
write(static_cast<ELF::Elf32_Word>(Alignment));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// "ZLIB" followed by 8 bytes representing the uncompressed size of the section,
|
||||
// useful for consumers to preallocate a buffer to decompress into.
|
||||
const StringRef Magic = "ZLIB";
|
||||
if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size())
|
||||
return false;
|
||||
if (sys::IsLittleEndianHost)
|
||||
sys::swapByteOrder(Size);
|
||||
CompressedContents.insert(CompressedContents.begin(),
|
||||
Magic.size() + sizeof(Size), 0);
|
||||
std::copy(Magic.begin(), Magic.end(), CompressedContents.begin());
|
||||
std::copy(reinterpret_cast<char *>(&Size),
|
||||
reinterpret_cast<char *>(&Size + 1),
|
||||
CompressedContents.begin() + Magic.size());
|
||||
write(ArrayRef<char>(Magic.begin(), Magic.size()));
|
||||
writeBE64(Size);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1007,8 +1026,11 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
|
||||
// Compressing debug_frame requires handling alignment fragments which is
|
||||
// more work (possibly generalizing MCAssembler.cpp:writeFragment to allow
|
||||
// for writing to arbitrary buffers) for little benefit.
|
||||
if (!Asm.getContext().getAsmInfo()->compressDebugSections() ||
|
||||
!SectionName.startswith(".debug_") || SectionName == ".debug_frame") {
|
||||
bool CompressionEnabled =
|
||||
Asm.getContext().getAsmInfo()->compressDebugSections() !=
|
||||
DebugCompressionType::DCT_None;
|
||||
if (!CompressionEnabled || !SectionName.startswith(".debug_") ||
|
||||
SectionName == ".debug_frame") {
|
||||
Asm.writeSectionData(&Section, Layout);
|
||||
return;
|
||||
}
|
||||
@ -1029,12 +1051,21 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!prependCompressionHeader(UncompressedData.size(), CompressedContents)) {
|
||||
bool ZlibStyle = Asm.getContext().getAsmInfo()->compressDebugSections() ==
|
||||
DebugCompressionType::DCT_Zlib;
|
||||
if (!maybeWriteCompression(UncompressedData.size(), CompressedContents,
|
||||
ZlibStyle, Sec.getAlignment())) {
|
||||
getStream() << UncompressedData;
|
||||
return;
|
||||
}
|
||||
Asm.getContext().renameELFSection(&Section,
|
||||
(".z" + SectionName.drop_front(1)).str());
|
||||
|
||||
if (ZlibStyle)
|
||||
// Set the compressed flag. That is zlib style.
|
||||
Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED);
|
||||
else
|
||||
// Add "z" prefix to section name. This is zlib-gnu style.
|
||||
Asm.getContext().renameELFSection(&Section,
|
||||
(".z" + SectionName.drop_front(1)).str());
|
||||
getStream() << CompressedContents;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ MCAsmInfo::MCAsmInfo() {
|
||||
// - The target subclasses for AArch64, ARM, and X86 handle these cases
|
||||
UseIntegratedAssembler = false;
|
||||
|
||||
CompressDebugSections = false;
|
||||
CompressDebugSections = DebugCompressionType::DCT_None;
|
||||
}
|
||||
|
||||
MCAsmInfo::~MCAsmInfo() {
|
||||
|
@ -1,27 +1,35 @@
|
||||
// RUN: llvm-mc -filetype=obj -compress-debug-sections -triple x86_64-pc-linux-gnu < %s -o %t
|
||||
// RUN: llvm-objdump -s %t | FileCheck %s
|
||||
// Check zlib-gnu style
|
||||
// RUN: llvm-mc -filetype=obj -compress-debug-sections=zlib-gnu -triple x86_64-pc-linux-gnu < %s -o %t
|
||||
// RUN: llvm-objdump -s %t | FileCheck --check-prefix=CHECK-GNU-STYLE %s
|
||||
// RUN: llvm-dwarfdump -debug-dump=str %t | FileCheck --check-prefix=STR %s
|
||||
// RUN: llvm-mc -filetype=obj -compress-debug-sections -triple i386-pc-linux-gnu < %s \
|
||||
// RUN: | llvm-readobj -symbols - | FileCheck --check-prefix=386-SYMBOLS %s
|
||||
// RUN: llvm-mc -filetype=obj -compress-debug-sections=zlib-gnu -triple i386-pc-linux-gnu < %s \
|
||||
// RUN: | llvm-readobj -symbols - | FileCheck --check-prefix=386-SYMBOLS-GNU %s
|
||||
|
||||
// Check zlib style
|
||||
// RUN: llvm-mc -filetype=obj -compress-debug-sections=zlib -triple x86_64-pc-linux-gnu < %s -o %t
|
||||
// RUN: llvm-objdump -s %t | FileCheck --check-prefix=CHECK-ZLIB-STYLE %s
|
||||
// RUN: llvm-dwarfdump -debug-dump=str %t | FileCheck --check-prefix=STR %s
|
||||
// RUN: llvm-mc -filetype=obj -compress-debug-sections=zlib -triple i386-pc-linux-gnu < %s \
|
||||
// RUN: | llvm-readobj -symbols - | FileCheck --check-prefix=386-SYMBOLS-ZLIB %s
|
||||
// RUN: llvm-readobj -sections %t | FileCheck --check-prefix=ZLIB-STYLE-FLAGS %s
|
||||
|
||||
// REQUIRES: zlib
|
||||
|
||||
// Don't compress small sections, such as this simple debug_abbrev example
|
||||
// CHECK: Contents of section .debug_abbrev:
|
||||
// CHECK-NOT: ZLIB
|
||||
// CHECK-NOT: Contents of
|
||||
// CHECK-GNU-STYLE: Contents of section .debug_abbrev:
|
||||
// CHECK-GNU-STYLE-NOT: ZLIB
|
||||
// CHECK-GNU-STYLE-NOT: Contents of
|
||||
|
||||
// CHECK: Contents of section .debug_info:
|
||||
// CHECK-GNU-STYLE: Contents of section .debug_info:
|
||||
|
||||
// CHECK: Contents of section .zdebug_str:
|
||||
// CHECK-GNU-STYLE: Contents of section .zdebug_str:
|
||||
// Check for the 'ZLIB' file magic at the start of the section only
|
||||
// CHECK-NEXT: ZLIB
|
||||
// CHECK-NOT: ZLIB
|
||||
|
||||
// CHECK-GNU-STYLE-NEXT: ZLIB
|
||||
// CHECK-GNU-STYLE-NOT: ZLIB
|
||||
// FIXME: Handle compressing alignment fragments to support compressing debug_frame
|
||||
// CHECK: Contents of section .debug_frame:
|
||||
// CHECK-NOT: ZLIB
|
||||
// CHECK: Contents of
|
||||
// CHECK-GNU-STYLE: Contents of section .debug_frame:
|
||||
// CHECK-GNU-STYLE-NOT: ZLIB
|
||||
// CHECK-GNU-STYLE: Contents of
|
||||
|
||||
// Decompress one valid dwarf section just to check that this roundtrips,
|
||||
// we use .zdebug_str section for that
|
||||
@ -29,9 +37,34 @@
|
||||
|
||||
// In x86 32 bit named symbols are used for temporary symbols in merge
|
||||
// sections, so make sure we handle symbols inside compressed sections
|
||||
// 386-SYMBOLS: Name: .Linfo_string0
|
||||
// 386-SYMBOLS-NOT: }
|
||||
// 386-SYMBOLS: Section: .zdebug_str
|
||||
// 386-SYMBOLS-GNU: Name: .Linfo_string0
|
||||
// 386-SYMBOLS-GNU-NOT: }
|
||||
// 386-SYMBOLS-GNU: Section: .zdebug_str
|
||||
|
||||
// Now check the zlib style output:
|
||||
|
||||
// Don't compress small sections, such as this simple debug_abbrev example
|
||||
// CHECK-ZLIB-STYLE: Contents of section .debug_abbrev:
|
||||
// CHECK-ZLIB-STYLE-NOT: ZLIB
|
||||
// CHECK-ZLIB-STYLE-NOT: Contents of
|
||||
// CHECK-ZLIB-STYLE: Contents of section .debug_info:
|
||||
// FIXME: Handle compressing alignment fragments to support compressing debug_frame
|
||||
// CHECK-ZLIB-STYLE: Contents of section .debug_frame:
|
||||
// CHECK-ZLIB-STYLE-NOT: ZLIB
|
||||
// CHECK-ZLIB-STYLE: Contents of
|
||||
|
||||
// Check that debug_line section was not renamed, so it is
|
||||
// zlib-style, not zlib-gnu one. Check that SHF_COMPRESSED was set.
|
||||
// ZLIB-STYLE-FLAGS: Section {
|
||||
// ZLIB-STYLE-FLAGS: Index:
|
||||
// ZLIB-STYLE-FLAGS: Name: .debug_str
|
||||
// ZLIB-STYLE-FLAGS-NEXT: Type: SHT_PROGBITS
|
||||
// ZLIB-STYLE-FLAGS-NEXT: Flags [
|
||||
// ZLIB-STYLE-FLAGS-NEXT: SHF_COMPRESSED
|
||||
|
||||
// 386-SYMBOLS-ZLIB: Name: .Linfo_string0
|
||||
// 386-SYMBOLS-ZLIB-NOT: }
|
||||
// 386-SYMBOLS-ZLIB: Section: .debug_str
|
||||
|
||||
.section .debug_line,"",@progbits
|
||||
|
||||
|
@ -52,9 +52,18 @@ OutputFilename("o", cl::desc("Output filename"),
|
||||
static cl::opt<bool>
|
||||
ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
|
||||
|
||||
static cl::opt<bool>
|
||||
CompressDebugSections("compress-debug-sections",
|
||||
cl::desc("Compress DWARF debug sections"));
|
||||
static cl::opt<DebugCompressionType>
|
||||
CompressDebugSections("compress-debug-sections", cl::ValueOptional,
|
||||
cl::init(DebugCompressionType::DCT_None),
|
||||
cl::desc("Choose DWARF debug sections compression:"),
|
||||
cl::values(
|
||||
clEnumValN(DebugCompressionType::DCT_None, "none",
|
||||
"No compression"),
|
||||
clEnumValN(DebugCompressionType::DCT_Zlib, "zlib",
|
||||
"Use zlib compression"),
|
||||
clEnumValN(DebugCompressionType::DCT_ZlibGnu, "zlib-gnu",
|
||||
"Use zlib-gnu compression (depricated)"),
|
||||
clEnumValEnd));
|
||||
|
||||
static cl::opt<bool>
|
||||
ShowInst("show-inst", cl::desc("Show internal instruction representation"));
|
||||
@ -407,13 +416,13 @@ int main(int argc, char **argv) {
|
||||
std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
|
||||
assert(MAI && "Unable to create target asm info!");
|
||||
|
||||
if (CompressDebugSections) {
|
||||
if (CompressDebugSections != DebugCompressionType::DCT_None) {
|
||||
if (!zlib::isAvailable()) {
|
||||
errs() << ProgName
|
||||
<< ": build tools with zlib to enable -compress-debug-sections";
|
||||
return 1;
|
||||
}
|
||||
MAI->setCompressDebugSections(true);
|
||||
MAI->setCompressDebugSections(CompressDebugSections);
|
||||
}
|
||||
|
||||
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
|
||||
|
Loading…
Reference in New Issue
Block a user