aboutsummaryrefslogtreecommitdiff
path: root/lib/DebugInfo/DWARF/DWARFContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo/DWARF/DWARFContext.cpp')
-rw-r--r--lib/DebugInfo/DWARF/DWARFContext.cpp296
1 files changed, 176 insertions, 120 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp
index 77f6f65ee131..cbce2dc89deb 100644
--- a/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -1,4 +1,4 @@
-//===-- DWARFContext.cpp --------------------------------------------------===//
+//===- DWARFContext.cpp ---------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,23 +7,45 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
#include "llvm/Object/Decompressor.h"
#include "llvm/Object/MachO.h"
+#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/RelocVisitor.h"
-#include "llvm/Support/Compression.h"
-#include "llvm/Support/Dwarf.h"
-#include "llvm/Support/ELF.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/Path.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
using namespace llvm;
using namespace dwarf;
using namespace object;
@@ -128,8 +150,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
auto CUDIE = CU->getUnitDIE();
if (!CUDIE)
continue;
- if (auto StmtOffset =
- CUDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list)) {
+ if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) {
DataExtractor lineData(getLineSection().Data, isLittleEndian(),
savedAddressByteSize);
DWARFDebugLine::LineTable LineTable;
@@ -387,7 +408,7 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) {
if (!UnitDIE)
return nullptr;
- auto Offset = UnitDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list);
+ auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
if (!Offset)
return nullptr; // No line table for this compile unit.
@@ -440,23 +461,32 @@ DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
return getCompileUnitForOffset(CUOffset);
}
-static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address,
- FunctionNameKind Kind,
- std::string &FunctionName) {
- if (Kind == FunctionNameKind::None)
- return false;
+static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
+ uint64_t Address,
+ FunctionNameKind Kind,
+ std::string &FunctionName,
+ uint32_t &StartLine) {
// 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.SmallVectorImpl<DWARFDie> &InlinedChain
+ // name of the topmost function in it.
SmallVector<DWARFDie, 4> InlinedChain;
CU->getInlinedChainForAddress(Address, InlinedChain);
- if (InlinedChain.size() == 0)
+ if (InlinedChain.empty())
return false;
- if (const char *Name = InlinedChain[0].getSubroutineName(Kind)) {
+
+ const DWARFDie &DIE = InlinedChain[0];
+ bool FoundResult = false;
+ const char *Name = nullptr;
+ if (Kind != FunctionNameKind::None && (Name = DIE.getSubroutineName(Kind))) {
FunctionName = Name;
- return true;
+ FoundResult = true;
+ }
+ if (auto DeclLineResult = DIE.getDeclLine()) {
+ StartLine = DeclLineResult;
+ FoundResult = true;
}
- return false;
+
+ return FoundResult;
}
DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
@@ -466,7 +496,9 @@ DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
if (!CU)
return Result;
- getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName);
+ getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind,
+ Result.FunctionName,
+ Result.StartLine);
if (Spec.FLIKind != FileLineInfoKind::None) {
if (const DWARFLineTable *LineTable = getLineTableForUnit(CU))
LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
@@ -484,13 +516,16 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
return Lines;
std::string FunctionName = "<invalid>";
- getFunctionNameForAddress(CU, Address, Spec.FNKind, FunctionName);
+ uint32_t StartLine = 0;
+ getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, FunctionName,
+ StartLine);
// If the Specifier says we don't need FileLineInfo, just
// return the top-most function at the starting address.
if (Spec.FLIKind == FileLineInfoKind::None) {
DILineInfo Result;
Result.FunctionName = FunctionName;
+ Result.StartLine = StartLine;
Lines.push_back(std::make_pair(Address, Result));
return Lines;
}
@@ -511,6 +546,7 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
Result.FunctionName = FunctionName;
Result.Line = Row.Line;
Result.Column = Row.Column;
+ Result.StartLine = StartLine;
Lines.push_back(std::make_pair(Row.Address, Result));
}
@@ -550,6 +586,8 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
// Get function name if necessary.
if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind))
Frame.FunctionName = Name;
+ if (auto DeclLineResult = FunctionDIE.getDeclLine())
+ Frame.StartLine = DeclLineResult;
if (Spec.FLIKind != FileLineInfoKind::None) {
if (i == 0) {
// For the topmost frame, initialize the line table of this
@@ -578,6 +616,66 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
return InliningInfo;
}
+static Error createError(const Twine &Reason, llvm::Error E) {
+ return make_error<StringError>(Reason + toString(std::move(E)),
+ inconvertibleErrorCode());
+}
+
+/// Returns the address of symbol relocation used against. Used for futher
+/// relocations computation. Symbol's section load address is taken in account if
+/// LoadedObjectInfo interface is provided.
+static Expected<uint64_t> getSymbolAddress(const object::ObjectFile &Obj,
+ const RelocationRef &Reloc,
+ const LoadedObjectInfo *L) {
+ uint64_t Ret = 0;
+ object::section_iterator RSec = Obj.section_end();
+ object::symbol_iterator Sym = Reloc.getSymbol();
+
+ // First calculate the address of the symbol or section as it appears
+ // in the object file
+ if (Sym != Obj.symbol_end()) {
+ Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
+ if (!SymAddrOrErr)
+ return createError("error: failed to compute symbol address: ",
+ SymAddrOrErr.takeError());
+
+ // Also remember what section this symbol is in for later
+ auto SectOrErr = Sym->getSection();
+ if (!SectOrErr)
+ return createError("error: failed to get symbol section: ",
+ SectOrErr.takeError());
+
+ RSec = *SectOrErr;
+ Ret = *SymAddrOrErr;
+ } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
+ RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
+ Ret = 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)
+ // 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.
+ if (L && RSec != Obj.section_end())
+ if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))
+ Ret += SectionLoadAddress - RSec->getAddress();
+ return Ret;
+}
+
+static bool isRelocScattered(const object::ObjectFile &Obj,
+ const RelocationRef &Reloc) {
+ const MachOObjectFile *MachObj = dyn_cast<MachOObjectFile>(&Obj);
+ if (!MachObj)
+ return false;
+ // MachO also has relocations that point to sections and
+ // scattered relocations.
+ auto RelocInfo = MachObj->getRelocation(Reloc.getRawDataRefImpl());
+ return MachObj->isRelocationScattered(RelocInfo);
+}
+
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
const LoadedObjectInfo *L)
: IsLittleEndian(Obj.isLittleEndian()),
@@ -618,40 +716,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
name = name.substr(
name.find_first_not_of("._z")); // Skip ".", "z" and "_" prefixes.
- StringRef *SectionData =
- StringSwitch<StringRef *>(name)
- .Case("debug_info", &InfoSection.Data)
- .Case("debug_abbrev", &AbbrevSection)
- .Case("debug_loc", &LocSection.Data)
- .Case("debug_line", &LineSection.Data)
- .Case("debug_aranges", &ARangeSection)
- .Case("debug_frame", &DebugFrameSection)
- .Case("eh_frame", &EHFrameSection)
- .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("debug_gnu_pubtypes", &GnuPubTypesSection)
- .Case("debug_info.dwo", &InfoDWOSection.Data)
- .Case("debug_abbrev.dwo", &AbbrevDWOSection)
- .Case("debug_loc.dwo", &LocDWOSection.Data)
- .Case("debug_line.dwo", &LineDWOSection.Data)
- .Case("debug_str.dwo", &StringDWOSection)
- .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
- .Case("debug_addr", &AddrSection)
- .Case("apple_names", &AppleNamesSection.Data)
- .Case("apple_types", &AppleTypesSection.Data)
- .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)
- .Case("gdb_index", &GdbIndexSection)
- // Any more debug info sections go here.
- .Default(nullptr);
- if (SectionData) {
+ if (StringRef *SectionData = MapSectionToMember(name)) {
*SectionData = data;
if (name == "debug_ranges") {
// FIXME: Use the other dwo range section when we emit it.
@@ -716,73 +781,19 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
if (Section.relocation_begin() != Section.relocation_end()) {
uint64_t SectionSize = RelocatedSection->getSize();
for (const RelocationRef &Reloc : Section.relocations()) {
- uint64_t Address = Reloc.getOffset();
- uint64_t Type = Reloc.getType();
- uint64_t SymAddr = 0;
- uint64_t SectionLoadAddress = 0;
- object::symbol_iterator Sym = Reloc.getSymbol();
- 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()) {
- Expected<uint64_t> SymAddrOrErr = Sym->getAddress();
- if (!SymAddrOrErr) {
- std::string Buf;
- raw_string_ostream OS(Buf);
- logAllUnhandledErrors(SymAddrOrErr.takeError(), OS, "");
- OS.flush();
- errs() << "error: failed to compute symbol address: "
- << Buf << '\n';
- continue;
- }
- SymAddr = *SymAddrOrErr;
- // Also remember what section this symbol is in for later
- auto SectOrErr = Sym->getSection();
- if (!SectOrErr) {
- std::string Buf;
- raw_string_ostream OS(Buf);
- logAllUnhandledErrors(SectOrErr.takeError(), OS, "");
- OS.flush();
- errs() << "error: failed to get symbol section: "
- << Buf << '\n';
- continue;
- }
- RSec = *SectOrErr;
- } 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();
- }
- }
+ // FIXME: it's not clear how to correctly handle scattered
+ // relocations.
+ if (isRelocScattered(Obj, Reloc))
+ continue;
- // 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();
+ Expected<uint64_t> SymAddrOrErr = getSymbolAddress(Obj, Reloc, L);
+ if (!SymAddrOrErr) {
+ errs() << toString(SymAddrOrErr.takeError()) << '\n';
+ continue;
}
object::RelocVisitor V(Obj);
- object::RelocToApply R(V.visit(Type, Reloc, SymAddr));
+ object::RelocToApply R(V.visit(Reloc.getType(), Reloc, *SymAddrOrErr));
if (V.error()) {
SmallString<32> Name;
Reloc.getTypeName(Name);
@@ -790,7 +801,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
<< Name << "\n";
continue;
}
-
+ uint64_t Address = Reloc.getOffset();
if (Address + R.Width > SectionSize) {
errs() << "error: " << R.Width << "-byte relocation starting "
<< Address << " bytes into section " << name << " which is "
@@ -812,4 +823,49 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
}
}
-void DWARFContextInMemory::anchor() { }
+DWARFContextInMemory::DWARFContextInMemory(
+ const StringMap<std::unique_ptr<MemoryBuffer>> &Sections, uint8_t AddrSize,
+ bool isLittleEndian)
+ : IsLittleEndian(isLittleEndian), AddressSize(AddrSize) {
+ for (const auto &SecIt : Sections) {
+ if (StringRef *SectionData = MapSectionToMember(SecIt.first()))
+ *SectionData = SecIt.second->getBuffer();
+ }
+}
+
+StringRef *DWARFContextInMemory::MapSectionToMember(StringRef Name) {
+ return StringSwitch<StringRef *>(Name)
+ .Case("debug_info", &InfoSection.Data)
+ .Case("debug_abbrev", &AbbrevSection)
+ .Case("debug_loc", &LocSection.Data)
+ .Case("debug_line", &LineSection.Data)
+ .Case("debug_aranges", &ARangeSection)
+ .Case("debug_frame", &DebugFrameSection)
+ .Case("eh_frame", &EHFrameSection)
+ .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("debug_gnu_pubtypes", &GnuPubTypesSection)
+ .Case("debug_info.dwo", &InfoDWOSection.Data)
+ .Case("debug_abbrev.dwo", &AbbrevDWOSection)
+ .Case("debug_loc.dwo", &LocDWOSection.Data)
+ .Case("debug_line.dwo", &LineDWOSection.Data)
+ .Case("debug_str.dwo", &StringDWOSection)
+ .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
+ .Case("debug_addr", &AddrSection)
+ .Case("apple_names", &AppleNamesSection.Data)
+ .Case("apple_types", &AppleTypesSection.Data)
+ .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)
+ .Case("gdb_index", &GdbIndexSection)
+ // Any more debug info sections go here.
+ .Default(nullptr);
+}
+
+void DWARFContextInMemory::anchor() {}