#include "llvm/ADT/StringSwitch.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Format.h"
getDebugFrame()->dump(OS);
}
+ if (DumpType == DIDT_All || DumpType == DIDT_Macro) {
+ OS << "\n.debug_macinfo contents:\n";
+ getDebugMacro()->dump(OS);
+ }
+
uint32_t offset = 0;
if (DumpType == DIDT_All || DumpType == DIDT_Aranges) {
OS << "\n.debug_aranges contents:\n";
OS << "\n.debug_line contents:\n";
for (const auto &CU : compile_units()) {
savedAddressByteSize = CU->getAddressByteSize();
- unsigned stmtOffset =
- CU->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
- CU.get(), DW_AT_stmt_list, -1U);
+ const auto *CUDIE = CU->getUnitDIE();
+ if (CUDIE == nullptr)
+ continue;
+ unsigned stmtOffset = CUDIE->getAttributeValueAsSectionOffset(
+ CU.get(), DW_AT_stmt_list, -1U);
if (stmtOffset != -1U) {
DataExtractor lineData(getLineSection().Data, isLittleEndian(),
savedAddressByteSize);
}
}
+ if (DumpType == DIDT_All || DumpType == DIDT_CUIndex) {
+ OS << "\n.debug_cu_index contents:\n";
+ DataExtractor CUIndexData(getCUIndexSection(), isLittleEndian(),
+ savedAddressByteSize);
+ DWARFUnitIndex CUIndex;
+ if (CUIndex.parse(CUIndexData))
+ CUIndex.dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_TUIndex) {
+ OS << "\n.debug_tu_index contents:\n";
+ DataExtractor TUIndexData(getTUIndexSection(), isLittleEndian(),
+ savedAddressByteSize);
+ DWARFUnitIndex TUIndex;
+ if (TUIndex.parse(TUIndexData))
+ TUIndex.dump(OS);
+ }
+
if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) {
OS << "\n.debug_line.dwo contents:\n";
unsigned stmtOffset = 0;
return DebugFrame.get();
}
+const DWARFDebugMacro *DWARFContext::getDebugMacro() {
+ if (Macro)
+ return Macro.get();
+
+ DataExtractor MacinfoData(getMacinfoSection(), isLittleEndian(), 0);
+ Macro.reset(new DWARFDebugMacro());
+ Macro->parse(MacinfoData);
+ return Macro.get();
+}
+
const DWARFLineTable *
-DWARFContext::getLineTableForUnit(DWARFUnit *cu) {
+DWARFContext::getLineTableForUnit(DWARFUnit *U) {
if (!Line)
Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
-
+ const auto *UnitDIE = U->getUnitDIE();
+ if (UnitDIE == nullptr)
+ return nullptr;
unsigned stmtOffset =
- cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset(
- cu, DW_AT_stmt_list, -1U);
+ UnitDIE->getAttributeValueAsSectionOffset(U, DW_AT_stmt_list, -1U);
if (stmtOffset == -1U)
return nullptr; // No line table for this compile unit.
// We have to parse it first.
DataExtractor lineData(getLineSection().Data, isLittleEndian(),
- cu->getAddressByteSize());
+ U->getAddressByteSize());
return Line->getOrParseLineTable(lineData, stmtOffset);
}
if (!TUs.empty())
return;
for (const auto &I : getTypesSections()) {
- TUs.push_back(DWARFUnitSection<DWARFTypeUnit>());
+ TUs.emplace_back();
TUs.back().parse(*this, I.second);
}
}
if (!DWOTUs.empty())
return;
for (const auto &I : getTypesDWOSections()) {
- DWOTUs.push_back(DWARFUnitSection<DWARFTypeUnit>());
+ DWOTUs.emplace_back();
DWOTUs.back().parseDWO(*this, I.second);
}
}
return true;
}
-DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj)
+DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
+ const LoadedObjectInfo *L)
: IsLittleEndian(Obj.isLittleEndian()),
AddressSize(Obj.getBytesInAddress()) {
for (const SectionRef &Section : Obj.sections()) {
if (IsVirtual)
continue;
StringRef data;
- Section.getContents(data);
+
+ section_iterator RelocatedSection = Section.getRelocatedSection();
+ // Try to obtain an already relocated version of this section.
+ // Else use the unrelocated section from the object file. We'll have to
+ // apply relocations ourselves later.
+ if (!L || !L->getLoadedSectionContents(*RelocatedSection,data))
+ Section.getContents(data);
name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
.Case("debug_frame", &DebugFrameSection)
.Case("debug_str", &StringSection)
.Case("debug_ranges", &RangeSection)
+ .Case("debug_macinfo", &MacinfoSection)
.Case("debug_pubnames", &PubNamesSection)
.Case("debug_pubtypes", &PubTypesSection)
.Case("debug_gnu_pubnames", &GnuPubNamesSection)
.Case("apple_namespaces", &AppleNamespacesSection.Data)
.Case("apple_namespac", &AppleNamespacesSection.Data)
.Case("apple_objc", &AppleObjCSection.Data)
+ .Case("debug_cu_index", &CUIndexSection)
+ .Case("debug_tu_index", &TUIndexSection)
// Any more debug info sections go here.
.Default(nullptr);
if (SectionData) {
TypesDWOSections[Section].Data = data;
}
- section_iterator RelocatedSection = Section.getRelocatedSection();
if (RelocatedSection == Obj.section_end())
continue;
StringRef RelSecName;
+ StringRef RelSecData;
RelocatedSection->getName(RelSecName);
+
+ // If the section we're relocating was relocated already by the JIT,
+ // then we used the relocated version above, so we do not need to process
+ // relocations for it now.
+ if (L && L->getLoadedSectionContents(*RelocatedSection,RelSecData))
+ continue;
+
+ // In Mach-o files, the relocations do not need to be applied if
+ // there is no load offset to apply. The value read at the
+ // relocation point already factors in the section address
+ // (actually applying the relocations will produce wrong results
+ // as the section address will be added twice).
+ if (!L && dyn_cast<MachOObjectFile>(&Obj))
+ continue;
+
RelSecName = RelSecName.substr(
RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.
if (Section.relocation_begin() != Section.relocation_end()) {
uint64_t SectionSize = RelocatedSection->getSize();
for (const RelocationRef &Reloc : Section.relocations()) {
- uint64_t Address;
- Reloc.getOffset(Address);
- uint64_t Type;
- Reloc.getType(Type);
+ uint64_t Address = Reloc.getOffset();
+ uint64_t Type = Reloc.getType();
uint64_t SymAddr = 0;
+ uint64_t SectionLoadAddress = 0;
object::symbol_iterator Sym = Reloc.getSymbol();
- if (Sym != Obj.symbol_end())
- Sym->getAddress(SymAddr);
+ object::section_iterator RSec = Obj.section_end();
+
+ // First calculate the address of the symbol or section as it appears
+ // in the objct file
+ if (Sym != Obj.symbol_end()) {
+ ErrorOr<uint64_t> SymAddrOrErr = Sym->getAddress();
+ if (std::error_code EC = SymAddrOrErr.getError()) {
+ errs() << "error: failed to compute symbol address: "
+ << EC.message() << '\n';
+ continue;
+ }
+ SymAddr = *SymAddrOrErr;
+ // Also remember what section this symbol is in for later
+ RSec = *Sym->getSection();
+ } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
+ // MachO also has relocations that point to sections and
+ // scattered relocations.
+ auto RelocInfo = MObj->getRelocation(Reloc.getRawDataRefImpl());
+ if (MObj->isRelocationScattered(RelocInfo)) {
+ // FIXME: it's not clear how to correctly handle scattered
+ // relocations.
+ continue;
+ } else {
+ RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
+ SymAddr = RSec->getAddress();
+ }
+ }
+
+ // If we are given load addresses for the sections, we need to adjust:
+ // SymAddr = (Address of Symbol Or Section in File) -
+ // (Address of Section in File) +
+ // (Load Address of Section)
+ if (L != nullptr && RSec != Obj.section_end()) {
+ // RSec is now either the section being targeted or the section
+ // containing the symbol being targeted. In either case,
+ // we need to perform the same computation.
+ StringRef SecName;
+ RSec->getName(SecName);
+// llvm::dbgs() << "Name: '" << SecName
+// << "', RSec: " << RSec->getRawDataRefImpl()
+// << ", Section: " << Section.getRawDataRefImpl() << "\n";
+ SectionLoadAddress = L->getSectionLoadAddress(*RSec);
+ if (SectionLoadAddress != 0)
+ SymAddr += SectionLoadAddress - RSec->getAddress();
+ }
object::RelocVisitor V(Obj);
object::RelocToApply R(V.visit(Type, Reloc, SymAddr));
if (V.error()) {
SmallString<32> Name;
- std::error_code ec(Reloc.getTypeName(Name));
- if (ec) {
- errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n";
- }
+ Reloc.getTypeName(Name);
errs() << "error: failed to compute relocation: "
<< Name << "\n";
continue;