Skip to content

Commit

Permalink
Split address information for DWARF5 split dwarf proposal. This involves
Browse files Browse the repository at this point in the history
using the DW_FORM_GNU_addr_index and a separate .debug_addr section which
stays in the executable and is fully linked.

Sneak in two other small changes:

a) Print out the debug_str_offsets.dwo section.
b) Change form we're expecting the entries in the debug_str_offsets.dwo
   section to take from ULEB128 to U32.

Add tests for all of this in the fission-cu.ll test.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172578 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
echristo committed Jan 15, 2013
1 parent af50dda commit 72f7bfb
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 28 deletions.
4 changes: 4 additions & 0 deletions include/llvm/MC/MCObjectFileInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class MCObjectFileInfo {
const MCSection *DwarfLineDWOSection;
const MCSection *DwarfLocDWOSection;
const MCSection *DwarfStrOffDWOSection;
const MCSection *DwarfAddrSection;

// Extra TLS Variable Data section. If the target needs to put additional
// information for a TLS variable, it'll go here.
Expand Down Expand Up @@ -251,6 +252,9 @@ class MCObjectFileInfo {
const MCSection *getDwarfStrOffDWOSection() const {
return DwarfStrOffDWOSection;
}
const MCSection *getDwarfAddrSection() const {
return DwarfAddrSection;
}

const MCSection *getTLSExtraDataSection() const {
return TLSExtraDataSection;
Expand Down
2 changes: 2 additions & 0 deletions lib/CodeGen/AsmPrinter/DIE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const {
case dwarf::DW_FORM_ref8: // Fall thru
case dwarf::DW_FORM_data8: Size = 8; break;
case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return;
case dwarf::DW_FORM_GNU_addr_index: Asm->EmitULEB128(Integer); return;
case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return;
case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return;
case dwarf::DW_FORM_addr:
Expand All @@ -222,6 +223,7 @@ unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const {
case dwarf::DW_FORM_ref8: // Fall thru
case dwarf::DW_FORM_data8: return sizeof(int64_t);
case dwarf::DW_FORM_GNU_str_index: return MCAsmInfo::getULEB128Size(Integer);
case dwarf::DW_FORM_GNU_addr_index: return MCAsmInfo::getULEB128Size(Integer);
case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer);
case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer);
case dwarf::DW_FORM_addr: return AP->getDataLayout().getPointerSize();
Expand Down
20 changes: 20 additions & 0 deletions lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,26 @@ void CompileUnit::addLabel(DIE *Die, unsigned Attribute, unsigned Form,
Die->addValue(Attribute, Form, Value);
}

/// addLabelAddress - Add a dwarf label attribute data and value using
/// DW_FORM_addr or DW_FORM_GNU_addr_index.
///
void CompileUnit::addLabelAddress(DIE *Die, unsigned Attribute,
MCSymbol *Label) {
if (!DD->useSplitDwarf()) {
if (Label != NULL) {
DIEValue *Value = new (DIEValueAllocator) DIELabel(Label);
Die->addValue(Attribute, dwarf::DW_FORM_addr, Value);
} else {
DIEValue *Value = new (DIEValueAllocator) DIEInteger(0);
Die->addValue(Attribute, dwarf::DW_FORM_addr, Value);
}
} else {
unsigned idx = DU->getAddrPoolIndex(Label);
DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx);
Die->addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value);
}
}

/// addDelta - Add a label delta attribute data and value.
///
void CompileUnit::addDelta(DIE *Die, unsigned Attribute, unsigned Form,
Expand Down
5 changes: 5 additions & 0 deletions lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ class CompileUnit {
void addLabel(DIE *Die, unsigned Attribute, unsigned Form,
const MCSymbol *Label);

/// addLabelAddress - Add a dwarf label attribute data and value using
/// either DW_FORM_addr or DW_FORM_GNU_addr_index.
///
void addLabelAddress(DIE *Die, unsigned Attribute, MCSymbol *Label);

/// addDelta - Add a label delta attribute data and value.
///
void addDelta(DIE *Die, unsigned Attribute, unsigned Form,
Expand Down
85 changes: 65 additions & 20 deletions lib/CodeGen/AsmPrinter/DwarfDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,15 @@ unsigned DwarfUnits::getStringPoolIndex(StringRef Str) {
return Entry.second;
}

unsigned DwarfUnits::getAddrPoolIndex(MCSymbol *Sym) {
std::pair<MCSymbol*, unsigned> &Entry = AddressPool[Sym];
if (Entry.first) return Entry.second;

Entry.second = NextAddrPoolNumber++;
Entry.first = Sym;
return Entry.second;
}

// Define a unique number for the abbreviation.
//
void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) {
Expand Down Expand Up @@ -384,10 +393,12 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU,
}
}

SPCU->addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber()));
SPCU->addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
Asm->GetTempSymbol("func_end", Asm->getFunctionNumber()));
SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc,
Asm->GetTempSymbol("func_begin",
Asm->getFunctionNumber()));
SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc,
Asm->GetTempSymbol("func_end",
Asm->getFunctionNumber()));
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
Expand Down Expand Up @@ -429,16 +440,16 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
return ScopeDIE;
}

const MCSymbol *Start = getLabelBeforeInsn(RI->first);
const MCSymbol *End = getLabelAfterInsn(RI->second);
MCSymbol *Start = getLabelBeforeInsn(RI->first);
MCSymbol *End = getLabelAfterInsn(RI->second);

if (End == 0) return 0;

assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
assert(End->isDefined() && "Invalid end label for an inlined scope!");

TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start);
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End);
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, Start);
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, End);

return ScopeDIE;
}
Expand All @@ -462,8 +473,8 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
}

SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
const MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
MCSymbol *EndLabel = getLabelAfterInsn(RI->second);

if (StartLabel == 0 || EndLabel == 0) {
llvm_unreachable("Unexpected Start and End labels for an inlined scope!");
Expand Down Expand Up @@ -492,10 +503,8 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
DebugRangeSymbols.push_back(NULL);
DebugRangeSymbols.push_back(NULL);
} else {
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
StartLabel);
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
EndLabel);
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, StartLabel);
TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, EndLabel);
}

InlinedSubprogramDIEs.insert(OriginDIE);
Expand Down Expand Up @@ -646,8 +655,8 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
DIUnit.getLanguage());
NewCU->addString(Die, dwarf::DW_AT_name, FN);
// 2.17.1 requires that we use DW_AT_low_pc for a single entry point
// into an entity.
NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
// into an entity. We're using 0 (or a NULL label) for this.
NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL);
// DW_AT_stmt_list is a offset of line number information for this
// compile unit in debug_line section.
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
Expand Down Expand Up @@ -975,6 +984,9 @@ void DwarfDebug::endModule() {
// Emit info into a debug macinfo section.
emitDebugMacInfo();

// Emit DWO addresses.
InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection());

// Emit inline info.
// TODO: When we don't need the option anymore we
// can remove all of the code that this section
Expand Down Expand Up @@ -1234,14 +1246,14 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
}

// Return Label preceding the instruction.
const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
assert(Label && "Didn't insert label before instruction");
return Label;
}

// Return Label immediately following the instruction.
const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
return LabelsAfterInsn.lookup(MI);
}

Expand Down Expand Up @@ -2158,14 +2170,46 @@ void DwarfUnits::emitStrings(const MCSection *StrSection,
if (OffsetSection) {
Asm->OutStreamer.SwitchSection(OffsetSection);
unsigned offset = 0;
unsigned size = 4;
unsigned size = 4; // FIXME: DWARF64 is 8.
for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
Asm->OutStreamer.EmitIntValue(offset, size);
offset += Entries[i].second->getKeyLength() + 1;
}
}
}

// Emit strings into a string section.
void DwarfUnits::emitAddresses(const MCSection *AddrSection) {

if (AddressPool.empty()) return;

// Start the dwarf addr section.
Asm->OutStreamer.SwitchSection(AddrSection);

// Get all of the string pool entries and put them in an array by their ID so
// we can sort them.
SmallVector<std::pair<unsigned,
std::pair<MCSymbol*, unsigned>* >, 64> Entries;

for (DenseMap<MCSymbol*, std::pair<MCSymbol*, unsigned> >::iterator
I = AddressPool.begin(), E = AddressPool.end();
I != E; ++I)
Entries.push_back(std::make_pair(I->second.second, &(I->second)));

array_pod_sort(Entries.begin(), Entries.end());

for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
// Emit a label for reference from debug information entries.
MCSymbol *Sym = Entries[i].second->first;
if (Sym)
Asm->EmitLabelReference(Entries[i].second->first,
Asm->getDataLayout().getPointerSize());
else
Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize());
}

}

// Emit visible names into a debug str section.
void DwarfDebug::emitDebugStr() {
DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
Expand Down Expand Up @@ -2402,8 +2446,9 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) {
// FIXME: We also need DW_AT_addr_base and DW_AT_dwo_id.

// 2.17.1 requires that we use DW_AT_low_pc for a single entry point
// into an entity.
// into an entity. We're using 0, or a NULL label for this.
NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);

// DW_AT_stmt_list is a offset of line number information for this
// compile unit in debug_line section.
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
Expand Down
25 changes: 22 additions & 3 deletions lib/CodeGen/AsmPrinter/DwarfDebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ class DbgVariable {
typedef StringMap<std::pair<MCSymbol*, unsigned>,
BumpPtrAllocator&> StrPool;

// A Symbol->pair<Symbol, unsigned> mapping of addresses used by indirect
// references.
typedef DenseMap<MCSymbol *, std::pair<MCSymbol *, unsigned> > AddrPool;

/// \brief Collects and handles information specific to a particular
/// collection of units.
class DwarfUnits {
Expand All @@ -215,12 +219,17 @@ class DwarfUnits {
unsigned NextStringPoolNumber;
std::string StringPref;

// Collection of addresses for this unit and assorted labels.
AddrPool AddressPool;
unsigned NextAddrPoolNumber;

public:
DwarfUnits(AsmPrinter *AP, FoldingSet<DIEAbbrev> *AS,
std::vector<DIEAbbrev *> *A, const char *Pref,
BumpPtrAllocator &DA) :
Asm(AP), AbbreviationsSet(AS), Abbreviations(A),
StringPool(DA), NextStringPoolNumber(0), StringPref(Pref) {}
StringPool(DA), NextStringPoolNumber(0), StringPref(Pref),
AddressPool(), NextAddrPoolNumber(0) {}

/// \brief Compute the size and offset of a DIE given an incoming Offset.
unsigned computeSizeAndOffset(DIE *Die, unsigned Offset);
Expand All @@ -242,6 +251,9 @@ class DwarfUnits {
/// \brief Emit all of the strings to the section given.
void emitStrings(const MCSection *, const MCSection *, const MCSymbol *);

/// \brief Emit all of the addresses to the section given.
void emitAddresses(const MCSection *);

/// \brief Returns the entry into the start of the pool.
MCSymbol *getStringPoolSym();

Expand All @@ -255,6 +267,13 @@ class DwarfUnits {

/// \brief Returns the string pool.
StrPool *getStringPool() { return &StringPool; }

/// \brief Returns the index into the address pool with the given
/// label/symbol.
unsigned getAddrPoolIndex(MCSymbol *);

/// \brief Returns the address pool.
AddrPool *getAddrPool() { return &AddressPool; }
};

/// \brief Collects and handles dwarf debug information.
Expand Down Expand Up @@ -560,15 +579,15 @@ class DwarfDebug {
}

/// \brief Return Label preceding the instruction.
const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);

/// \brief Ensure that a label will be emitted after MI.
void requestLabelAfterInsn(const MachineInstr *MI) {
LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol*)0));
}

/// \brief Return Label immediately following the instruction.
const MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
MCSymbol *getLabelAfterInsn(const MachineInstr *MI);

public:
//===--------------------------------------------------------------------===//
Expand Down
6 changes: 4 additions & 2 deletions lib/DebugInfo/DWARFCompileUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class DWARFCompileUnit {
StringRef RangeSection;
StringRef StringSection;
StringRef StringOffsetSection;
StringRef AddrOffsetSection;
const RelocAddrMap *RelocMap;
bool isLittleEndian;

Expand All @@ -43,16 +44,17 @@ class DWARFCompileUnit {
public:

DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS,
StringRef RS, StringRef SS, StringRef SOS,
StringRef RS, StringRef SS, StringRef SOS, StringRef AOS,
const RelocAddrMap *M, bool LE) :
Abbrev(DA), InfoSection(IS), AbbrevSection(AS),
RangeSection(RS), StringSection(SS), StringOffsetSection(SOS),
RelocMap(M), isLittleEndian(LE) {
AddrOffsetSection(AOS), RelocMap(M), isLittleEndian(LE) {
clear();
}

StringRef getStringSection() const { return StringSection; }
StringRef getStringOffsetSection() const { return StringOffsetSection; }
StringRef getAddrOffsetSection() const { return AddrOffsetSection; }
const RelocAddrMap *getRelocMap() const { return RelocMap; }
DataExtractor getDebugInfoExtractor() const;

Expand Down
14 changes: 13 additions & 1 deletion lib/DebugInfo/DWARFContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ void DWARFContext::dump(raw_ostream &OS) {
OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
strDWOOffset = offset;
}

OS << "\n.debug_str_offsets.dwo contents:\n";
DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(), 0);
offset = 0;
while (offset < getStringOffsetDWOSection().size()) {
OS << format("0x%8.8x: ", offset);
OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
}
}

const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
Expand Down Expand Up @@ -152,7 +160,8 @@ void DWARFContext::parseCompileUnits() {
while (DIData.isValidOffset(offset)) {
CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(),
getAbbrevSection(), getRangeSection(),
getStringSection(), "",
getStringSection(), StringRef(),
getAddrSection(),
&infoRelocMap(),
isLittleEndian()));
if (!CUs.back().extract(DIData, &offset)) {
Expand All @@ -174,6 +183,7 @@ void DWARFContext::parseDWOCompileUnits() {
getRangeDWOSection(),
getStringDWOSection(),
getStringOffsetDWOSection(),
getAddrSection(),
&infoDWORelocMap(),
isLittleEndian()));
if (!DWOCUs.back().extract(DIData, &offset)) {
Expand Down Expand Up @@ -386,6 +396,8 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
StringDWOSection = data;
else if (name == "debug_str_offsets.dwo")
StringOffsetDWOSection = data;
else if (name == "debug_addr")
AddrSection = data;
// Any more debug info sections go here.
else
continue;
Expand Down
Loading

0 comments on commit 72f7bfb

Please sign in to comment.