llvm.org GIT mirror llvm / ee7c0d2
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 Andrew Kaylor 7 years ago
13 changed file(s) with 139 addition(s) and 13 deletion(s). Raw diff Collapse all Expand all
4949
5050 virtual StringRef getData() const = 0;
5151
52 virtual object::ObjectFile* getObjectFile() const = 0;
53
5254 // Subclasses can override these methods to provide JIT debugging support
5355 virtual void registerWithDebugger() = 0;
5456 virtual void deregisterWithDebugger() = 0;
1212 #include "DWARFDebugAbbrev.h"
1313 #include "DWARFDebugInfoEntry.h"
1414 #include "DWARFDebugRangeList.h"
15 #include "DWARFRelocMap.h"
1516 #include
1617
1718 namespace llvm {
1920 class DWARFDebugAbbrev;
2021 class StringRef;
2122 class raw_ostream;
22 typedef DenseMap > RelocAddrMap;
2323
2424 class DWARFCompileUnit {
2525 const DWARFDebugAbbrev *Abbrev;
5252 DataExtractor lineData(getLineSection(), isLittleEndian(),
5353 savedAddressByteSize);
5454 DWARFDebugLine::DumpingState state(OS);
55 DWARFDebugLine::parseStatementTable(lineData, &stmtOffset, state);
55 DWARFDebugLine::parseStatementTable(lineData, &lineRelocMap(), &stmtOffset, state);
5656 }
5757 }
5858 }
154154 const DWARFLineTable *
155155 DWARFContext::getLineTableForCompileUnit(DWARFCompileUnit *cu) {
156156 if (!Line)
157 Line.reset(new DWARFDebugLine());
157 Line.reset(new DWARFDebugLine(&lineRelocMap()));
158158
159159 unsigned stmtOffset =
160160 cu->getCompileUnitDIE()->getAttributeValueAsUnsigned(cu, DW_AT_stmt_list,
421421 else
422422 continue;
423423
424 // TODO: For now only handle relocations for the debug_info section.
424 // TODO: Add support for relocations in other sections as needed.
425 // Record relocations for the debug_info and debug_line sections.
425426 RelocAddrMap *Map;
426427 if (name == "debug_info")
427428 Map = &InfoRelocMap;
428429 else if (name == "debug_info.dwo")
429430 Map = &InfoDWORelocMap;
431 else if (name == "debug_line")
432 Map = &LineRelocMap;
430433 else
431434 continue;
432435
440443 reloc_i->getAddress(Address);
441444 uint64_t Type;
442445 reloc_i->getType(Type);
446 uint64_t SymAddr = 0;
447 // ELF relocations may need the symbol address
448 if (Obj->isELF()) {
449 object::SymbolRef Sym;
450 reloc_i->getSymbol(Sym);
451 Sym.getAddress(SymAddr);
452 }
443453
444454 object::RelocVisitor V(Obj->getFileFormatName());
445455 // The section address is always 0 for debug sections.
446 object::RelocToApply R(V.visit(Type, *reloc_i));
456 object::RelocToApply R(V.visit(Type, *reloc_i, 0, SymAddr));
447457 if (V.error()) {
448458 SmallString<32> Name;
449459 error_code ec(reloc_i->getTypeName(Name));
9494
9595 virtual bool isLittleEndian() const = 0;
9696 virtual const RelocAddrMap &infoRelocMap() const = 0;
97 virtual const RelocAddrMap &lineRelocMap() const = 0;
9798 virtual StringRef getInfoSection() = 0;
9899 virtual StringRef getAbbrevSection() = 0;
99100 virtual StringRef getARangeSection() = 0;
129130 virtual void anchor();
130131 bool IsLittleEndian;
131132 RelocAddrMap InfoRelocMap;
133 RelocAddrMap LineRelocMap;
132134 StringRef InfoSection;
133135 StringRef AbbrevSection;
134136 StringRef ARangeSection;
149151 DWARFContextInMemory(object::ObjectFile *);
150152 virtual bool isLittleEndian() const { return IsLittleEndian; }
151153 virtual const RelocAddrMap &infoRelocMap() const { return InfoRelocMap; }
154 virtual const RelocAddrMap &lineRelocMap() const { return LineRelocMap; }
152155 virtual StringRef getInfoSection() { return InfoSection; }
153156 virtual StringRef getAbbrevSection() { return AbbrevSection; }
154157 virtual StringRef getARangeSection() { return ARangeSection; }
154154 if (pos.second) {
155155 // Parse and cache the line table for at this offset.
156156 State state;
157 if (!parseStatementTable(debug_line_data, &offset, state))
157 if (!parseStatementTable(debug_line_data, RelocMap, &offset, state))
158158 return 0;
159159 pos.first->second = state;
160160 }
218218 }
219219
220220 bool
221 DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
221 DWARFDebugLine::parseStatementTable(DataExtractor debug_line_data,
222 const RelocAddrMap *RMap,
222223 uint32_t *offset_ptr, State &state) {
223224 const uint32_t debug_line_offset = *offset_ptr;
224225
267268 // relocatable address. All of the other statement program opcodes
268269 // that affect the address register add a delta to it. This instruction
269270 // stores a relocatable value into it instead.
270 state.Address = debug_line_data.getAddress(offset_ptr);
271 {
272 // If this address is in our relocation map, apply the relocation.
273 RelocAddrMap::const_iterator AI = RMap->find(*offset_ptr);
274 if (AI != RMap->end()) {
275 const std::pair &R = AI->second;
276 state.Address = debug_line_data.getAddress(offset_ptr) + R.second;
277 } else
278 state.Address = debug_line_data.getAddress(offset_ptr);
279 }
271280 break;
272281
273282 case DW_LNE_define_file:
99 #ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
1010 #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
1111
12 #include "DWARFRelocMap.h"
1213 #include "llvm/Support/DataExtractor.h"
1314 #include
1415 #include
2021
2122 class DWARFDebugLine {
2223 public:
24 DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {}
2325 struct FileNameEntry {
2426 FileNameEntry() : Name(0), DirIdx(0), ModTime(0), Length(0) {}
2527
226228 Prologue *prologue);
227229 /// Parse a single line table (prologue and all rows).
228230 static bool parseStatementTable(DataExtractor debug_line_data,
231 const RelocAddrMap *RMap,
229232 uint32_t *offset_ptr, State &state);
230233
231234 const LineTable *getLineTable(uint32_t offset) const;
237240 typedef LineTableMapTy::iterator LineTableIter;
238241 typedef LineTableMapTy::const_iterator LineTableConstIter;
239242
243 const RelocAddrMap *RelocMap;
240244 LineTableMapTy LineTableMap;
241245 };
242246
0 //===-- DWARFRelocMap.h -----------------------------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_DEBUGINFO_DWARFRELOCMAP_H
10 #define LLVM_DEBUGINFO_DWARFRELOCMAP_H
11
12 #include "llvm/ADT/DenseMap.h"
13
14 namespace llvm {
15
16 typedef DenseMap > RelocAddrMap;
17
18 } // namespace llvm
19
20 #endif // LLVM_DEBUGINFO_DWARFRELOCMAP_H
5757
5858 virtual StringRef getData() const { return ObjFile->getData(); }
5959
60 virtual object::ObjectFile* getObjectFile() const { return ObjFile; }
61
6062 // Subclasses can override these methods to update the image with loaded
6163 // addresses for sections and common symbols
6264 virtual void updateSectionAddress(const object::SectionRef &Sec,
0 RUN: llvm-rtdyld -printline %p/Inputs/test-inline.o \
1 RUN: | FileCheck %s -check-prefix TEST_INLINE
2
3 ; This test verifies that relocations are correctly applied to the
4 ; .debug_line section. If relocations are not applied the first two
5 ; functions will be reported as both starting at address zero in the
6 ; line number table.
7 TEST_INLINE: Function: _Z15test_parametersPfPA2_dR11char_structPPitm, Size = 170
8 TEST_INLINE-NEXT: Line info:test-inline.cpp, line:33
9 TEST_INLINE-NEXT: Function: _Z3foov, Size = 3
10 TEST_INLINE-NEXT: Line info:test-inline.cpp, line:28
11 TEST_INLINE-NEXT: Function: main, Size = 146
12 TEST_INLINE-NEXT: Line info:test-inline.cpp, line:39
13
14
None set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC object RuntimeDyld JIT)
0 set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} support MC object RuntimeDyld JIT debuginfo)
11
22 add_llvm_tool(llvm-rtdyld
33 llvm-rtdyld.cpp
88
99 LEVEL := ../..
1010 TOOLNAME := llvm-rtdyld
11 LINK_COMPONENTS := all-targets support MC object RuntimeDyld JIT
11 LINK_COMPONENTS := all-targets support MC object RuntimeDyld JIT debuginfo
1212
1313 # This tool has no plugins, optimize startup time.
1414 TOOL_NO_EXPORTS := 1
1212
1313 #include "llvm/ADT/OwningPtr.h"
1414 #include "llvm/ADT/StringMap.h"
15 #include "llvm/DebugInfo/DIContext.h"
1516 #include "llvm/ExecutionEngine/ObjectBuffer.h"
1617 #include "llvm/ExecutionEngine/ObjectImage.h"
1718 #include "llvm/ExecutionEngine/RuntimeDyld.h"
3031 cl::desc(""));
3132
3233 enum ActionType {
33 AC_Execute
34 AC_Execute,
35 AC_PrintLineInfo
3436 };
3537
3638 static cl::opt
3840 cl::init(AC_Execute),
3941 cl::values(clEnumValN(AC_Execute, "execute",
4042 "Load, link, and execute the inputs."),
43 clEnumValN(AC_PrintLineInfo, "printline",
44 "Load, link, and print line information for each function."),
4145 clEnumValEnd));
4246
4347 static cl::opt
112116 }
113117
114118 /* *** */
119
120 static int printLineInfoForInput() {
121 // If we don't have any input files, read from stdin.
122 if (!InputFileList.size())
123 InputFileList.push_back("-");
124 for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) {
125 // Instantiate a dynamic linker.
126 TrivialMemoryManager *MemMgr = new TrivialMemoryManager;
127 RuntimeDyld Dyld(MemMgr);
128
129 // Load the input memory buffer.
130 OwningPtr InputBuffer;
131 OwningPtr LoadedObject;
132 if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i],
133 InputBuffer))
134 return Error("unable to read input: '" + ec.message() + "'");
135
136 // Load the object file
137 LoadedObject.reset(Dyld.loadObject(new ObjectBuffer(InputBuffer.take())));
138 if (!LoadedObject) {
139 return Error(Dyld.getErrorString());
140 }
141
142 // Resolve all the relocations we can.
143 Dyld.resolveRelocations();
144
145 OwningPtr Context(DIContext::getDWARFContext(LoadedObject->getObjectFile()));
146
147 // Use symbol info to iterate functions in the object.
148 error_code ec;
149 for (object::symbol_iterator I = LoadedObject->begin_symbols(),
150 E = LoadedObject->end_symbols();
151 I != E && !ec;
152 I.increment(ec)) {
153 object::SymbolRef::Type SymType;
154 if (I->getType(SymType)) continue;
155 if (SymType == object::SymbolRef::ST_Function) {
156 StringRef Name;
157 uint64_t Addr;
158 uint64_t Size;
159 if (I->getName(Name)) continue;
160 if (I->getAddress(Addr)) continue;
161 if (I->getSize(Size)) continue;
162
163 outs() << "Function: " << Name << ", Size = " << Size << "\n";
164
165 DILineInfo Result = Context->getLineInfoForAddress(Addr);
166 outs() << " Line info:" << Result.getFileName() << ", line:" << Result.getLine() << "\n";
167 }
168 }
169 }
170
171 return 0;
172 }
115173
116174 static int executeInput() {
117175 // Instantiate a dynamic linker.
179237 switch (Action) {
180238 case AC_Execute:
181239 return executeInput();
182 }
183 }
240 case AC_PrintLineInfo:
241 return printLineInfoForInput();
242 }
243 }