Split address information for DWARF5 split dwarf proposal. This involves

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
This commit is contained in:
Eric Christopher
2013-01-15 23:56:56 +00:00
parent af50dda410
commit 72f7bfbf0e
13 changed files with 204 additions and 28 deletions

View File

@ -115,6 +115,7 @@ protected:
const MCSection *DwarfLineDWOSection; const MCSection *DwarfLineDWOSection;
const MCSection *DwarfLocDWOSection; const MCSection *DwarfLocDWOSection;
const MCSection *DwarfStrOffDWOSection; const MCSection *DwarfStrOffDWOSection;
const MCSection *DwarfAddrSection;
// Extra TLS Variable Data section. If the target needs to put additional // Extra TLS Variable Data section. If the target needs to put additional
// information for a TLS variable, it'll go here. // information for a TLS variable, it'll go here.
@ -251,6 +252,9 @@ public:
const MCSection *getDwarfStrOffDWOSection() const { const MCSection *getDwarfStrOffDWOSection() const {
return DwarfStrOffDWOSection; return DwarfStrOffDWOSection;
} }
const MCSection *getDwarfAddrSection() const {
return DwarfAddrSection;
}
const MCSection *getTLSExtraDataSection() const { const MCSection *getTLSExtraDataSection() const {
return TLSExtraDataSection; return TLSExtraDataSection;

View File

@ -198,6 +198,7 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const {
case dwarf::DW_FORM_ref8: // Fall thru case dwarf::DW_FORM_ref8: // Fall thru
case dwarf::DW_FORM_data8: Size = 8; break; case dwarf::DW_FORM_data8: Size = 8; break;
case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return; 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_udata: Asm->EmitULEB128(Integer); return;
case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return; case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return;
case dwarf::DW_FORM_addr: case dwarf::DW_FORM_addr:
@ -222,6 +223,7 @@ unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const {
case dwarf::DW_FORM_ref8: // Fall thru case dwarf::DW_FORM_ref8: // Fall thru
case dwarf::DW_FORM_data8: return sizeof(int64_t); 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_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_udata: return MCAsmInfo::getULEB128Size(Integer);
case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer); case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer);
case dwarf::DW_FORM_addr: return AP->getDataLayout().getPointerSize(); case dwarf::DW_FORM_addr: return AP->getDataLayout().getPointerSize();

View File

@ -170,6 +170,26 @@ void CompileUnit::addLabel(DIE *Die, unsigned Attribute, unsigned Form,
Die->addValue(Attribute, Form, Value); 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. /// addDelta - Add a label delta attribute data and value.
/// ///
void CompileUnit::addDelta(DIE *Die, unsigned Attribute, unsigned Form, void CompileUnit::addDelta(DIE *Die, unsigned Attribute, unsigned Form,

View File

@ -207,6 +207,11 @@ public:
void addLabel(DIE *Die, unsigned Attribute, unsigned Form, void addLabel(DIE *Die, unsigned Attribute, unsigned Form,
const MCSymbol *Label); 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. /// addDelta - Add a label delta attribute data and value.
/// ///
void addDelta(DIE *Die, unsigned Attribute, unsigned Form, void addDelta(DIE *Die, unsigned Attribute, unsigned Form,

View File

@ -237,6 +237,15 @@ unsigned DwarfUnits::getStringPoolIndex(StringRef Str) {
return Entry.second; 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. // Define a unique number for the abbreviation.
// //
void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) { void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) {
@ -384,10 +393,12 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU,
} }
} }
SPCU->addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc,
Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber())); Asm->GetTempSymbol("func_begin",
SPCU->addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, Asm->getFunctionNumber()));
Asm->GetTempSymbol("func_end", Asm->getFunctionNumber())); SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc,
Asm->GetTempSymbol("func_end",
Asm->getFunctionNumber()));
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
MachineLocation Location(RI->getFrameRegister(*Asm->MF)); MachineLocation Location(RI->getFrameRegister(*Asm->MF));
SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location); SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
@ -429,16 +440,16 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
return ScopeDIE; return ScopeDIE;
} }
const MCSymbol *Start = getLabelBeforeInsn(RI->first); MCSymbol *Start = getLabelBeforeInsn(RI->first);
const MCSymbol *End = getLabelAfterInsn(RI->second); MCSymbol *End = getLabelAfterInsn(RI->second);
if (End == 0) return 0; if (End == 0) return 0;
assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
assert(End->isDefined() && "Invalid end 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->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, Start);
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End); TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, End);
return ScopeDIE; return ScopeDIE;
} }
@ -462,8 +473,8 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
} }
SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(); SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin();
const MCSymbol *StartLabel = getLabelBeforeInsn(RI->first); MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
const MCSymbol *EndLabel = getLabelAfterInsn(RI->second); MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
if (StartLabel == 0 || EndLabel == 0) { if (StartLabel == 0 || EndLabel == 0) {
llvm_unreachable("Unexpected Start and End labels for an inlined scope!"); llvm_unreachable("Unexpected Start and End labels for an inlined scope!");
@ -492,10 +503,8 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
DebugRangeSymbols.push_back(NULL); DebugRangeSymbols.push_back(NULL);
DebugRangeSymbols.push_back(NULL); DebugRangeSymbols.push_back(NULL);
} else { } else {
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, StartLabel);
StartLabel); TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, EndLabel);
TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
EndLabel);
} }
InlinedSubprogramDIEs.insert(OriginDIE); InlinedSubprogramDIEs.insert(OriginDIE);
@ -646,8 +655,8 @@ CompileUnit *DwarfDebug::constructCompileUnit(const MDNode *N) {
DIUnit.getLanguage()); DIUnit.getLanguage());
NewCU->addString(Die, dwarf::DW_AT_name, FN); NewCU->addString(Die, dwarf::DW_AT_name, FN);
// 2.17.1 requires that we use DW_AT_low_pc for a single entry point // 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); NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL);
// DW_AT_stmt_list is a offset of line number information for this // DW_AT_stmt_list is a offset of line number information for this
// compile unit in debug_line section. // compile unit in debug_line section.
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
@ -975,6 +984,9 @@ void DwarfDebug::endModule() {
// Emit info into a debug macinfo section. // Emit info into a debug macinfo section.
emitDebugMacInfo(); emitDebugMacInfo();
// Emit DWO addresses.
InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection());
// Emit inline info. // Emit inline info.
// TODO: When we don't need the option anymore we // TODO: When we don't need the option anymore we
// can remove all of the code that this section // can remove all of the code that this section
@ -1234,14 +1246,14 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
} }
// Return Label preceding the instruction. // Return Label preceding the instruction.
const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) { MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) {
MCSymbol *Label = LabelsBeforeInsn.lookup(MI); MCSymbol *Label = LabelsBeforeInsn.lookup(MI);
assert(Label && "Didn't insert label before instruction"); assert(Label && "Didn't insert label before instruction");
return Label; return Label;
} }
// Return Label immediately following the instruction. // Return Label immediately following the instruction.
const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
return LabelsAfterInsn.lookup(MI); return LabelsAfterInsn.lookup(MI);
} }
@ -2158,7 +2170,7 @@ void DwarfUnits::emitStrings(const MCSection *StrSection,
if (OffsetSection) { if (OffsetSection) {
Asm->OutStreamer.SwitchSection(OffsetSection); Asm->OutStreamer.SwitchSection(OffsetSection);
unsigned offset = 0; unsigned offset = 0;
unsigned size = 4; unsigned size = 4; // FIXME: DWARF64 is 8.
for (unsigned i = 0, e = Entries.size(); i != e; ++i) { for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
Asm->OutStreamer.EmitIntValue(offset, size); Asm->OutStreamer.EmitIntValue(offset, size);
offset += Entries[i].second->getKeyLength() + 1; offset += Entries[i].second->getKeyLength() + 1;
@ -2166,6 +2178,38 @@ void DwarfUnits::emitStrings(const MCSection *StrSection,
} }
} }
// 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. // Emit visible names into a debug str section.
void DwarfDebug::emitDebugStr() { void DwarfDebug::emitDebugStr() {
DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
@ -2402,8 +2446,9 @@ CompileUnit *DwarfDebug::constructSkeletonCU(const MDNode *N) {
// FIXME: We also need DW_AT_addr_base and DW_AT_dwo_id. // 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 // 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); 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 // DW_AT_stmt_list is a offset of line number information for this
// compile unit in debug_line section. // compile unit in debug_line section.
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())

View File

@ -195,6 +195,10 @@ public:
typedef StringMap<std::pair<MCSymbol*, unsigned>, typedef StringMap<std::pair<MCSymbol*, unsigned>,
BumpPtrAllocator&> StrPool; 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 /// \brief Collects and handles information specific to a particular
/// collection of units. /// collection of units.
class DwarfUnits { class DwarfUnits {
@ -215,12 +219,17 @@ class DwarfUnits {
unsigned NextStringPoolNumber; unsigned NextStringPoolNumber;
std::string StringPref; std::string StringPref;
// Collection of addresses for this unit and assorted labels.
AddrPool AddressPool;
unsigned NextAddrPoolNumber;
public: public:
DwarfUnits(AsmPrinter *AP, FoldingSet<DIEAbbrev> *AS, DwarfUnits(AsmPrinter *AP, FoldingSet<DIEAbbrev> *AS,
std::vector<DIEAbbrev *> *A, const char *Pref, std::vector<DIEAbbrev *> *A, const char *Pref,
BumpPtrAllocator &DA) : BumpPtrAllocator &DA) :
Asm(AP), AbbreviationsSet(AS), Abbreviations(A), 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. /// \brief Compute the size and offset of a DIE given an incoming Offset.
unsigned computeSizeAndOffset(DIE *Die, unsigned Offset); unsigned computeSizeAndOffset(DIE *Die, unsigned Offset);
@ -242,6 +251,9 @@ public:
/// \brief Emit all of the strings to the section given. /// \brief Emit all of the strings to the section given.
void emitStrings(const MCSection *, const MCSection *, const MCSymbol *); 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. /// \brief Returns the entry into the start of the pool.
MCSymbol *getStringPoolSym(); MCSymbol *getStringPoolSym();
@ -255,6 +267,13 @@ public:
/// \brief Returns the string pool. /// \brief Returns the string pool.
StrPool *getStringPool() { return &StringPool; } 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. /// \brief Collects and handles dwarf debug information.
@ -560,7 +579,7 @@ private:
} }
/// \brief Return Label preceding the instruction. /// \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. /// \brief Ensure that a label will be emitted after MI.
void requestLabelAfterInsn(const MachineInstr *MI) { void requestLabelAfterInsn(const MachineInstr *MI) {
@ -568,7 +587,7 @@ private:
} }
/// \brief Return Label immediately following the instruction. /// \brief Return Label immediately following the instruction.
const MCSymbol *getLabelAfterInsn(const MachineInstr *MI); MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
public: public:
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//

View File

@ -29,6 +29,7 @@ class DWARFCompileUnit {
StringRef RangeSection; StringRef RangeSection;
StringRef StringSection; StringRef StringSection;
StringRef StringOffsetSection; StringRef StringOffsetSection;
StringRef AddrOffsetSection;
const RelocAddrMap *RelocMap; const RelocAddrMap *RelocMap;
bool isLittleEndian; bool isLittleEndian;
@ -43,16 +44,17 @@ class DWARFCompileUnit {
public: public:
DWARFCompileUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, 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) : const RelocAddrMap *M, bool LE) :
Abbrev(DA), InfoSection(IS), AbbrevSection(AS), Abbrev(DA), InfoSection(IS), AbbrevSection(AS),
RangeSection(RS), StringSection(SS), StringOffsetSection(SOS), RangeSection(RS), StringSection(SS), StringOffsetSection(SOS),
RelocMap(M), isLittleEndian(LE) { AddrOffsetSection(AOS), RelocMap(M), isLittleEndian(LE) {
clear(); clear();
} }
StringRef getStringSection() const { return StringSection; } StringRef getStringSection() const { return StringSection; }
StringRef getStringOffsetSection() const { return StringOffsetSection; } StringRef getStringOffsetSection() const { return StringOffsetSection; }
StringRef getAddrOffsetSection() const { return AddrOffsetSection; }
const RelocAddrMap *getRelocMap() const { return RelocMap; } const RelocAddrMap *getRelocMap() const { return RelocMap; }
DataExtractor getDebugInfoExtractor() const; DataExtractor getDebugInfoExtractor() const;

View File

@ -86,6 +86,14 @@ void DWARFContext::dump(raw_ostream &OS) {
OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s); OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
strDWOOffset = offset; 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() { const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
@ -152,7 +160,8 @@ void DWARFContext::parseCompileUnits() {
while (DIData.isValidOffset(offset)) { while (DIData.isValidOffset(offset)) {
CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(), CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(),
getAbbrevSection(), getRangeSection(), getAbbrevSection(), getRangeSection(),
getStringSection(), "", getStringSection(), StringRef(),
getAddrSection(),
&infoRelocMap(), &infoRelocMap(),
isLittleEndian())); isLittleEndian()));
if (!CUs.back().extract(DIData, &offset)) { if (!CUs.back().extract(DIData, &offset)) {
@ -174,6 +183,7 @@ void DWARFContext::parseDWOCompileUnits() {
getRangeDWOSection(), getRangeDWOSection(),
getStringDWOSection(), getStringDWOSection(),
getStringOffsetDWOSection(), getStringOffsetDWOSection(),
getAddrSection(),
&infoDWORelocMap(), &infoDWORelocMap(),
isLittleEndian())); isLittleEndian()));
if (!DWOCUs.back().extract(DIData, &offset)) { if (!DWOCUs.back().extract(DIData, &offset)) {
@ -386,6 +396,8 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
StringDWOSection = data; StringDWOSection = data;
else if (name == "debug_str_offsets.dwo") else if (name == "debug_str_offsets.dwo")
StringOffsetDWOSection = data; StringOffsetDWOSection = data;
else if (name == "debug_addr")
AddrSection = data;
// Any more debug info sections go here. // Any more debug info sections go here.
else else
continue; continue;

View File

@ -108,6 +108,7 @@ public:
virtual StringRef getStringDWOSection() = 0; virtual StringRef getStringDWOSection() = 0;
virtual StringRef getStringOffsetDWOSection() = 0; virtual StringRef getStringOffsetDWOSection() = 0;
virtual StringRef getRangeDWOSection() = 0; virtual StringRef getRangeDWOSection() = 0;
virtual StringRef getAddrSection() = 0;
virtual const RelocAddrMap &infoDWORelocMap() const = 0; virtual const RelocAddrMap &infoDWORelocMap() const = 0;
static bool isSupportedVersion(unsigned version) { static bool isSupportedVersion(unsigned version) {
@ -143,6 +144,7 @@ class DWARFContextInMemory : public DWARFContext {
StringRef StringDWOSection; StringRef StringDWOSection;
StringRef StringOffsetDWOSection; StringRef StringOffsetDWOSection;
StringRef RangeDWOSection; StringRef RangeDWOSection;
StringRef AddrSection;
public: public:
DWARFContextInMemory(object::ObjectFile *); DWARFContextInMemory(object::ObjectFile *);
@ -163,6 +165,9 @@ public:
return StringOffsetDWOSection; return StringOffsetDWOSection;
} }
virtual StringRef getRangeDWOSection() { return RangeDWOSection; } virtual StringRef getRangeDWOSection() { return RangeDWOSection; }
virtual StringRef getAddrSection() {
return AddrSection;
}
virtual const RelocAddrMap &infoDWORelocMap() const { virtual const RelocAddrMap &infoDWORelocMap() const {
return InfoDWORelocMap; return InfoDWORelocMap;
} }

View File

@ -325,6 +325,16 @@ DWARFFormValue::dump(raw_ostream &OS, const DWARFCompileUnit *cu) const {
switch (Form) { switch (Form) {
case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break; case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break;
case DW_FORM_GNU_addr_index: {
StringRef AddrOffsetSec = cu->getAddrOffsetSection();
OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
if (AddrOffsetSec.size() != 0) {
DataExtractor DA(AddrOffsetSec, true, cu->getAddressByteSize());
OS << format("0x%016" PRIx64, getIndirectAddress(&DA, cu));
} else
OS << "<no .debug_addr section>";
break;
}
case DW_FORM_flag_present: OS << "true"; break; case DW_FORM_flag_present: OS << "true"; break;
case DW_FORM_flag: case DW_FORM_flag:
case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break; case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break;
@ -452,10 +462,19 @@ DWARFFormValue::getIndirectCString(const DataExtractor *DS,
if (!DS || !DSO) return NULL; if (!DS || !DSO) return NULL;
uint32_t offset = Value.uval * 4; uint32_t offset = Value.uval * 4;
uint32_t soffset = DSO->getULEB128(&offset); uint32_t soffset = DSO->getU32(&offset);
return DS->getCStr(&soffset); return DS->getCStr(&soffset);
} }
uint64_t
DWARFFormValue::getIndirectAddress(const DataExtractor *DA,
const DWARFCompileUnit *cu) const {
if (!DA) return 0;
uint32_t offset = Value.uval * cu->getAddressByteSize();
return DA->getAddress(&offset);
}
uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const { uint64_t DWARFFormValue::getReference(const DWARFCompileUnit *cu) const {
uint64_t die_offset = Value.uval; uint64_t die_offset = Value.uval;
switch (Form) { switch (Form) {

View File

@ -66,6 +66,8 @@ public:
const char *getAsCString(const DataExtractor *debug_str_data_ptr) const; const char *getAsCString(const DataExtractor *debug_str_data_ptr) const;
const char *getIndirectCString(const DataExtractor *, const char *getIndirectCString(const DataExtractor *,
const DataExtractor *) const; const DataExtractor *) const;
uint64_t getIndirectAddress(const DataExtractor *,
const DWARFCompileUnit *) const;
bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr,
const DWARFCompileUnit *cu) const; const DWARFCompileUnit *cu) const;
static bool skipValue(uint16_t form, DataExtractor debug_info_data, static bool skipValue(uint16_t form, DataExtractor debug_info_data,

View File

@ -437,6 +437,9 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
DwarfStrOffDWOSection = DwarfStrOffDWOSection =
Ctx->getELFSection(".debug_str_offsets.dwo", ELF::SHT_PROGBITS, 0, Ctx->getELFSection(".debug_str_offsets.dwo", ELF::SHT_PROGBITS, 0,
SectionKind::getMetadata()); SectionKind::getMetadata());
DwarfAddrSection =
Ctx->getELFSection(".debug_addr", ELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
} }

View File

@ -26,14 +26,52 @@
; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x00000000) ; CHECK: DW_AT_stmt_list [DW_FORM_data4] (0x00000000)
; CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000006] = "/usr/local/google/home/echristo/tmp") ; CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000006] = "/usr/local/google/home/echristo/tmp")
; Check that we're using the right forms.
; CHECK: .debug_abbrev.dwo contents:
; CHECK: Abbrev table for offset: 0x00000000
; CHECK: [1] DW_TAG_compile_unit DW_CHILDREN_yes
; CHECK: DW_AT_producer DW_FORM_GNU_str_index
; CHECK: DW_AT_language DW_FORM_data2
; CHECK: DW_AT_name DW_FORM_GNU_str_index
; CHECK: DW_AT_low_pc DW_FORM_GNU_addr_index
; CHECK: DW_AT_stmt_list DW_FORM_data4
; CHECK: DW_AT_comp_dir DW_FORM_GNU_str_index
; CHECK: [2] DW_TAG_base_type DW_CHILDREN_no
; CHECK: DW_AT_name DW_FORM_GNU_str_index
; CHECK: DW_AT_encoding DW_FORM_data1
; CHECK: DW_AT_byte_size DW_FORM_data1
; CHECK: [3] DW_TAG_variable DW_CHILDREN_no
; CHECK: DW_AT_name DW_FORM_GNU_str_index
; CHECK: DW_AT_type DW_FORM_ref4
; CHECK: DW_AT_external DW_FORM_flag_present
; CHECK: DW_AT_decl_file DW_FORM_data1
; CHECK: DW_AT_decl_line DW_FORM_data1
; CHECK: DW_AT_location DW_FORM_block1
; Check that the rest of the compile units have information. ; Check that the rest of the compile units have information.
; FIXME: Strings will ultimately be a different form.
; CHECK: .debug_info.dwo contents: ; CHECK: .debug_info.dwo contents:
; CHECK: DW_TAG_compile_unit ; CHECK: DW_TAG_compile_unit
; CHECK: DW_AT_producer [DW_FORM_GNU_str_index] ( indexed (00000000) string = "clang version 3.3 (trunk 169021) (llvm/trunk 169020)") ; CHECK: DW_AT_producer [DW_FORM_GNU_str_index] ( indexed (00000000) string = "clang version 3.3 (trunk 169021) (llvm/trunk 169020)")
; CHECK: DW_AT_language [DW_FORM_data2] (0x000c) ; CHECK: DW_AT_language [DW_FORM_data2] (0x000c)
; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000001) string = "baz.c") ; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000001) string = "baz.c")
; CHECK: DW_AT_low_pc [DW_FORM_GNU_addr_index] ( indexed (00000000) address = 0x0000000000000000)
; CHECK: DW_TAG_base_type ; CHECK: DW_TAG_base_type
; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000004) string = "int") ; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000004) string = "int")
; CHECK: DW_TAG_variable ; CHECK: DW_TAG_variable
; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000003) string = "a") ; CHECK: DW_AT_name [DW_FORM_GNU_str_index] ( indexed (00000003) string = "a")
; CHECK: .debug_str.dwo contents:
; CHECK: 0x00000000: "clang version 3.3 (trunk 169021) (llvm/trunk 169020)"
; CHECK: 0x00000035: "baz.c"
; CHECK: 0x0000003b: "/usr/local/google/home/echristo/tmp"
; CHECK: 0x0000005f: "a"
; CHECK: 0x00000061: "int"
; CHECK: .debug_str_offsets.dwo contents:
; CHECK: 0x00000000: 00000000
; CHECK: 0x00000004: 00000035
; CHECK: 0x00000008: 0000003b
; CHECK: 0x0000000c: 0000005f
; CHECK: 0x00000010: 00000061