typedef DWARFDebugLine::LineTable DWARFLineTable;
+DWARFContext::~DWARFContext() {
+ DeleteContainerPointers(CUs);
+ DeleteContainerPointers(DWOCUs);
+}
+
+static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data,
+ bool LittleEndian) {
+ OS << "\n." << Name << " contents:\n";
+ DataExtractor pubNames(Data, LittleEndian, 0);
+ uint32_t offset = 0;
+ OS << "Length: " << pubNames.getU32(&offset) << "\n";
+ OS << "Version: " << pubNames.getU16(&offset) << "\n";
+ OS << "Offset in .debug_info: " << pubNames.getU32(&offset) << "\n";
+ OS << "Size: " << pubNames.getU32(&offset) << "\n";
+ OS << "Offset Linkage Kind Name\n";
+ while (offset < Data.size()) {
+ uint32_t dieRef = pubNames.getU32(&offset);
+ if (dieRef == 0)
+ break;
+ PubIndexEntryDescriptor desc(pubNames.getU8(&offset));
+ OS << format("0x%8.8x ", dieRef)
+ << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage)) << ' '
+ << dwarf::GDBIndexEntryKindString(desc.Kind) << " \""
+ << pubNames.getCStr(&offset) << "\"\n";
+ }
+}
+
void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
OS << ".debug_abbrev contents:\n";
getCompileUnitAtIndex(i)->dump(OS);
}
+ if (DumpType == DIDT_All || DumpType == DIDT_Types) {
+ OS << "\n.debug_types contents:\n";
+ for (unsigned i = 0, e = getNumTypeUnits(); i != e; ++i)
+ getTypeUnitAtIndex(i)->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
+ OS << "\n.debug_loc contents:\n";
+ getDebugLoc()->dump(OS);
+ }
+
if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
OS << "\n.debug_frame contents:\n";
getDebugFrame()->dump(OS);
cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
-1U);
if (stmtOffset != -1U) {
- DataExtractor lineData(getLineSection(), isLittleEndian(),
+ DataExtractor lineData(getLineSection().Data, isLittleEndian(),
savedAddressByteSize);
DWARFDebugLine::DumpingState state(OS);
- DWARFDebugLine::parseStatementTable(lineData, &lineRelocMap(), &stmtOffset, state);
+ DWARFDebugLine::parseStatementTable(lineData, &getLineSection().Relocs, &stmtOffset, state);
}
}
}
}
}
+ if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames)
+ dumpPubSection(OS, "debug_gnu_pubnames", getGnuPubNamesSection(),
+ isLittleEndian());
+
+ if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes)
+ dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(),
+ isLittleEndian());
+
if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo) {
const DWARFDebugAbbrev *D = getDebugAbbrevDWO();
if (D) {
return AbbrevDWO.get();
}
+const DWARFDebugLoc *DWARFContext::getDebugLoc() {
+ if (Loc)
+ return Loc.get();
+
+ DataExtractor LocData(getLocSection().Data, isLittleEndian(), 0);
+ Loc.reset(new DWARFDebugLoc(getLocSection().Relocs));
+ // assume all compile units have the same address byte size
+ if (getNumCompileUnits())
+ Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize());
+ return Loc.get();
+}
+
const DWARFDebugAranges *DWARFContext::getDebugAranges() {
if (Aranges)
return Aranges.get();
const DWARFLineTable *
DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
if (!Line)
- Line.reset(new DWARFDebugLine(&lineRelocMap()));
+ Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
unsigned stmtOffset =
cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
return lt;
// We have to parse it first.
- DataExtractor lineData(getLineSection(), isLittleEndian(),
+ DataExtractor lineData(getLineSection().Data, isLittleEndian(),
cu->getAddressByteSize());
return Line->getOrParseLineTable(lineData, stmtOffset);
}
void DWARFContext::parseCompileUnits() {
uint32_t offset = 0;
- const DataExtractor &DIData = DataExtractor(getInfoSection(),
+ const DataExtractor &DIData = DataExtractor(getInfoSection().Data,
isLittleEndian(), 0);
while (DIData.isValidOffset(offset)) {
- CUs.push_back(DWARFCompileUnit(getDebugAbbrev(), getInfoSection(),
- getAbbrevSection(), getRangeSection(),
- getStringSection(), StringRef(),
- getAddrSection(),
- &infoRelocMap(),
- isLittleEndian()));
- if (!CUs.back().extract(DIData, &offset)) {
- CUs.pop_back();
+ OwningPtr<DWARFCompileUnit> CU(new DWARFCompileUnit(
+ getDebugAbbrev(), getInfoSection().Data, getAbbrevSection(),
+ getRangeSection(), getStringSection(), StringRef(), getAddrSection(),
+ &getInfoSection().Relocs, isLittleEndian()));
+ if (!CU->extract(DIData, &offset)) {
break;
}
+ CUs.push_back(CU.take());
+ offset = CUs.back()->getNextUnitOffset();
+ }
+}
- offset = CUs.back().getNextCompileUnitOffset();
+void DWARFContext::parseTypeUnits() {
+ const std::map<object::SectionRef, Section> &Sections = getTypesSections();
+ for (std::map<object::SectionRef, Section>::const_iterator
+ I = Sections.begin(),
+ E = Sections.end();
+ I != E; ++I) {
+ uint32_t offset = 0;
+ const DataExtractor &DIData =
+ DataExtractor(I->second.Data, isLittleEndian(), 0);
+ while (DIData.isValidOffset(offset)) {
+ OwningPtr<DWARFTypeUnit> TU(new DWARFTypeUnit(
+ getDebugAbbrev(), I->second.Data, getAbbrevSection(),
+ getRangeSection(), getStringSection(), StringRef(), getAddrSection(),
+ &I->second.Relocs, isLittleEndian()));
+ if (!TU->extract(DIData, &offset))
+ break;
+ TUs.push_back(TU.take());
+ offset = TUs.back()->getNextUnitOffset();
+ }
}
}
void DWARFContext::parseDWOCompileUnits() {
uint32_t offset = 0;
- const DataExtractor &DIData = DataExtractor(getInfoDWOSection(),
- isLittleEndian(), 0);
+ const DataExtractor &DIData =
+ DataExtractor(getInfoDWOSection().Data, isLittleEndian(), 0);
while (DIData.isValidOffset(offset)) {
- DWOCUs.push_back(DWARFCompileUnit(getDebugAbbrevDWO(), getInfoDWOSection(),
- getAbbrevDWOSection(),
- getRangeDWOSection(),
- getStringDWOSection(),
- getStringOffsetDWOSection(),
- getAddrSection(),
- &infoDWORelocMap(),
- isLittleEndian()));
- if (!DWOCUs.back().extract(DIData, &offset)) {
- DWOCUs.pop_back();
+ OwningPtr<DWARFCompileUnit> DWOCU(new DWARFCompileUnit(
+ getDebugAbbrevDWO(), getInfoDWOSection().Data, getAbbrevDWOSection(),
+ getRangeDWOSection(), getStringDWOSection(),
+ getStringOffsetDWOSection(), getAddrSection(),
+ &getInfoDWOSection().Relocs, isLittleEndian()));
+ if (!DWOCU->extract(DIData, &offset)) {
break;
}
-
- offset = DWOCUs.back().getNextCompileUnitOffset();
+ DWOCUs.push_back(DWOCU.take());
+ offset = DWOCUs.back()->getNextUnitOffset();
}
}
namespace {
struct OffsetComparator {
- bool operator()(const DWARFCompileUnit &LHS,
- const DWARFCompileUnit &RHS) const {
- return LHS.getOffset() < RHS.getOffset();
+ bool operator()(const DWARFCompileUnit *LHS,
+ const DWARFCompileUnit *RHS) const {
+ return LHS->getOffset() < RHS->getOffset();
}
- bool operator()(const DWARFCompileUnit &LHS, uint32_t RHS) const {
- return LHS.getOffset() < RHS;
+ bool operator()(const DWARFCompileUnit *LHS, uint32_t RHS) const {
+ return LHS->getOffset() < RHS;
}
- bool operator()(uint32_t LHS, const DWARFCompileUnit &RHS) const {
- return LHS < RHS.getOffset();
+ bool operator()(uint32_t LHS, const DWARFCompileUnit *RHS) const {
+ return LHS < RHS->getOffset();
}
};
}
if (CUs.empty())
parseCompileUnits();
- DWARFCompileUnit *CU = std::lower_bound(CUs.begin(), CUs.end(), Offset,
- OffsetComparator());
- if (CU != CUs.end())
- return &*CU;
+ DWARFCompileUnit **CU =
+ std::lower_bound(CUs.begin(), CUs.end(), Offset, OffsetComparator());
+ if (CU != CUs.end()) {
+ return *CU;
+ }
return 0;
}
// The address may correspond to instruction in some inlined function,
// so we have to build the chain of inlined functions and take the
// name of the topmost function in it.
- const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ const DWARFDebugInfoEntryInlinedChain &InlinedChain =
CU->getInlinedChainForAddress(Address);
- if (InlinedChain.size() > 0) {
- const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
- if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
+ if (InlinedChain.DIEs.size() > 0) {
+ const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
+ if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U))
FunctionName = Name;
}
}
// The address may correspond to instruction in some inlined function,
// so we have to build the chain of inlined functions and take the
// name of the topmost function in it.
- const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ const DWARFDebugInfoEntryInlinedChain &InlinedChain =
CU->getInlinedChainForAddress(Address);
- if (InlinedChain.size() > 0) {
- const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain[0];
- if (const char *Name = TopFunctionDIE.getSubroutineName(CU))
+ if (InlinedChain.DIEs.size() > 0) {
+ const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
+ if (const char *Name = TopFunctionDIE.getSubroutineName(InlinedChain.U))
FunctionName = Name;
}
}
- StringRef FuncNameRef = StringRef(FunctionName);
-
// If the Specifier says we don't need FileLineInfo, just
// return the top-most function at the starting address.
if (!Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
- Lines.push_back(std::make_pair(Address,
- DILineInfo(StringRef("<invalid>"),
- FuncNameRef, 0, 0)));
+ Lines.push_back(
+ std::make_pair(Address, DILineInfo("<invalid>", FunctionName, 0, 0)));
return Lines;
}
std::string FileName = "<invalid>";
getFileNameForCompileUnit(CU, LineTable, Row.File,
NeedsAbsoluteFilePath, FileName);
- Lines.push_back(std::make_pair(Row.Address,
- DILineInfo(StringRef(FileName),
- FuncNameRef, Row.Line, Row.Column)));
+ Lines.push_back(std::make_pair(
+ Row.Address, DILineInfo(FileName, FunctionName, Row.Line, Row.Column)));
}
return Lines;
if (!CU)
return DIInliningInfo();
- const DWARFDebugInfoEntryMinimal::InlinedChain &InlinedChain =
+ const DWARFDebugInfoEntryInlinedChain &InlinedChain =
CU->getInlinedChainForAddress(Address);
- if (InlinedChain.size() == 0)
+ if (InlinedChain.DIEs.size() == 0)
return DIInliningInfo();
DIInliningInfo InliningInfo;
uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
const DWARFLineTable *LineTable = 0;
- for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) {
- const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain[i];
+ for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) {
+ const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i];
std::string FileName = "<invalid>";
std::string FunctionName = "<invalid>";
uint32_t Line = 0;
uint32_t Column = 0;
// Get function name if necessary.
if (Specifier.needs(DILineInfoSpecifier::FunctionName)) {
- if (const char *Name = FunctionDIE.getSubroutineName(CU))
+ if (const char *Name = FunctionDIE.getSubroutineName(InlinedChain.U))
FunctionName = Name;
}
if (Specifier.needs(DILineInfoSpecifier::FileLineInfo)) {
}
// Get call file/line/column of a current DIE.
if (i + 1 < n) {
- FunctionDIE.getCallerFrame(CU, CallFile, CallLine, CallColumn);
+ FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine,
+ CallColumn);
}
}
DILineInfo Frame(StringRef(FileName), StringRef(FunctionName),
}
StringRef *Section = StringSwitch<StringRef*>(name)
- .Case("debug_info", &InfoSection)
+ .Case("debug_info", &InfoSection.Data)
.Case("debug_abbrev", &AbbrevSection)
- .Case("debug_line", &LineSection)
+ .Case("debug_loc", &LocSection.Data)
+ .Case("debug_line", &LineSection.Data)
.Case("debug_aranges", &ARangeSection)
.Case("debug_frame", &DebugFrameSection)
.Case("debug_str", &StringSection)
.Case("debug_ranges", &RangeSection)
.Case("debug_pubnames", &PubNamesSection)
- .Case("debug_info.dwo", &InfoDWOSection)
+ .Case("debug_gnu_pubnames", &GnuPubNamesSection)
+ .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
+ .Case("debug_info.dwo", &InfoDWOSection.Data)
.Case("debug_abbrev.dwo", &AbbrevDWOSection)
.Case("debug_str.dwo", &StringDWOSection)
.Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
// FIXME: Use the other dwo range section when we emit it.
RangeDWOSection = data;
}
+ } else if (name == "debug_types") {
+ // Find debug_types data by section rather than name as there are
+ // multiple, comdat grouped, debug_types sections.
+ TypesSections[*i].Data = data;
}
section_iterator RelocatedSection = i->getRelocatedSection();
// TODO: Add support for relocations in other sections as needed.
// Record relocations for the debug_info and debug_line sections.
RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
- .Case("debug_info", &InfoRelocMap)
- .Case("debug_info.dwo", &InfoDWORelocMap)
- .Case("debug_line", &LineRelocMap)
+ .Case("debug_info", &InfoSection.Relocs)
+ .Case("debug_loc", &LocSection.Relocs)
+ .Case("debug_info.dwo", &InfoDWOSection.Relocs)
+ .Case("debug_line", &LineSection.Relocs)
.Default(0);
- if (!Map)
- continue;
+ if (!Map) {
+ if (RelSecName != "debug_types")
+ continue;
+ // Find debug_types relocs by section rather than name as there are
+ // multiple, comdat grouped, debug_types sections.
+ Map = &TypesSections[*RelocatedSection].Relocs;
+ }
if (i->begin_relocations() != i->end_relocations()) {
uint64_t SectionSize;
uint64_t SymAddr = 0;
// ELF relocations may need the symbol address
if (Obj->isELF()) {
- object::SymbolRef Sym;
- reloc_i->getSymbol(Sym);
- Sym.getAddress(SymAddr);
+ object::symbol_iterator Sym = reloc_i->getSymbol();
+ Sym->getAddress(SymAddr);
}
object::RelocVisitor V(Obj->getFileFormatName());