mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
DebugInfo: Support for compressed debug info sections
1) When creating a .debug_* section and instead create a .zdebug_ section. 2) When creating a fragment in a .zdebug_* section, make it a compressed fragment. 3) When computing the size of a compressed section, compress the data and use the size of the compressed data. 4) Emit the compressed bytes. Also, check that only if a section has a compressed fragment, then that is the only fragment in the section. Assert-fail if the fragment's data is modified after it is compressed. Initial review on llvm-commits by Eric Christopher and Rafael Espindola. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204958 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8040d49d85
commit
0a0c4cc56f
@ -51,6 +51,7 @@ public:
|
|||||||
enum FragmentType {
|
enum FragmentType {
|
||||||
FT_Align,
|
FT_Align,
|
||||||
FT_Data,
|
FT_Data,
|
||||||
|
FT_Compressed,
|
||||||
FT_CompactEncodedInst,
|
FT_CompactEncodedInst,
|
||||||
FT_Fill,
|
FT_Fill,
|
||||||
FT_Relaxable,
|
FT_Relaxable,
|
||||||
@ -160,6 +161,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
case MCFragment::FT_Relaxable:
|
case MCFragment::FT_Relaxable:
|
||||||
case MCFragment::FT_CompactEncodedInst:
|
case MCFragment::FT_CompactEncodedInst:
|
||||||
|
case MCFragment::FT_Compressed:
|
||||||
case MCFragment::FT_Data:
|
case MCFragment::FT_Data:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -194,7 +196,8 @@ public:
|
|||||||
|
|
||||||
static bool classof(const MCFragment *F) {
|
static bool classof(const MCFragment *F) {
|
||||||
MCFragment::FragmentType Kind = F->getKind();
|
MCFragment::FragmentType Kind = F->getKind();
|
||||||
return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data;
|
return Kind == MCFragment::FT_Relaxable || Kind == MCFragment::FT_Data ||
|
||||||
|
Kind == MCFragment::FT_Compressed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -213,6 +216,11 @@ class MCDataFragment : public MCEncodedFragmentWithFixups {
|
|||||||
|
|
||||||
/// Fixups - The list of fixups in this fragment.
|
/// Fixups - The list of fixups in this fragment.
|
||||||
SmallVector<MCFixup, 4> Fixups;
|
SmallVector<MCFixup, 4> Fixups;
|
||||||
|
protected:
|
||||||
|
MCDataFragment(MCFragment::FragmentType FType, MCSectionData *SD = 0)
|
||||||
|
: MCEncodedFragmentWithFixups(FType, SD), HasInstructions(false),
|
||||||
|
AlignToBundleEnd(false) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MCDataFragment(MCSectionData *SD = 0)
|
MCDataFragment(MCSectionData *SD = 0)
|
||||||
: MCEncodedFragmentWithFixups(FT_Data, SD),
|
: MCEncodedFragmentWithFixups(FT_Data, SD),
|
||||||
@ -246,10 +254,21 @@ public:
|
|||||||
const_fixup_iterator fixup_end() const override {return Fixups.end();}
|
const_fixup_iterator fixup_end() const override {return Fixups.end();}
|
||||||
|
|
||||||
static bool classof(const MCFragment *F) {
|
static bool classof(const MCFragment *F) {
|
||||||
return F->getKind() == MCFragment::FT_Data;
|
return F->getKind() == MCFragment::FT_Data ||
|
||||||
|
F->getKind() == MCFragment::FT_Compressed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MCCompressedFragment: public MCDataFragment {
|
||||||
|
mutable SmallVector<char, 32> CompressedContents;
|
||||||
|
public:
|
||||||
|
MCCompressedFragment(MCSectionData *SD = nullptr)
|
||||||
|
: MCDataFragment(FT_Compressed, SD) {}
|
||||||
|
const SmallVectorImpl<char> &getCompressedContents() const;
|
||||||
|
using MCDataFragment::getContents;
|
||||||
|
SmallVectorImpl<char> &getContents() override;
|
||||||
|
};
|
||||||
|
|
||||||
/// This is a compact (memory-size-wise) fragment for holding an encoded
|
/// This is a compact (memory-size-wise) fragment for holding an encoded
|
||||||
/// instruction (non-relaxable) that has no fixups registered. When applicable,
|
/// instruction (non-relaxable) that has no fixups registered. When applicable,
|
||||||
/// it can be used instead of MCDataFragment and lead to lower memory
|
/// it can be used instead of MCDataFragment and lead to lower memory
|
||||||
|
@ -100,6 +100,8 @@ MCAsmInfo::MCAsmInfo() {
|
|||||||
// architecture basis.
|
// architecture basis.
|
||||||
// - The target subclasses for AArch64, ARM, and X86 handle these cases
|
// - The target subclasses for AArch64, ARM, and X86 handle these cases
|
||||||
UseIntegratedAssembler = false;
|
UseIntegratedAssembler = false;
|
||||||
|
|
||||||
|
CompressDebugSections = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MCAsmInfo::~MCAsmInfo() {
|
MCAsmInfo::~MCAsmInfo() {
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#include "llvm/Support/LEB128.h"
|
#include "llvm/Support/LEB128.h"
|
||||||
#include "llvm/Support/TargetRegistry.h"
|
#include "llvm/Support/TargetRegistry.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
|
#include "llvm/Support/Compression.h"
|
||||||
|
#include "llvm/Support/Host.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@ -230,6 +233,39 @@ MCEncodedFragmentWithFixups::~MCEncodedFragmentWithFixups() {
|
|||||||
|
|
||||||
/* *** */
|
/* *** */
|
||||||
|
|
||||||
|
const SmallVectorImpl<char> &MCCompressedFragment::getCompressedContents() const {
|
||||||
|
assert(getParent()->size() == 1 &&
|
||||||
|
"Only compress sections containing a single fragment");
|
||||||
|
if (CompressedContents.empty()) {
|
||||||
|
std::unique_ptr<MemoryBuffer> CompressedSection;
|
||||||
|
zlib::Status Success =
|
||||||
|
zlib::compress(StringRef(getContents().data(), getContents().size()),
|
||||||
|
CompressedSection);
|
||||||
|
(void)Success;
|
||||||
|
assert(Success == zlib::StatusOK);
|
||||||
|
CompressedContents.push_back('Z');
|
||||||
|
CompressedContents.push_back('L');
|
||||||
|
CompressedContents.push_back('I');
|
||||||
|
CompressedContents.push_back('B');
|
||||||
|
uint64_t Size = getContents().size();
|
||||||
|
if (sys::IsLittleEndianHost)
|
||||||
|
Size = sys::SwapByteOrder(Size);
|
||||||
|
CompressedContents.append(reinterpret_cast<char *>(&Size),
|
||||||
|
reinterpret_cast<char *>(&Size + 1));
|
||||||
|
CompressedContents.append(CompressedSection->getBuffer().begin(),
|
||||||
|
CompressedSection->getBuffer().end());
|
||||||
|
}
|
||||||
|
return CompressedContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallVectorImpl<char> &MCCompressedFragment::getContents() {
|
||||||
|
assert(CompressedContents.empty() &&
|
||||||
|
"Fragment contents should not be altered after compression");
|
||||||
|
return MCDataFragment::getContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* *** */
|
||||||
|
|
||||||
MCSectionData::MCSectionData() : Section(0) {}
|
MCSectionData::MCSectionData() : Section(0) {}
|
||||||
|
|
||||||
MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
|
MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
|
||||||
@ -430,6 +466,8 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
|
|||||||
case MCFragment::FT_Relaxable:
|
case MCFragment::FT_Relaxable:
|
||||||
case MCFragment::FT_CompactEncodedInst:
|
case MCFragment::FT_CompactEncodedInst:
|
||||||
return cast<MCEncodedFragment>(F).getContents().size();
|
return cast<MCEncodedFragment>(F).getContents().size();
|
||||||
|
case MCFragment::FT_Compressed:
|
||||||
|
return cast<MCCompressedFragment>(F).getCompressedContents().size();
|
||||||
case MCFragment::FT_Fill:
|
case MCFragment::FT_Fill:
|
||||||
return cast<MCFillFragment>(F).getSize();
|
return cast<MCFillFragment>(F).getSize();
|
||||||
|
|
||||||
@ -618,6 +656,11 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MCFragment::FT_Compressed:
|
||||||
|
++stats::EmittedDataFragments;
|
||||||
|
OW->WriteBytes(cast<MCCompressedFragment>(F).getCompressedContents());
|
||||||
|
break;
|
||||||
|
|
||||||
case MCFragment::FT_Data:
|
case MCFragment::FT_Data:
|
||||||
++stats::EmittedDataFragments;
|
++stats::EmittedDataFragments;
|
||||||
writeFragmentContents(F, OW);
|
writeFragmentContents(F, OW);
|
||||||
@ -694,6 +737,7 @@ void MCAssembler::writeSectionData(const MCSectionData *SD,
|
|||||||
ie = SD->end(); it != ie; ++it) {
|
ie = SD->end(); it != ie; ++it) {
|
||||||
switch (it->getKind()) {
|
switch (it->getKind()) {
|
||||||
default: llvm_unreachable("Invalid fragment in virtual section!");
|
default: llvm_unreachable("Invalid fragment in virtual section!");
|
||||||
|
case MCFragment::FT_Compressed:
|
||||||
case MCFragment::FT_Data: {
|
case MCFragment::FT_Data: {
|
||||||
// Check that we aren't trying to write a non-zero contents (or fixups)
|
// Check that we aren't trying to write a non-zero contents (or fixups)
|
||||||
// into a virtual section. This is to support clients which use standard
|
// into a virtual section. This is to support clients which use standard
|
||||||
@ -1021,6 +1065,8 @@ void MCFragment::dump() {
|
|||||||
switch (getKind()) {
|
switch (getKind()) {
|
||||||
case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
|
case MCFragment::FT_Align: OS << "MCAlignFragment"; break;
|
||||||
case MCFragment::FT_Data: OS << "MCDataFragment"; break;
|
case MCFragment::FT_Data: OS << "MCDataFragment"; break;
|
||||||
|
case MCFragment::FT_Compressed:
|
||||||
|
OS << "MCCompressedFragment"; break;
|
||||||
case MCFragment::FT_CompactEncodedInst:
|
case MCFragment::FT_CompactEncodedInst:
|
||||||
OS << "MCCompactEncodedInstFragment"; break;
|
OS << "MCCompactEncodedInstFragment"; break;
|
||||||
case MCFragment::FT_Fill: OS << "MCFillFragment"; break;
|
case MCFragment::FT_Fill: OS << "MCFillFragment"; break;
|
||||||
@ -1047,6 +1093,7 @@ void MCFragment::dump() {
|
|||||||
<< " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">";
|
<< " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MCFragment::FT_Compressed:
|
||||||
case MCFragment::FT_Data: {
|
case MCFragment::FT_Data: {
|
||||||
const MCDataFragment *DF = cast<MCDataFragment>(this);
|
const MCDataFragment *DF = cast<MCDataFragment>(this);
|
||||||
OS << "\n ";
|
OS << "\n ";
|
||||||
|
@ -37,13 +37,13 @@ typedef std::map<SectionGroupPair, const MCSectionCOFF *> COFFUniqueMapTy;
|
|||||||
|
|
||||||
MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
|
MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri,
|
||||||
const MCObjectFileInfo *mofi, const SourceMgr *mgr,
|
const MCObjectFileInfo *mofi, const SourceMgr *mgr,
|
||||||
bool DoAutoReset) :
|
bool DoAutoReset)
|
||||||
SrcMgr(mgr), MAI(mai), MRI(mri), MOFI(mofi),
|
: SrcMgr(mgr), MAI(mai), MRI(mri), MOFI(mofi), Allocator(),
|
||||||
Allocator(), Symbols(Allocator), UsedNames(Allocator),
|
Symbols(Allocator), UsedNames(Allocator), NextUniqueID(0),
|
||||||
NextUniqueID(0),
|
CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0), DwarfLocSeen(false),
|
||||||
CurrentDwarfLoc(0,0,0,DWARF2_FLAG_IS_STMT,0,0),
|
GenDwarfForAssembly(false), GenDwarfFileNumber(0),
|
||||||
DwarfLocSeen(false), GenDwarfForAssembly(false), GenDwarfFileNumber(0),
|
AllowTemporaryLabels(true), DwarfCompileUnitID(0),
|
||||||
AllowTemporaryLabels(true), DwarfCompileUnitID(0), AutoReset(DoAutoReset) {
|
AutoReset(DoAutoReset) {
|
||||||
|
|
||||||
error_code EC = llvm::sys::fs::current_path(CompilationDir);
|
error_code EC = llvm::sys::fs::current_path(CompilationDir);
|
||||||
if (EC)
|
if (EC)
|
||||||
@ -251,6 +251,11 @@ getELFSection(StringRef Section, unsigned Type, unsigned Flags,
|
|||||||
ELFUniquingMap = new ELFUniqueMapTy();
|
ELFUniquingMap = new ELFUniqueMapTy();
|
||||||
ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap;
|
ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)ELFUniquingMap;
|
||||||
|
|
||||||
|
SmallString<32> ZDebugName;
|
||||||
|
if (MAI->compressDebugSections() && Section.startswith(".debug_") &&
|
||||||
|
Section != ".debug_frame")
|
||||||
|
Section = (".z" + Section.drop_front(1)).toStringRef(ZDebugName);
|
||||||
|
|
||||||
// Do the lookup, if we have a hit, return it.
|
// Do the lookup, if we have a hit, return it.
|
||||||
std::pair<ELFUniqueMapTy::iterator, bool> Entry = Map.insert(
|
std::pair<ELFUniqueMapTy::iterator, bool> Entry = Map.insert(
|
||||||
std::make_pair(SectionGroupPair(Section, Group), (MCSectionELF *)0));
|
std::make_pair(SectionGroupPair(Section, Group), (MCSectionELF *)0));
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "llvm/MC/MCSection.h"
|
#include "llvm/MC/MCSection.h"
|
||||||
#include "llvm/MC/MCSymbol.h"
|
#include "llvm/MC/MCSymbol.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
|
#include "llvm/MC/MCSectionELF.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB,
|
MCObjectStreamer::MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB,
|
||||||
@ -63,7 +64,11 @@ MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const {
|
|||||||
// When bundling is enabled, we don't want to add data to a fragment that
|
// When bundling is enabled, we don't want to add data to a fragment that
|
||||||
// already has instructions (see MCELFStreamer::EmitInstToData for details)
|
// already has instructions (see MCELFStreamer::EmitInstToData for details)
|
||||||
if (!F || (Assembler->isBundlingEnabled() && F->hasInstructions())) {
|
if (!F || (Assembler->isBundlingEnabled() && F->hasInstructions())) {
|
||||||
F = new MCDataFragment();
|
const auto *Sec = dyn_cast<MCSectionELF>(&getCurrentSectionData()->getSection());
|
||||||
|
if (Sec && Sec->getSectionName().startswith(".zdebug_"))
|
||||||
|
F = new MCCompressedFragment();
|
||||||
|
else
|
||||||
|
F = new MCDataFragment();
|
||||||
insert(F);
|
insert(F);
|
||||||
}
|
}
|
||||||
return F;
|
return F;
|
||||||
|
18
test/MC/ELF/compression.s
Normal file
18
test/MC/ELF/compression.s
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// RUN: llvm-mc -filetype=obj -compress-debug-sections -triple x86_64-pc-linux-gnu %s -o - | llvm-objdump -s - | FileCheck %s
|
||||||
|
|
||||||
|
// CHECK: Contents of section .zdebug_line:
|
||||||
|
// Check for the 'ZLIB' file magic at the start of the section
|
||||||
|
// CHECK-NEXT: ZLIB
|
||||||
|
// We shouldn't compress the debug_frame section, since it can be relaxed
|
||||||
|
// CHECK: Contents of section .debug_frame
|
||||||
|
// CHECK-NOT: ZLIB
|
||||||
|
|
||||||
|
.section .debug_line,"",@progbits
|
||||||
|
.text
|
||||||
|
foo:
|
||||||
|
.cfi_startproc
|
||||||
|
.file 1 "Driver.ii"
|
||||||
|
.loc 1 2 0
|
||||||
|
nop
|
||||||
|
.cfi_endproc
|
||||||
|
.cfi_sections .debug_frame
|
@ -49,6 +49,9 @@ OutputFilename("o", cl::desc("Output filename"),
|
|||||||
static cl::opt<bool>
|
static cl::opt<bool>
|
||||||
ShowEncoding("show-encoding", cl::desc("Show instruction encodings"));
|
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<bool>
|
static cl::opt<bool>
|
||||||
ShowInst("show-inst", cl::desc("Show internal instruction representation"));
|
ShowInst("show-inst", cl::desc("Show internal instruction representation"));
|
||||||
|
|
||||||
@ -381,6 +384,9 @@ int main(int argc, char **argv) {
|
|||||||
std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
|
std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
|
||||||
assert(MAI && "Unable to create target asm info!");
|
assert(MAI && "Unable to create target asm info!");
|
||||||
|
|
||||||
|
if (CompressDebugSections)
|
||||||
|
MAI->setCompressDebugSections(true);
|
||||||
|
|
||||||
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
|
// FIXME: This is not pretty. MCContext has a ptr to MCObjectFileInfo and
|
||||||
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
|
// MCObjectFileInfo needs a MCContext reference in order to initialize itself.
|
||||||
std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
|
std::unique_ptr<MCObjectFileInfo> MOFI(new MCObjectFileInfo());
|
||||||
|
Loading…
Reference in New Issue
Block a user