summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kaylor <andrew.kaylor@intel.com>2013-01-25 22:50:58 +0000
committerAndrew Kaylor <andrew.kaylor@intel.com>2013-01-25 22:50:58 +0000
commitee7c0d2f931590ccdc53a14b1839e11bb29fc96e (patch)
tree691f74c6f15436cdeacf8fa67089c34071a00460
parentc73b7f702258b844dc2702fd9d79d8a8706460a7 (diff)
downloadllvm-ee7c0d2f931590ccdc53a14b1839e11bb29fc96e.tar.gz
llvm-ee7c0d2f931590ccdc53a14b1839e11bb29fc96e.tar.bz2
llvm-ee7c0d2f931590ccdc53a14b1839e11bb29fc96e.tar.xz
Add support for applying in-memory relocations to the .debug_line section and, in the case of ELF files, using symbol addresses when available for relocations to the .debug_info section. Also extending the llvm-rtdyld tool to add the ability to dump line number information for testing purposes.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173517 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/ExecutionEngine/ObjectImage.h2
-rw-r--r--lib/DebugInfo/DWARFCompileUnit.h2
-rw-r--r--lib/DebugInfo/DWARFContext.cpp18
-rw-r--r--lib/DebugInfo/DWARFContext.h3
-rw-r--r--lib/DebugInfo/DWARFDebugLine.cpp15
-rw-r--r--lib/DebugInfo/DWARFDebugLine.h4
-rw-r--r--lib/DebugInfo/DWARFRelocMap.h21
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h2
-rw-r--r--test/DebugInfo/Inputs/test-inline.obin0 -> 6040 bytes
-rw-r--r--test/DebugInfo/debuglineinfo.test15
-rw-r--r--tools/llvm-rtdyld/CMakeLists.txt2
-rw-r--r--tools/llvm-rtdyld/Makefile2
-rw-r--r--tools/llvm-rtdyld/llvm-rtdyld.cpp62
13 files changed, 137 insertions, 11 deletions
diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h
index d09e4deb1a..9fddca7e33 100644
--- a/include/llvm/ExecutionEngine/ObjectImage.h
+++ b/include/llvm/ExecutionEngine/ObjectImage.h
@@ -50,6 +50,8 @@ public:
virtual StringRef getData() const = 0;
+ virtual object::ObjectFile* getObjectFile() const = 0;
+
// Subclasses can override these methods to provide JIT debugging support
virtual void registerWithDebugger() = 0;
virtual void deregisterWithDebugger() = 0;
diff --git a/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h
index de70b2e2a9..2a74605fcb 100644
--- a/lib/DebugInfo/DWARFCompileUnit.h
+++ b/lib/DebugInfo/DWARFCompileUnit.h
@@ -13,6 +13,7 @@
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugInfoEntry.h"
#include "DWARFDebugRangeList.h"
+#include "DWARFRelocMap.h"
#include <vector>
namespace llvm {
@@ -20,7 +21,6 @@ namespace llvm {
class DWARFDebugAbbrev;
class StringRef;
class raw_ostream;
-typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap;
class DWARFCompileUnit {
const DWARFDebugAbbrev *Abbrev;
diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp
index 39953499ce..66d299bad2 100644
--- a/lib/DebugInfo/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARFContext.cpp
@@ -53,7 +53,7 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
DataExtractor lineData(getLineSection(), isLittleEndian(),
savedAddressByteSize);
DWARFDebugLine::DumpingState state(OS);
- DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
+ DWARFDebugLine::parseStatementTable(lineData, &lineRelocMap(), &stmtOffset, state);
}
}
}
@@ -155,7 +155,7 @@ const DWARFDebugAranges *DWARFContext::getDebugAranges() {
const DWARFLineTable *
DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
if (!Line)
- Line.reset(new DWARFDebugLine());
+ Line.reset(new DWARFDebugLine(&lineRelocMap()));
unsigned stmtOffset =
cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
@@ -422,12 +422,15 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
else
continue;
- // TODO: For now only handle relocations for the debug_info section.
+ // TODO: Add support for relocations in other sections as needed.
+ // Record relocations for the debug_info and debug_line sections.
RelocAddrMap *Map;
if (name == "debug_info")
Map = &InfoRelocMap;
else if (name == "debug_info.dwo")
Map = &InfoDWORelocMap;
+ else if (name == "debug_line")
+ Map = &LineRelocMap;
else
continue;
@@ -441,10 +444,17 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) :
reloc_i->getAddress(Address);
uint64_t Type;
reloc_i->getType(Type);
+ uint64_t SymAddr = 0;
+ // ELF relocations may need the symbol address
+ if (Obj->isELF()) {
+ object::SymbolRef Sym;
+ reloc_i->getSymbol(Sym);
+ Sym.getAddress(SymAddr);
+ }
object::RelocVisitor V(Obj->getFileFormatName());
// The section address is always 0 for debug sections.
- object::RelocToApply R(V.visit(Type, *reloc_i));
+ object::RelocToApply R(V.visit(Type, *reloc_i, 0, SymAddr));
if (V.error()) {
SmallString<32> Name;
error_code ec(reloc_i->getTypeName(Name));
diff --git a/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h
index 8a4a3afec3..d6314b87c3 100644
--- a/lib/DebugInfo/DWARFContext.h
+++ b/lib/DebugInfo/DWARFContext.h
@@ -95,6 +95,7 @@ public:
virtual bool isLittleEndian() const = 0;
virtual const RelocAddrMap &infoRelocMap() const = 0;
+ virtual const RelocAddrMap &lineRelocMap() const = 0;
virtual StringRef getInfoSection() = 0;
virtual StringRef getAbbrevSection() = 0;
virtual StringRef getARangeSection() = 0;
@@ -130,6 +131,7 @@ class DWARFContextInMemory : public DWARFContext {
virtual void anchor();
bool IsLittleEndian;
RelocAddrMap InfoRelocMap;
+ RelocAddrMap LineRelocMap;
StringRef InfoSection;
StringRef AbbrevSection;
StringRef ARangeSection;
@@ -150,6 +152,7 @@ public:
DWARFContextInMemory(object::ObjectFile *);
virtual bool isLittleEndian() const { return IsLittleEndian; }
virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; }
+ virtual const RelocAddrMap &lineRelocMap() const { return LineRelocMap; }
virtual StringRef getInfoSection() { return InfoSection; }
virtual StringRef getAbbrevSection() { return AbbrevSection; }
virtual StringRef getARangeSection() { return ARangeSection; }
diff --git a/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp
index 267364adfa..16ef896ca7 100644
--- a/lib/DebugInfo/DWARFDebugLine.cpp
+++ b/lib/DebugInfo/DWARFDebugLine.cpp
@@ -155,7 +155,7 @@ DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data,
if (pos.second) {
// Parse and cache the line table for at this offset.
State state;
- if (!parseStatementTable(debug_line_data, &offset, state))
+ if (!parseStatementTable(debug_line_data, RelocMap, &offset, state))
return 0;
pos.first->second = state;
}
@@ -219,7 +219,8 @@ DWARFDebugLine::parsePrologue(DataExtractor debug_line_data,
}
bool
-DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
+DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
+ const RelocAddrMap *RMap,
uint32_t *offset_ptr, State &state) {
const uint32_t debug_line_offset = *offset_ptr;
@@ -268,7 +269,15 @@ DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
// relocatable address. All of the other statement program opcodes
// that affect the address register add a delta to it. This instruction
// stores a relocatable value into it instead.
- state.Address = debug_line_data.getAddress(offset_ptr);
+ {
+ // If this address is in our relocation map, apply the relocation.
+ RelocAddrMap::const_iterator AI = RMap->find(*offset_ptr);
+ if (AI != RMap->end()) {
+ const std::pair<uint8_t, int64_t> &R = AI->second;
+ state.Address = debug_line_data.getAddress(offset_ptr) + R.second;
+ } else
+ state.Address = debug_line_data.getAddress(offset_ptr);
+ }
break;
case DW_LNE_define_file:
diff --git a/lib/DebugInfo/DWARFDebugLine.h b/lib/DebugInfo/DWARFDebugLine.h
index 586dd7e878..dbaf91d321 100644
--- a/lib/DebugInfo/DWARFDebugLine.h
+++ b/lib/DebugInfo/DWARFDebugLine.h
@@ -10,6 +10,7 @@
#ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
+#include "DWARFRelocMap.h"
#include "llvm/Support/DataExtractor.h"
#include <map>
#include <string>
@@ -21,6 +22,7 @@ class raw_ostream;
class DWARFDebugLine {
public:
+ DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {}
struct FileNameEntry {
FileNameEntry() : Name(0), DirIdx(0), ModTime(0), Length(0) {}
@@ -227,6 +229,7 @@ public:
Prologue *prologue);
/// Parse a single line table (prologue and all rows).
static bool parseStatementTable(DataExtractor debug_line_data,
+ const RelocAddrMap *RMap,
uint32_t *offset_ptr, State &state);
const LineTable *getLineTable(uint32_t offset) const;
@@ -238,6 +241,7 @@ private:
typedef LineTableMapTy::iterator LineTableIter;
typedef LineTableMapTy::const_iterator LineTableConstIter;
+ const RelocAddrMap *RelocMap;
LineTableMapTy LineTableMap;
};
diff --git a/lib/DebugInfo/DWARFRelocMap.h b/lib/DebugInfo/DWARFRelocMap.h
new file mode 100644
index 0000000000..f53d05cac5
--- /dev/null
+++ b/lib/DebugInfo/DWARFRelocMap.h
@@ -0,0 +1,21 @@
+//===-- DWARFRelocMap.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_DWARFRELOCMAP_H
+#define LLVM_DEBUGINFO_DWARFRELOCMAP_H
+
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+
+typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap;
+
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARFRELOCMAP_H \ No newline at end of file
diff --git a/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h b/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h
index 28b4f0f84a..89350cc5b6 100644
--- a/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h
+++ b/lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h
@@ -58,6 +58,8 @@ public:
virtual StringRef getData() const { return ObjFile->getData(); }
+ virtual object::ObjectFile* getObjectFile() const { return ObjFile; }
+
// Subclasses can override these methods to update the image with loaded
// addresses for sections and common symbols
virtual void updateSectionAddress(const object::SectionRef &Sec,
diff --git a/test/DebugInfo/Inputs/test-inline.o b/test/DebugInfo/Inputs/test-inline.o
new file mode 100644
index 0000000000..a650c91725
--- /dev/null
+++ b/test/DebugInfo/Inputs/test-inline.o
Binary files differ
diff --git a/test/DebugInfo/debuglineinfo.test b/test/DebugInfo/debuglineinfo.test
new file mode 100644
index 0000000000..78de390a8b
--- /dev/null
+++ b/test/DebugInfo/debuglineinfo.test
@@ -0,0 +1,15 @@
+RUN: llvm-rtdyld -printline %p/Inputs/test-inline.o \
+RUN: | FileCheck %s -check-prefix TEST_INLINE
+
+; This test verifies that relocations are correctly applied to the
+; .debug_line section. If relocations are not applied the first two
+; functions will be reported as both starting at address zero in the
+; line number table.
+TEST_INLINE: Function: _Z15test_parametersPfPA2_dR11char_structPPitm, Size = 170
+TEST_INLINE-NEXT: Line info:test-inline.cpp, line:33
+TEST_INLINE-NEXT: Function: _Z3foov, Size = 3
+TEST_INLINE-NEXT: Line info:test-inline.cpp, line:28
+TEST_INLINE-NEXT: Function: main, Size = 146
+TEST_INLINE-NEXT: Line info:test-inline.cpp, line:39
+
+
diff --git a/tools/llvm-rtdyld/CMakeLists.txt b/tools/llvm-rtdyld/CMakeLists.txt
index 17e2c3e2d5..8d161d366d 100644
--- a/tools/llvm-rtdyld/CMakeLists.txt
+++ b/tools/llvm-rtdyld/CMakeLists.txt
@@ -1,4 +1,4 @@
-set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC object RuntimeDyld JIT)
+set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC object RuntimeDyld JIT debuginfo)
add_llvm_tool(llvm-rtdyld
llvm-rtdyld.cpp
diff --git a/tools/llvm-rtdyld/Makefile b/tools/llvm-rtdyld/Makefile
index 30fbee0979..fabdd683a9 100644
--- a/tools/llvm-rtdyld/Makefile
+++ b/tools/llvm-rtdyld/Makefile
@@ -9,7 +9,7 @@
LEVEL := ../..
TOOLNAME := llvm-rtdyld
-LINK_COMPONENTS := all-targets support MC object RuntimeDyld JIT
+LINK_COMPONENTS := all-targets support MC object RuntimeDyld JIT debuginfo
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp
index ec63c9b56c..8b71a4f364 100644
--- a/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -13,6 +13,7 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/ExecutionEngine/ObjectBuffer.h"
#include "llvm/ExecutionEngine/ObjectImage.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
@@ -31,7 +32,8 @@ InputFileList(cl::Positional, cl::ZeroOrMore,
cl::desc("<input file>"));
enum ActionType {
- AC_Execute
+ AC_Execute,
+ AC_PrintLineInfo
};
static cl::opt<ActionType>
@@ -39,6 +41,8 @@ Action(cl::desc("Action to perform:"),
cl::init(AC_Execute),
cl::values(clEnumValN(AC_Execute, "execute",
"Load, link, and execute the inputs."),
+ clEnumValN(AC_PrintLineInfo, "printline",
+ "Load, link, and print line information for each function."),
clEnumValEnd));
static cl::opt<std::string>
@@ -114,6 +118,60 @@ static int Error(const Twine &Msg) {
/* *** */
+static int printLineInfoForInput() {
+ // If we don't have any input files, read from stdin.
+ if (!InputFileList.size())
+ InputFileList.push_back("-");
+ for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
+ // Instantiate a dynamic linker.
+ TrivialMemoryManager *MemMgr = new TrivialMemoryManager;
+ RuntimeDyld Dyld(MemMgr);
+
+ // Load the input memory buffer.
+ OwningPtr<MemoryBuffer> InputBuffer;
+ OwningPtr<ObjectImage> LoadedObject;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i],
+ InputBuffer))
+ return Error("unable to read input: '" + ec.message() + "'");
+
+ // Load the object file
+ LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take())));
+ if (!LoadedObject) {
+ return Error(Dyld.getErrorString());
+ }
+
+ // Resolve all the relocations we can.
+ Dyld.resolveRelocations();
+
+ OwningPtr<DIContext> Context(DIContext::getDWARFContext(LoadedObject->getObjectFile()));
+
+ // Use symbol info to iterate functions in the object.
+ error_code ec;
+ for (object::symbol_iterator I = LoadedObject->begin_symbols(),
+ E = LoadedObject->end_symbols();
+ I != E && !ec;
+ I.increment(ec)) {
+ object::SymbolRef::Type SymType;
+ if (I->getType(SymType)) continue;
+ if (SymType == object::SymbolRef::ST_Function) {
+ StringRef Name;
+ uint64_t Addr;
+ uint64_t Size;
+ if (I->getName(Name)) continue;
+ if (I->getAddress(Addr)) continue;
+ if (I->getSize(Size)) continue;
+
+ outs() << "Function: " << Name << ", Size = " << Size << "\n";
+
+ DILineInfo Result = Context->getLineInfoForAddress(Addr);
+ outs() << " Line info:" << Result.getFileName() << ", line:" << Result.getLine() << "\n";
+ }
+ }
+ }
+
+ return 0;
+}
+
static int executeInput() {
// Instantiate a dynamic linker.
TrivialMemoryManager *MemMgr = new TrivialMemoryManager;
@@ -180,5 +238,7 @@ int main(int argc, char **argv) {
switch (Action) {
case AC_Execute:
return executeInput();
+ case AC_PrintLineInfo:
+ return printLineInfoForInput();
}
}