summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/DebugInfo/DIContext.h1
-rw-r--r--lib/DebugInfo/CMakeLists.txt1
-rw-r--r--lib/DebugInfo/DWARFContext.cpp19
-rw-r--r--lib/DebugInfo/DWARFContext.h11
-rw-r--r--lib/DebugInfo/DWARFDebugLoc.cpp74
-rw-r--r--lib/DebugInfo/DWARFDebugLoc.h60
-rw-r--r--lib/DebugInfo/DWARFFormValue.cpp6
-rw-r--r--test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp13
-rw-r--r--test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.obin0 -> 2604 bytes
-rw-r--r--test/DebugInfo/dwarfdump-debug-loc-simple.test26
-rw-r--r--tools/llvm-dwarfdump/llvm-dwarfdump.cpp1
11 files changed, 211 insertions, 1 deletions
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
index 8fcd9e0b82..bdd8dce08d 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DIContext.h
@@ -105,6 +105,7 @@ enum DIDumpType {
DIDT_Info,
DIDT_InfoDwo,
DIDT_Line,
+ DIDT_Loc,
DIDT_Ranges,
DIDT_Pubnames,
DIDT_Str,
diff --git a/lib/DebugInfo/CMakeLists.txt b/lib/DebugInfo/CMakeLists.txt
index e97455abac..4a6221d454 100644
--- a/lib/DebugInfo/CMakeLists.txt
+++ b/lib/DebugInfo/CMakeLists.txt
@@ -9,6 +9,7 @@ add_llvm_library(LLVMDebugInfo
DWARFDebugFrame.cpp
DWARFDebugInfoEntry.cpp
DWARFDebugLine.cpp
+ DWARFDebugLoc.cpp
DWARFDebugRangeList.cpp
DWARFFormValue.cpp
)
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
index aaae952da5..6ecd0a75a1 100644
--- a/lib/DebugInfo/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARFContext.cpp
@@ -35,6 +35,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
getCompileUnitAtIndex(i)->dump(OS);
}
+ if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
+ OS << ".debug_loc contents:\n";
+ getDebugLoc()->dump(OS);
+ }
+
if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
OS << "\n.debug_frame contents:\n";
getDebugFrame()->dump(OS);
@@ -171,6 +176,18 @@ const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
return AbbrevDWO.get();
}
+const DWARFDebugLoc *DWARFContext::getDebugLoc() {
+ if (Loc)
+ return Loc.get();
+
+ DataExtractor LocData(getLocSection(), isLittleEndian(), 0);
+ Loc.reset(new DWARFDebugLoc(locRelocMap()));
+ // 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();
@@ -542,6 +559,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
StringRef *Section = StringSwitch<StringRef*>(name)
.Case("debug_info", &InfoSection)
.Case("debug_abbrev", &AbbrevSection)
+ .Case("debug_loc", &LocSection)
.Case("debug_line", &LineSection)
.Case("debug_aranges", &ARangeSection)
.Case("debug_frame", &DebugFrameSection)
@@ -576,6 +594,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
// Record relocations for the debug_info and debug_line sections.
RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
.Case("debug_info", &InfoRelocMap)
+ .Case("debug_loc", &LocRelocMap)
.Case("debug_info.dwo", &InfoDWORelocMap)
.Case("debug_line", &LineRelocMap)
.Default(0);
diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h
index 78c18e6168..af9965fd1d 100644
--- a/lib/DebugInfo/DWARFContext.h
+++ b/lib/DebugInfo/DWARFContext.h
@@ -14,6 +14,7 @@
#include "DWARFDebugAranges.h"
#include "DWARFDebugFrame.h"
#include "DWARFDebugLine.h"
+#include "DWARFDebugLoc.h"
#include "DWARFDebugRangeList.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallVector.h"
@@ -28,6 +29,7 @@ namespace llvm {
class DWARFContext : public DIContext {
SmallVector<DWARFCompileUnit, 1> CUs;
OwningPtr<DWARFDebugAbbrev> Abbrev;
+ OwningPtr<DWARFDebugLoc> Loc;
OwningPtr<DWARFDebugAranges> Aranges;
OwningPtr<DWARFDebugLine> Line;
OwningPtr<DWARFDebugFrame> DebugFrame;
@@ -80,6 +82,9 @@ public:
/// Get a pointer to the parsed DebugAbbrev object.
const DWARFDebugAbbrev *getDebugAbbrev();
+ /// Get a pointer to the parsed DebugLoc object.
+ const DWARFDebugLoc *getDebugLoc();
+
/// Get a pointer to the parsed dwo abbreviations object.
const DWARFDebugAbbrev *getDebugAbbrevDWO();
@@ -104,8 +109,10 @@ public:
virtual uint8_t getAddressSize() const = 0;
virtual const RelocAddrMap &infoRelocMap() const = 0;
virtual const RelocAddrMap &lineRelocMap() const = 0;
+ virtual const RelocAddrMap &locRelocMap() const = 0;
virtual StringRef getInfoSection() = 0;
virtual StringRef getAbbrevSection() = 0;
+ virtual StringRef getLocSection() = 0;
virtual StringRef getARangeSection() = 0;
virtual StringRef getDebugFrameSection() = 0;
virtual StringRef getLineSection() = 0;
@@ -142,9 +149,11 @@ class DWARFContextInMemory : public DWARFContext {
bool IsLittleEndian;
uint8_t AddressSize;
RelocAddrMap InfoRelocMap;
+ RelocAddrMap LocRelocMap;
RelocAddrMap LineRelocMap;
StringRef InfoSection;
StringRef AbbrevSection;
+ StringRef LocSection;
StringRef ARangeSection;
StringRef DebugFrameSection;
StringRef LineSection;
@@ -169,9 +178,11 @@ public:
virtual bool isLittleEndian() const { return IsLittleEndian; }
virtual uint8_t getAddressSize() const { return AddressSize; }
virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; }
+ virtual const RelocAddrMap &locRelocMap() const { return LocRelocMap; }
virtual const RelocAddrMap &lineRelocMap() const { return LineRelocMap; }
virtual StringRef getInfoSection() { return InfoSection; }
virtual StringRef getAbbrevSection() { return AbbrevSection; }
+ virtual StringRef getLocSection() { return LocSection; }
virtual StringRef getARangeSection() { return ARangeSection; }
virtual StringRef getDebugFrameSection() { return DebugFrameSection; }
virtual StringRef getLineSection() { return LineSection; }
diff --git a/lib/DebugInfo/DWARFDebugLoc.cpp b/lib/DebugInfo/DWARFDebugLoc.cpp
new file mode 100644
index 0000000000..46de489204
--- /dev/null
+++ b/lib/DebugInfo/DWARFDebugLoc.cpp
@@ -0,0 +1,74 @@
+//===-- DWARFDebugLoc.cpp -------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugLoc.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void DWARFDebugLoc::dump(raw_ostream &OS) const {
+ for (LocationLists::const_iterator I = Locations.begin(), E = Locations.end(); I != E; ++I) {
+ OS << format("0x%8.8x: ", I->Offset);
+ const unsigned Indent = 12;
+ for (SmallVectorImpl<Entry>::const_iterator I2 = I->Entries.begin(), E2 = I->Entries.end(); I2 != E2; ++I2) {
+ if (I2 != I->Entries.begin())
+ OS.indent(Indent);
+ OS << "Begining address offset: " << format("0x%016" PRIx64, I2->Begin)
+ << '\n';
+ OS.indent(Indent) << " Ending address offset: "
+ << format("0x%016" PRIx64, I2->End) << '\n';
+ OS.indent(Indent) << " Location description: ";
+ for (SmallVectorImpl<unsigned char>::const_iterator I3 = I2->Loc.begin(), E3 = I2->Loc.end(); I3 != E3; ++I3) {
+ OS << format("%2.2x ", *I3);
+ }
+ OS << "\n\n";
+ }
+ }
+}
+
+void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) {
+ uint32_t Offset = 0;
+ while (data.isValidOffset(Offset)) {
+ Locations.resize(Locations.size() + 1);
+ LocationList &Loc = Locations.back();
+ Loc.Offset = Offset;
+ // 2.6.2 Location Lists
+ // A location list entry consists of:
+ while (true) {
+ Entry E;
+ RelocAddrMap::const_iterator AI = RelocMap.find(Offset);
+ // 1. A beginning address offset. ...
+ E.Begin = data.getUnsigned(&Offset, AddressSize);
+ if (AI != RelocMap.end())
+ E.Begin += AI->second.second;
+
+ AI = RelocMap.find(Offset);
+ // 2. An ending address offset. ...
+ E.End = data.getUnsigned(&Offset, AddressSize);
+ if (AI != RelocMap.end())
+ E.End += AI->second.second;
+
+ // The end of any given location list is marked by an end of list entry,
+ // which consists of a 0 for the beginning address offset and a 0 for the
+ // ending address offset.
+ if (E.Begin == 0 && E.End == 0)
+ break;
+
+ unsigned Bytes = data.getU16(&Offset);
+ // A single location description describing the location of the object...
+ StringRef str = data.getData().substr(Offset, Bytes);
+ Offset += Bytes;
+ E.Loc.reserve(str.size());
+ std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
+ Loc.Entries.push_back(llvm_move(E));
+ }
+ }
+}
diff --git a/lib/DebugInfo/DWARFDebugLoc.h b/lib/DebugInfo/DWARFDebugLoc.h
new file mode 100644
index 0000000000..d31aaaa127
--- /dev/null
+++ b/lib/DebugInfo/DWARFDebugLoc.h
@@ -0,0 +1,60 @@
+//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFDEBUGLOC_H
+#define LLVM_DEBUGINFO_DWARFDEBUGLOC_H
+
+#include "DWARFRelocMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/DataExtractor.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+class DWARFDebugLoc {
+ /// A single location within a location list.
+ struct Entry {
+ /// The beginning address of the instruction range.
+ uint64_t Begin;
+ /// The ending address of the instruction range.
+ uint64_t End;
+ /// The location of the variable within the specified range.
+ SmallVector<unsigned char, 4> Loc;
+ };
+
+ /// A list of locations that contain one variable.
+ struct LocationList {
+ /// The beginning offset where this location list is stored in the debug_loc
+ /// section.
+ unsigned Offset;
+ /// All the locations in which the variable is stored.
+ SmallVector<Entry, 2> Entries;
+ };
+
+ typedef SmallVector<LocationList, 4> LocationLists;
+
+ /// A list of all the variables in the debug_loc section, each one describing
+ /// the locations in which the variable is stored.
+ LocationLists Locations;
+
+ /// A map used to resolve binary relocations.
+ const RelocAddrMap &RelocMap;
+
+public:
+ DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {}
+ /// Print the location lists found within the debug_loc section.
+ void dump(raw_ostream &OS) const;
+ /// Parse the debug_loc section accessible via the 'data' parameter using the
+ /// specified address size to interpret the address ranges.
+ void parse(DataExtractor data, unsigned AddressSize);
+};
+}
+
+#endif
diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp
index 5f06f43d81..1a1cf2452c 100644
--- a/lib/DebugInfo/DWARFFormValue.cpp
+++ b/lib/DebugInfo/DWARFFormValue.cpp
@@ -126,9 +126,13 @@ DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
Value.uval = data.getU16(offset_ptr);
break;
case DW_FORM_data4:
- case DW_FORM_ref4:
+ case DW_FORM_ref4: {
+ RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
Value.uval = data.getU32(offset_ptr);
+ if (AI != cu->getRelocMap()->end())
+ Value.uval += AI->second.second;
break;
+ }
case DW_FORM_data8:
case DW_FORM_ref8:
Value.uval = data.getU64(offset_ptr);
diff --git a/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp b/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp
new file mode 100644
index 0000000000..04a0b20cc2
--- /dev/null
+++ b/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.cpp
@@ -0,0 +1,13 @@
+// clang -c -g -o dwarfdump-test-loc-list-32bit.elf.o -m32 dwarfdump-test-loc-list-32bit.elf.cpp
+
+namespace pr14763 {
+struct foo {
+ foo(const foo&);
+};
+
+foo func(bool b, foo f, foo g) {
+ if (b)
+ return f;
+ return g;
+}
+}
diff --git a/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.o b/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.o
new file mode 100644
index 0000000000..25d10b9809
--- /dev/null
+++ b/test/DebugInfo/Inputs/dwarfdump-test-loc-list-32bit.elf.o
Binary files differ
diff --git a/test/DebugInfo/dwarfdump-debug-loc-simple.test b/test/DebugInfo/dwarfdump-debug-loc-simple.test
new file mode 100644
index 0000000000..f38be6dc8f
--- /dev/null
+++ b/test/DebugInfo/dwarfdump-debug-loc-simple.test
@@ -0,0 +1,26 @@
+RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-loc-list-32bit.elf.o | FileCheck %s
+Note: the input file was generated from Inputs/dwarfdump-test-loc-list-32bit.elf.cpp
+
+CHECK: .debug_info
+CHECK: DW_AT_name{{.*}}"f"
+CHECK: DW_AT_location{{.*}}([[F_LOC:0x[0-9a-f]*]])
+CHECK: DW_AT_name{{.*}}"g"
+CHECK: DW_AT_location{{.*}}([[G_LOC:0x[0-9a-f]*]])
+CHECK: .debug_loc contents:
+CHECK-NEXT: [[F_LOC]]: Begining address offset: 0x0000000000000000
+CHECK-NEXT: Ending address offset: 0x0000000000000023
+this is actually the wrong location due to PR14763, but that doesn't matter for
+the purposes of testing dwarfdump
+CHECK-NEXT: Location description: 51
+CHECK-NEXT: {{^$}}
+CHECK-NEXT: Begining address offset: 0x0000000000000023
+CHECK-NEXT: Ending address offset: 0x000000000000005d
+CHECK-NEXT: Location description: 75 70
+CHECK-NEXT: {{^$}}
+CHECK-NEXT: [[G_LOC]]: Begining address offset: 0x0000000000000000
+CHECK-NEXT: Ending address offset: 0x0000000000000020
+CHECK-NEXT: Location description: 50
+CHECK-NEXT: {{^$}}
+CHECK-NEXT: Begining address offset: 0x0000000000000020
+CHECK-NEXT: Ending address offset: 0x000000000000005d
+CHECK-NEXT: Location description: 75 74
diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 80948560ca..eef6f797cc 100644
--- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -63,6 +63,7 @@ DumpType("debug-dump", cl::init(DIDT_All),
clEnumValN(DIDT_Info, "info", ".debug_info"),
clEnumValN(DIDT_InfoDwo, "info.dwo", ".debug_info.dwo"),
clEnumValN(DIDT_Line, "line", ".debug_line"),
+ clEnumValN(DIDT_Loc, "loc", ".debug_loc"),
clEnumValN(DIDT_Frames, "frames", ".debug_frame"),
clEnumValN(DIDT_Ranges, "ranges", ".debug_ranges"),
clEnumValN(DIDT_Pubnames, "pubnames", ".debug_pubnames"),