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.cpp250
1 files changed, 203 insertions, 47 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp
index e6620ee3dd1d..5ede9bf59619 100644
--- a/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -1,9 +1,8 @@
//===- DWARFContext.cpp ---------------------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -37,11 +36,12 @@
#include "llvm/Object/Decompressor.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
-#include "llvm/Object/RelocVisitor.h"
+#include "llvm/Object/RelocationResolver.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetRegistry.h"
@@ -102,7 +102,8 @@ static ContributionCollection
collectContributionData(DWARFContext::unit_iterator_range Units) {
ContributionCollection Contributions;
for (const auto &U : Units)
- Contributions.push_back(U->getStringOffsetsTableContribution());
+ if (const auto &C = U->getStringOffsetsTableContribution())
+ Contributions.push_back(C);
// Sort the contributions so that any invalid ones are placed at
// the start of the contributions vector. This way they are reported
// first.
@@ -158,9 +159,9 @@ static void dumpDWARFv5StringOffsetsSection(
// Detect overlapping contributions.
if (Offset > ContributionHeader) {
- OS << "error: overlapping contributions to string offsets table in "
- "section ."
- << SectionName << ".\n";
+ WithColor::error()
+ << "overlapping contributions to string offsets table in section ."
+ << SectionName << ".\n";
return;
}
// Report a gap in the table.
@@ -269,11 +270,11 @@ static void dumpAddrSection(raw_ostream &OS, DWARFDataExtractor &AddrData,
}
// Dump the .debug_rnglists or .debug_rnglists.dwo section (DWARF v5).
-static void
-dumpRnglistsSection(raw_ostream &OS, DWARFDataExtractor &rnglistData,
- llvm::function_ref<Optional<SectionedAddress>(uint32_t)>
- LookupPooledAddress,
- DIDumpOptions DumpOpts) {
+static void dumpRnglistsSection(
+ raw_ostream &OS, DWARFDataExtractor &rnglistData,
+ llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
+ LookupPooledAddress,
+ DIDumpOptions DumpOpts) {
uint32_t Offset = 0;
while (rnglistData.isValidOffset(Offset)) {
llvm::DWARFDebugRnglistTable Rnglists;
@@ -926,6 +927,9 @@ DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) {
DWARFDie DIE = Worklist.back();
Worklist.pop_back();
+ if (!DIE.isValid())
+ continue;
+
if (DIE.getTag() == DW_TAG_lexical_block &&
DIE.addressRangeContainsAddress(Address)) {
Result.BlockDIE = DIE;
@@ -939,6 +943,8 @@ DWARFContext::DIEsForAddress DWARFContext::getDIEsForAddress(uint64_t Address) {
return Result;
}
+/// TODO: change input parameter from "uint64_t Address"
+/// into "SectionedAddress Address"
static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
uint64_t Address,
FunctionNameKind Kind,
@@ -967,36 +973,155 @@ static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
return FoundResult;
}
-DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
+static Optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) {
+ if (auto SizeAttr = Type.find(DW_AT_byte_size))
+ if (Optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant())
+ return Size;
+
+ switch (Type.getTag()) {
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ return PointerSize;
+ case DW_TAG_ptr_to_member_type: {
+ if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type))
+ if (BaseType.getTag() == DW_TAG_subroutine_type)
+ return 2 * PointerSize;
+ return PointerSize;
+ }
+ case DW_TAG_const_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_restrict_type:
+ case DW_TAG_typedef: {
+ if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type))
+ return getTypeSize(BaseType, PointerSize);
+ break;
+ }
+ case DW_TAG_array_type: {
+ DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type);
+ if (!BaseType)
+ return Optional<uint64_t>();
+ Optional<uint64_t> BaseSize = getTypeSize(BaseType, PointerSize);
+ if (!BaseSize)
+ return Optional<uint64_t>();
+ uint64_t Size = *BaseSize;
+ for (DWARFDie Child : Type) {
+ if (Child.getTag() != DW_TAG_subrange_type)
+ continue;
+
+ if (auto ElemCountAttr = Child.find(DW_AT_count))
+ if (Optional<uint64_t> ElemCount =
+ ElemCountAttr->getAsUnsignedConstant())
+ Size *= *ElemCount;
+ if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound))
+ if (Optional<int64_t> UpperBound =
+ UpperBoundAttr->getAsSignedConstant()) {
+ int64_t LowerBound = 0;
+ if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound))
+ LowerBound = LowerBoundAttr->getAsSignedConstant().getValueOr(0);
+ Size *= *UpperBound - LowerBound + 1;
+ }
+ }
+ return Size;
+ }
+ default:
+ break;
+ }
+ return Optional<uint64_t>();
+}
+
+void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
+ DWARFDie Die, std::vector<DILocal> &Result) {
+ if (Die.getTag() == DW_TAG_variable ||
+ Die.getTag() == DW_TAG_formal_parameter) {
+ DILocal Local;
+ if (auto NameAttr = Subprogram.find(DW_AT_name))
+ if (Optional<const char *> Name = NameAttr->getAsCString())
+ Local.FunctionName = *Name;
+ if (auto LocationAttr = Die.find(DW_AT_location))
+ if (Optional<ArrayRef<uint8_t>> Location = LocationAttr->getAsBlock())
+ if (!Location->empty() && (*Location)[0] == DW_OP_fbreg)
+ Local.FrameOffset =
+ decodeSLEB128(Location->data() + 1, nullptr, Location->end());
+ if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
+ Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
+
+ if (auto Origin =
+ Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
+ Die = Origin;
+ if (auto NameAttr = Die.find(DW_AT_name))
+ if (Optional<const char *> Name = NameAttr->getAsCString())
+ Local.Name = *Name;
+ if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
+ Local.Size = getTypeSize(Type, getCUAddrSize());
+ if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
+ if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
+ LT->getFileNameByIndex(
+ DeclFileAttr->getAsUnsignedConstant().getValue(),
+ CU->getCompilationDir(),
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
+ Local.DeclFile);
+ }
+ if (auto DeclLineAttr = Die.find(DW_AT_decl_line))
+ Local.DeclLine = DeclLineAttr->getAsUnsignedConstant().getValue();
+
+ Result.push_back(Local);
+ return;
+ }
+
+ if (Die.getTag() == DW_TAG_inlined_subroutine)
+ if (auto Origin =
+ Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
+ Subprogram = Origin;
+
+ for (auto Child : Die)
+ addLocalsForDie(CU, Subprogram, Child, Result);
+}
+
+std::vector<DILocal>
+DWARFContext::getLocalsForAddress(object::SectionedAddress Address) {
+ std::vector<DILocal> Result;
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
+ if (!CU)
+ return Result;
+
+ DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);
+ if (Subprogram.isValid())
+ addLocalsForDie(CU, Subprogram, Subprogram, Result);
+ return Result;
+}
+
+DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,
DILineInfoSpecifier Spec) {
DILineInfo Result;
- DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
if (!CU)
return Result;
- getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind,
- Result.FunctionName,
- Result.StartLine);
+
+ getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
+ Result.FunctionName, Result.StartLine);
if (Spec.FLIKind != FileLineInfoKind::None) {
- if (const DWARFLineTable *LineTable = getLineTableForUnit(CU))
- LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
- Spec.FLIKind, Result);
+ if (const DWARFLineTable *LineTable = getLineTableForUnit(CU)) {
+ LineTable->getFileLineInfoForAddress(
+ {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
+ Spec.FLIKind, Result);
+ }
}
return Result;
}
-DILineInfoTable
-DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
- DILineInfoSpecifier Spec) {
+DILineInfoTable DWARFContext::getLineInfoForAddressRange(
+ object::SectionedAddress Address, uint64_t Size, DILineInfoSpecifier Spec) {
DILineInfoTable Lines;
- DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
if (!CU)
return Lines;
std::string FunctionName = "<invalid>";
uint32_t StartLine = 0;
- getFunctionNameAndStartLineForAddress(CU, Address, Spec.FNKind, FunctionName,
- StartLine);
+ getFunctionNameAndStartLineForAddress(CU, Address.Address, Spec.FNKind,
+ FunctionName, StartLine);
// If the Specifier says we don't need FileLineInfo, just
// return the top-most function at the starting address.
@@ -1004,7 +1129,7 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
DILineInfo Result;
Result.FunctionName = FunctionName;
Result.StartLine = StartLine;
- Lines.push_back(std::make_pair(Address, Result));
+ Lines.push_back(std::make_pair(Address.Address, Result));
return Lines;
}
@@ -1012,8 +1137,10 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
// Get the index of row we're looking for in the line table.
std::vector<uint32_t> RowVector;
- if (!LineTable->lookupAddressRange(Address, Size, RowVector))
+ if (!LineTable->lookupAddressRange({Address.Address, Address.SectionIndex},
+ Size, RowVector)) {
return Lines;
+ }
for (uint32_t RowIndex : RowVector) {
// Take file number and line/column from the row.
@@ -1025,33 +1152,33 @@ DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
Result.Line = Row.Line;
Result.Column = Row.Column;
Result.StartLine = StartLine;
- Lines.push_back(std::make_pair(Row.Address, Result));
+ Lines.push_back(std::make_pair(Row.Address.Address, Result));
}
return Lines;
}
DIInliningInfo
-DWARFContext::getInliningInfoForAddress(uint64_t Address,
+DWARFContext::getInliningInfoForAddress(object::SectionedAddress Address,
DILineInfoSpecifier Spec) {
DIInliningInfo InliningInfo;
- DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
if (!CU)
return InliningInfo;
const DWARFLineTable *LineTable = nullptr;
SmallVector<DWARFDie, 4> InlinedChain;
- CU->getInlinedChainForAddress(Address, InlinedChain);
+ CU->getInlinedChainForAddress(Address.Address, InlinedChain);
if (InlinedChain.size() == 0) {
// If there is no DIE for address (e.g. it is in unavailable .dwo file),
// try to at least get file/line info from symbol table.
if (Spec.FLIKind != FileLineInfoKind::None) {
DILineInfo Frame;
LineTable = getLineTableForUnit(CU);
- if (LineTable &&
- LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
- Spec.FLIKind, Frame))
+ if (LineTable && LineTable->getFileLineInfoForAddress(
+ {Address.Address, Address.SectionIndex},
+ CU->getCompilationDir(), Spec.FLIKind, Frame))
InliningInfo.addFrame(Frame);
}
return InliningInfo;
@@ -1073,8 +1200,9 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
LineTable = getLineTableForUnit(CU);
// For the topmost routine, get file/line info from line table.
if (LineTable)
- LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
- Spec.FLIKind, Frame);
+ LineTable->getFileLineInfoForAddress(
+ {Address.Address, Address.SectionIndex}, CU->getCompilationDir(),
+ Spec.FLIKind, Frame);
} else {
// Otherwise, use call file, call line and call column from
// previous DIE in inlined chain.
@@ -1402,8 +1530,14 @@ public:
// 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);
+ if (!L || !L->getLoadedSectionContents(*RelocatedSection, Data)) {
+ Expected<StringRef> E = Section.getContents();
+ if (E)
+ Data = *E;
+ else
+ // maybeDecompress below will error.
+ consumeError(E.takeError());
+ }
if (auto Err = maybeDecompress(Section, Name, Data)) {
ErrorPolicy EP = HandleError(createError(
@@ -1495,6 +1629,9 @@ public:
// Symbol to [address, section index] cache mapping.
std::map<SymbolRef, SymInfo> AddrCache;
+ bool (*Supports)(uint64_t);
+ RelocationResolver Resolver;
+ std::tie(Supports, Resolver) = getRelocationResolver(Obj);
for (const RelocationRef &Reloc : Section.relocations()) {
// FIXME: it's not clear how to correctly handle scattered
// relocations.
@@ -1509,9 +1646,31 @@ public:
continue;
}
- object::RelocVisitor V(Obj);
- uint64_t Val = V.visit(Reloc.getType(), Reloc, SymInfoOrErr->Address);
- if (V.error()) {
+ // Check if Resolver can handle this relocation type early so as not to
+ // handle invalid cases in DWARFDataExtractor.
+ //
+ // TODO Don't store Resolver in every RelocAddrEntry.
+ if (Supports && Supports(Reloc.getType())) {
+ auto I = Map->try_emplace(
+ Reloc.getOffset(),
+ RelocAddrEntry{SymInfoOrErr->SectionIndex, Reloc,
+ SymInfoOrErr->Address,
+ Optional<object::RelocationRef>(), 0, Resolver});
+ // If we didn't successfully insert that's because we already had a
+ // relocation for that offset. Store it as a second relocation in the
+ // same RelocAddrEntry instead.
+ if (!I.second) {
+ RelocAddrEntry &entry = I.first->getSecond();
+ if (entry.Reloc2) {
+ ErrorPolicy EP = HandleError(createError(
+ "At most two relocations per offset are supported"));
+ if (EP == ErrorPolicy::Halt)
+ return;
+ }
+ entry.Reloc2 = Reloc;
+ entry.SymbolValue2 = SymInfoOrErr->Address;
+ }
+ } else {
SmallString<32> Type;
Reloc.getTypeName(Type);
ErrorPolicy EP = HandleError(
@@ -1519,10 +1678,7 @@ public:
errorCodeToError(object_error::parse_failed)));
if (EP == ErrorPolicy::Halt)
return;
- continue;
}
- RelocAddrEntry Rel = {SymInfoOrErr->SectionIndex, Val};
- Map->insert({Reloc.getOffset(), Rel});
}
}