summaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF/DWARFContext.cpp')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFContext.cpp154
1 files changed, 115 insertions, 39 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index c06d85d50609..aaa6d5250f23 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -288,6 +288,7 @@ static void dumpRnglistsSection(
static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
DWARFDataExtractor Data,
const MCRegisterInfo *MRI,
+ const DWARFObject &Obj,
Optional<uint64_t> DumpOffset) {
uint64_t Offset = 0;
@@ -299,13 +300,21 @@ static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
}
Header.dump(OS, DumpOpts);
- DataExtractor LocData(Data.getData(),
- Data.isLittleEndian(), Header.getAddrSize());
- DWARFDebugLoclists Loclists;
uint64_t EndOffset = Header.length() + Header.getHeaderOffset();
- Loclists.parse(LocData, Offset, EndOffset, Header.getVersion());
- Loclists.dump(OS, 0, MRI, DumpOpts, DumpOffset);
+ Data.setAddressSize(Header.getAddrSize());
+ DWARFDebugLoclists Loc(Data, Header.getVersion());
+ if (DumpOffset) {
+ if (DumpOffset >= Offset && DumpOffset < EndOffset) {
+ Offset = *DumpOffset;
+ Loc.dumpLocationList(&Offset, OS, /*BaseAddr=*/None, MRI, Obj, nullptr,
+ DumpOpts, /*Indent=*/0);
+ OS << "\n";
+ return;
+ }
+ } else {
+ Loc.dumpRange(Offset, EndOffset - Offset, OS, MRI, Obj, DumpOpts);
+ }
Offset = EndOffset;
}
}
@@ -380,21 +389,45 @@ void DWARFContext::dump(
dumpDebugType(".debug_types.dwo", dwo_types_section_units());
}
+ DIDumpOptions LLDumpOpts = DumpOpts;
+ if (LLDumpOpts.Verbose)
+ LLDumpOpts.DisplayRawContents = true;
+
if (const auto *Off = shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc,
DObj->getLocSection().Data)) {
- getDebugLoc()->dump(OS, getRegisterInfo(), DumpOpts, *Off);
+ getDebugLoc()->dump(OS, getRegisterInfo(), *DObj, LLDumpOpts, *Off);
}
if (const auto *Off =
shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
DObj->getLoclistsSection().Data)) {
DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
0);
- dumpLoclistsSection(OS, DumpOpts, Data, getRegisterInfo(), *Off);
+ dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off);
+ }
+ if (const auto *Off =
+ shouldDump(ExplicitDWO, ".debug_loclists.dwo", DIDT_ID_DebugLoclists,
+ DObj->getLoclistsDWOSection().Data)) {
+ DWARFDataExtractor Data(*DObj, DObj->getLoclistsDWOSection(),
+ isLittleEndian(), 0);
+ dumpLoclistsSection(OS, LLDumpOpts, Data, getRegisterInfo(), *DObj, *Off);
}
+
if (const auto *Off =
shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
DObj->getLocDWOSection().Data)) {
- getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), DumpOpts, *Off);
+ DWARFDataExtractor Data(*DObj, DObj->getLocDWOSection(), isLittleEndian(),
+ 4);
+ DWARFDebugLoclists Loc(Data, /*Version=*/4);
+ if (*Off) {
+ uint64_t Offset = **Off;
+ Loc.dumpLocationList(&Offset, OS,
+ /*BaseAddr=*/None, getRegisterInfo(), *DObj, nullptr,
+ LLDumpOpts, /*Indent=*/0);
+ OS << "\n";
+ } else {
+ Loc.dumpRange(0, Data.getData().size(), OS, getRegisterInfo(), *DObj,
+ LLDumpOpts);
+ }
}
if (const auto *Off = shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
@@ -409,6 +442,9 @@ void DWARFContext::dump(
if (Explicit || !getDebugMacro()->empty()) {
OS << "\n.debug_macinfo contents:\n";
getDebugMacro()->dump(OS);
+ } else if (ExplicitDWO || !getDebugMacroDWO()->empty()) {
+ OS << "\n.debug_macinfo.dwo contents:\n";
+ getDebugMacroDWO()->dump(OS);
}
}
@@ -715,32 +751,16 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() {
if (Loc)
return Loc.get();
- Loc.reset(new DWARFDebugLoc);
// Assume all units have the same address byte size.
- if (getNumCompileUnits()) {
- DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(),
- getUnitAtIndex(0)->getAddressByteSize());
- Loc->parse(LocData);
- }
+ auto LocData =
+ getNumCompileUnits()
+ ? DWARFDataExtractor(*DObj, DObj->getLocSection(), isLittleEndian(),
+ getUnitAtIndex(0)->getAddressByteSize())
+ : DWARFDataExtractor("", isLittleEndian(), 0);
+ Loc.reset(new DWARFDebugLoc(std::move(LocData)));
return Loc.get();
}
-const DWARFDebugLoclists *DWARFContext::getDebugLocDWO() {
- if (LocDWO)
- return LocDWO.get();
-
- LocDWO.reset(new DWARFDebugLoclists());
- // Assume all compile units have the same address byte size.
- // FIXME: We don't need AddressSize for split DWARF since relocatable
- // addresses cannot appear there. At the moment DWARFExpression requires it.
- DataExtractor LocData(DObj->getLocDWOSection().Data, isLittleEndian(), 4);
- // Use version 4. DWO does not support the DWARF v5 .debug_loclists yet and
- // that means we are parsing the new style .debug_loc (pre-standatized version
- // of the .debug_loclists).
- LocDWO->parse(LocData, 0, LocData.getData().size(), 4 /* Version */);
- return LocDWO.get();
-}
-
const DWARFDebugAranges *DWARFContext::getDebugAranges() {
if (Aranges)
return Aranges.get();
@@ -781,6 +801,17 @@ const DWARFDebugFrame *DWARFContext::getEHFrame() {
return DebugFrame.get();
}
+const DWARFDebugMacro *DWARFContext::getDebugMacroDWO() {
+ if (MacroDWO)
+ return MacroDWO.get();
+
+ DataExtractor MacinfoDWOData(DObj->getMacinfoDWOSection(), isLittleEndian(),
+ 0);
+ MacroDWO.reset(new DWARFDebugMacro());
+ MacroDWO->parse(MacinfoDWOData);
+ return MacroDWO.get();
+}
+
const DWARFDebugMacro *DWARFContext::getDebugMacro() {
if (Macro)
return Macro.get();
@@ -843,7 +874,7 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) {
}
Expected<const DWARFDebugLine::LineTable *> DWARFContext::getLineTableForUnit(
- DWARFUnit *U, std::function<void(Error)> RecoverableErrorCallback) {
+ DWARFUnit *U, function_ref<void(Error)> RecoverableErrorCallback) {
if (!Line)
Line.reset(new DWARFDebugLine);
@@ -1027,19 +1058,56 @@ static Optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) {
return Optional<uint64_t>();
}
+static Optional<int64_t>
+getExpressionFrameOffset(ArrayRef<uint8_t> Expr,
+ Optional<unsigned> FrameBaseReg) {
+ if (!Expr.empty() &&
+ (Expr[0] == DW_OP_fbreg ||
+ (FrameBaseReg && Expr[0] == DW_OP_breg0 + *FrameBaseReg))) {
+ unsigned Count;
+ int64_t Offset = decodeSLEB128(Expr.data() + 1, &Count, Expr.end());
+ // A single DW_OP_fbreg or DW_OP_breg.
+ if (Expr.size() == Count + 1)
+ return Offset;
+ // Same + DW_OP_deref (Fortran arrays look like this).
+ if (Expr.size() == Count + 2 && Expr[Count + 1] == DW_OP_deref)
+ return Offset;
+ // Fallthrough. Do not accept ex. (DW_OP_breg W29, DW_OP_stack_value)
+ }
+ return None;
+}
+
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 (const char *Name = Subprogram.getSubroutineName(DINameKind::ShortName))
+ Local.FunctionName = Name;
+
+ Optional<unsigned> FrameBaseReg;
+ if (auto FrameBase = Subprogram.find(DW_AT_frame_base))
+ if (Optional<ArrayRef<uint8_t>> Expr = FrameBase->getAsBlock())
+ if (!Expr->empty() && (*Expr)[0] >= DW_OP_reg0 &&
+ (*Expr)[0] <= DW_OP_reg31) {
+ FrameBaseReg = (*Expr)[0] - DW_OP_reg0;
+ }
+
+ if (Expected<std::vector<DWARFLocationExpression>> Loc =
+ Die.getLocations(DW_AT_location)) {
+ for (const auto &Entry : *Loc) {
+ if (Optional<int64_t> FrameOffset =
+ getExpressionFrameOffset(Entry.Expr, FrameBaseReg)) {
+ Local.FrameOffset = *FrameOffset;
+ break;
+ }
+ }
+ } else {
+ // FIXME: missing DW_AT_location is OK here, but other errors should be
+ // reported to the user.
+ consumeError(Loc.takeError());
+ }
+
if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
@@ -1377,6 +1445,7 @@ class DWARFObjInMemory final : public DWARFObject {
DWARFSectionMap LocSection;
DWARFSectionMap LoclistsSection;
+ DWARFSectionMap LoclistsDWOSection;
DWARFSectionMap LineSection;
DWARFSectionMap RangesSection;
DWARFSectionMap RnglistsSection;
@@ -1403,6 +1472,7 @@ class DWARFObjInMemory final : public DWARFObject {
return StringSwitch<DWARFSectionMap *>(Name)
.Case("debug_loc", &LocSection)
.Case("debug_loclists", &LoclistsSection)
+ .Case("debug_loclists.dwo", &LoclistsDWOSection)
.Case("debug_line", &LineSection)
.Case("debug_frame", &FrameSection)
.Case("eh_frame", &EHFrameSection)
@@ -1431,6 +1501,7 @@ class DWARFObjInMemory final : public DWARFObject {
StringRef ArangesSection;
StringRef StrSection;
StringRef MacinfoSection;
+ StringRef MacinfoDWOSection;
StringRef AbbrevDWOSection;
StringRef StrDWOSection;
StringRef CUIndexSection;
@@ -1450,6 +1521,7 @@ class DWARFObjInMemory final : public DWARFObject {
.Case("debug_aranges", &ArangesSection)
.Case("debug_str", &StrSection)
.Case("debug_macinfo", &MacinfoSection)
+ .Case("debug_macinfo.dwo", &MacinfoDWOSection)
.Case("debug_abbrev.dwo", &AbbrevDWOSection)
.Case("debug_str.dwo", &StrDWOSection)
.Case("debug_cu_index", &CUIndexSection)
@@ -1733,6 +1805,9 @@ public:
const DWARFSection &getRnglistsDWOSection() const override {
return RnglistsDWOSection;
}
+ const DWARFSection &getLoclistsDWOSection() const override {
+ return LoclistsDWOSection;
+ }
const DWARFSection &getAddrSection() const override { return AddrSection; }
StringRef getCUIndexSection() const override { return CUIndexSection; }
StringRef getGdbIndexSection() const override { return GdbIndexSection; }
@@ -1773,6 +1848,7 @@ public:
return RnglistsSection;
}
StringRef getMacinfoSection() const override { return MacinfoSection; }
+ StringRef getMacinfoDWOSection() const override { return MacinfoDWOSection; }
const DWARFSection &getPubnamesSection() const override { return PubnamesSection; }
const DWARFSection &getPubtypesSection() const override { return PubtypesSection; }
const DWARFSection &getGnuPubnamesSection() const override {