llvm.org GIT mirror llvm / b6976af
Make it easier to use DwarfContext with MCJIT Summary: This supersedes http://reviews.llvm.org/D4010, hopefully properly dealing with the JIT case and also adds an actual test case. DwarfContext was basically already usable for the JIT (and back when we were overwriting ELF files it actually worked out of the box by accident), but in order to resolve relocations correctly it needs to know the load address of the section. Rather than trying to get this out of the ObjectFile or requiring the user to create a new ObjectFile just to get some debug info, this adds the capability to pass in that info directly. As part of this I separated out part of the LoadedObjectInfo struct from RuntimeDyld, since it is now required at a higher layer. Reviewers: lhames, echristo Reviewed By: echristo Subscribers: vtjnash, friss, rafael, llvm-commits Differential Revision: http://reviews.llvm.org/D6961 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237961 91177308-0d34-0410-b5e6-96231b3b80d8 Keno Fischer 4 years ago
17 changed file(s) with 205 addition(s) and 38 deletion(s). Raw diff Collapse all Expand all
135135 const DIContextKind Kind;
136136 };
137137
138 /// An inferface for inquiring the load address of a loaded object file
139 /// to be used by the DIContext implementations when applying relocations
140 /// on the fly.
141 class LoadedObjectInfo {
142 public:
143 LoadedObjectInfo() {}
144 virtual ~LoadedObjectInfo() {}
145
146 /// Obtain the Load Address of a section by Name.
147 ///
148 /// Calculate the address of the section identified by the passed in Name.
149 /// The section need not be present in the local address space. The addresses
150 /// need to be consistent with the addresses used to query the DIContext and
151 /// the output of this function should be deterministic, i.e. repeated calls with
152 /// the same Name should give the same address.
153 virtual uint64_t getSectionLoadAddress(StringRef Name) const = 0;
154
155 /// If conveniently available, return the content of the given Section.
156 ///
157 /// When the section is available in the local address space, in relocated (loaded)
158 /// form, e.g. because it was relocated by a JIT for execution, this function
159 /// should provide the contents of said section in `Data`. If the loaded section
160 /// is not available, or the cost of retrieving it would be prohibitive, this
161 /// function should return false. In that case, relocations will be read from the
162 /// local (unrelocated) object file and applied on the fly. Note that this method
163 /// is used purely for optimzation purposes in the common case of JITting in the
164 /// local address space, so returning false should always be correct.
165 virtual bool getLoadedSectionContents(StringRef Name, StringRef &Data) const {
166 return false;
167 }
168
169 /// Obtain a copy of this LoadedObjectInfo.
170 ///
171 /// The caller is responsible for deallocation once the copy is no longer required.
172 virtual LoadedObjectInfo *clone() const = 0;
173 };
174
138175 }
139176
140177 #endif
254254 SmallVector, 4> UncompressedSections;
255255
256256 public:
257 DWARFContextInMemory(const object::ObjectFile &Obj);
257 DWARFContextInMemory(const object::ObjectFile &Obj,
258 const LoadedObjectInfo *L = nullptr);
258259 bool isLittleEndian() const override { return IsLittleEndian; }
259260 uint8_t getAddressSize() const override { return AddressSize; }
260261 const DWARFSection &getInfoSection() override { return InfoSection; }
1616 #include "JITSymbolFlags.h"
1717 #include "llvm/ADT/StringRef.h"
1818 #include "llvm/Support/Memory.h"
19 #include "llvm/DebugInfo/DIContext.h"
1920 #include
2021
2122 namespace llvm {
5354 };
5455
5556 /// \brief Information about the loaded object.
56 class LoadedObjectInfo {
57 class LoadedObjectInfo : public llvm::LoadedObjectInfo {
5758 friend class RuntimeDyldImpl;
5859 public:
5960 LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
349349 return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE;
350350 }
351351
352 bool isSection() const {
353 return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION;
354 }
355
352356 bool isSectionDefinition() const {
353357 // C++/CLI creates external ABS symbols for non-const appdomain globals.
354358 // These are also followed by an auxiliary section definition.
611615 std::error_code getRelocationOffset(DataRefImpl Rel,
612616 uint64_t &Res) const override;
613617 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
618 section_iterator getRelocationSection(DataRefImpl Rel) const override;
614619 std::error_code getRelocationType(DataRefImpl Rel,
615620 uint64_t &Res) const override;
616621 std::error_code
8585 std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override;
8686 std::error_code getSymbolType(DataRefImpl Symb,
8787 SymbolRef::Type &Res) const override;
88 section_iterator getSymbolSection(const Elf_Sym *Symb) const;
8889 std::error_code getSymbolSection(DataRefImpl Symb,
8990 section_iterator &Res) const override;
9091
111112 std::error_code getRelocationOffset(DataRefImpl Rel,
112113 uint64_t &Res) const override;
113114 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
115 section_iterator getRelocationSection(DataRefImpl Rel) const override;
114116 std::error_code getRelocationType(DataRefImpl Rel,
115117 uint64_t &Res) const override;
116118 std::error_code
415417 }
416418
417419 template
420 section_iterator
421 ELFObjectFile::getSymbolSection(const Elf_Sym *ESym) const {
422 const Elf_Shdr *ESec = EF.getSection(ESym);
423 if (!ESec)
424 return section_end();
425 else {
426 DataRefImpl Sec;
427 Sec.p = reinterpret_cast(ESec);
428 return section_iterator(SectionRef(Sec, this));
429 }
430 }
431
432 template
418433 std::error_code
419434 ELFObjectFile::getSymbolSection(DataRefImpl Symb,
420435 section_iterator &Res) const {
421 const Elf_Sym *ESym = getSymbol(Symb);
422 const Elf_Shdr *ESec = EF.getSection(ESym);
423 if (!ESec)
424 Res = section_end();
425 else {
426 DataRefImpl Sec;
427 Sec.p = reinterpret_cast(ESec);
428 Res = section_iterator(SectionRef(Sec, this));
429 }
436 Res = getSymbolSection(getSymbol(Symb));
430437 return object_error::success;
431438 }
432439
585592 }
586593
587594 return symbol_iterator(SymbolRef(SymbolData, this));
595 }
596
597 // ELF relocations can target sections, by targetting a symbol of type
598 // STT_SECTION
599 template
600 section_iterator
601 ELFObjectFile::getRelocationSection(DataRefImpl Rel) const {
602 symbol_iterator Sym = getRelocationSymbol(Rel);
603 if (Sym == symbol_end())
604 return section_end();
605 const Elf_Sym *ESym = getSymbol(Sym->getRawDataRefImpl());
606 if (ESym->getType() != ELF::STT_SECTION)
607 return section_end();
608 return getSymbolSection(ESym);
588609 }
589610
590611 template
234234 std::error_code getRelocationOffset(DataRefImpl Rel,
235235 uint64_t &Res) const override;
236236 symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
237 section_iterator getRelocationSection(DataRefImpl Rel) const override;
237238 std::error_code getRelocationType(DataRefImpl Rel,
238239 uint64_t &Res) const override;
239240 std::error_code
325326 unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const;
326327 unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const;
327328 unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const;
328 SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const;
329 SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const;
329330
330331 // Walk load commands.
331332 LoadCommandInfo getFirstLoadCommandInfo() const;
3131
3232 class SymbolRef;
3333 class symbol_iterator;
34 class SectionRef;
35 typedef content_iterator section_iterator;
3436
3537 /// RelocationRef - This is a value type class that represents a single
3638 /// relocation in the list of relocations in the object file.
5052 std::error_code getAddress(uint64_t &Result) const;
5153 std::error_code getOffset(uint64_t &Result) const;
5254 symbol_iterator getSymbol() const;
55 section_iterator getSection() const;
5356 std::error_code getType(uint64_t &Result) const;
5457
5558 /// @brief Indicates whether this relocation should hidden when listing
7578
7679 /// SectionRef - This is a value type class that represents a single section in
7780 /// the list of sections in the object file.
78 class SectionRef;
79 typedef content_iterator section_iterator;
8081 class SectionRef {
8182 friend class SymbolRef;
8283 DataRefImpl SectionPimpl;
246247 virtual std::error_code getRelocationOffset(DataRefImpl Rel,
247248 uint64_t &Res) const = 0;
248249 virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0;
250 virtual section_iterator getRelocationSection(DataRefImpl Rel) const = 0;
249251 virtual std::error_code getRelocationType(DataRefImpl Rel,
250252 uint64_t &Res) const = 0;
251253 virtual std::error_code
466468 return OwningObject->getRelocationSymbol(RelocationPimpl);
467469 }
468470
471 inline section_iterator RelocationRef::getSection() const {
472 return OwningObject->getRelocationSection(RelocationPimpl);
473 }
474
469475 inline std::error_code RelocationRef::getType(uint64_t &Result) const {
470476 return OwningObject->getRelocationType(RelocationPimpl, Result);
471477 }
539539 return true;
540540 }
541541
542 DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj)
542 DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
543 const LoadedObjectInfo *L)
543544 : IsLittleEndian(Obj.isLittleEndian()),
544545 AddressSize(Obj.getBytesInAddress()) {
545546 for (const SectionRef &Section : Obj.sections()) {
553554 if (IsVirtual)
554555 continue;
555556 StringRef data;
556 Section.getContents(data);
557
558 // Try to obtain an already relocated version of this section.
559 // Else use the unrelocated section from the object file. We'll have to
560 // apply relocations ourselves later.
561 if (!L || !L->getLoadedSectionContents(name,data))
562 Section.getContents(data);
557563
558564 name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
559565
621627 continue;
622628
623629 StringRef RelSecName;
630 StringRef RelSecData;
624631 RelocatedSection->getName(RelSecName);
632
633 // If the section we're relocating was relocated already by the JIT,
634 // then we used the relocated version above, so we do not need to process
635 // relocations for it now.
636 if (L && L->getLoadedSectionContents(RelSecName,RelSecData))
637 continue;
638
625639 RelSecName = RelSecName.substr(
626640 RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.
627641
657671 uint64_t Type;
658672 Reloc.getType(Type);
659673 uint64_t SymAddr = 0;
674 uint64_t SectionLoadAddress = 0;
660675 object::symbol_iterator Sym = Reloc.getSymbol();
661 if (Sym != Obj.symbol_end())
676 object::section_iterator RSec = Reloc.getSection();
677
678 // First calculate the address of the symbol or section as it appears
679 // in the objct file
680 if (Sym != Obj.symbol_end()) {
662681 Sym->getAddress(SymAddr);
682 // Also remember what section this symbol is in for later
683 Sym->getSection(RSec);
684 } else if (RSec != Obj.section_end())
685 SymAddr = RSec->getAddress();
686
687 // If we are given load addresses for the sections, we need to adjust:
688 // SymAddr = (Address of Symbol Or Section in File) -
689 // (Address of Section in File) +
690 // (Load Address of Section)
691 if (L != nullptr && RSec != Obj.section_end()) {
692 // RSec is now either the section being targetted or the section
693 // containing the symbol being targetted. In either case,
694 // we need to perform the same computation.
695 StringRef SecName;
696 RSec->getName(SecName);
697 SectionLoadAddress = L->getSectionLoadAddress(SecName);
698 if (SectionLoadAddress != 0)
699 SymAddr += SectionLoadAddress - RSec->getAddress();
700 }
663701
664702 object::RelocVisitor V(Obj);
665703 object::RelocToApply R(V.visit(Type, Reloc, SymAddr));
3333 getObjectForDebug(const ObjectFile &Obj) const override {
3434 return OwningBinary();
3535 }
36
37 RuntimeDyld::LoadedObjectInfo *clone() const { return new LoadedCOFFObjectInfo(*this); }
3638 };
3739 }
3840
111111
112112 OwningBinary
113113 getObjectForDebug(const ObjectFile &Obj) const override;
114
115 RuntimeDyld::LoadedObjectInfo *clone() const { return new LoadedELFObjectInfo(*this); }
114116 };
115117
116118 template
202202 SectionList Sections;
203203
204204 typedef unsigned SID; // Type for SectionIDs
205 #define RTDYLD_INVALID_SECTION_ID ((SID)(-1))
205 #define RTDYLD_INVALID_SECTION_ID ((RuntimeDyldImpl::SID)(-1))
206206
207207 // Keep a map of sections from object file to the SectionID which
208208 // references it.
3535 getObjectForDebug(const ObjectFile &Obj) const override {
3636 return OwningBinary();
3737 }
38
39 RuntimeDyld::LoadedObjectInfo *clone() const { return new LoadedMachOObjectInfo(*this); }
3840 };
3941
4042 }
7476 Value.Offset = RE.Addend;
7577 }
7678 } else {
77 SectionRef Sec = Obj.getRelocationSection(RelInfo);
79 SectionRef Sec = Obj.getAnyRelocationSection(RelInfo);
7880 bool IsCode = Sec.isText();
7981 Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID);
8082 uint64_t Addr = Sec.getAddress();
10411041 else
10421042 llvm_unreachable("no symbol table pointer!");
10431043 return symbol_iterator(SymbolRef(Ref, this));
1044 }
1045
1046 section_iterator COFFObjectFile::getRelocationSection(DataRefImpl Rel) const {
1047 symbol_iterator Sym = getRelocationSymbol(Rel);
1048 if (Sym == symbol_end())
1049 return section_end();
1050 COFFSymbolRef Symb = getCOFFSymbol(*Sym);
1051 if (!Symb.isSection())
1052 return section_end();
1053 section_iterator Res(section_end());
1054 if (getSymbolSection(Sym->getRawDataRefImpl(),Res))
1055 return section_end();
1056 return Res;
10441057 }
10451058
10461059 std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
707707 DataRefImpl Sym;
708708 Sym.p = reinterpret_cast(getPtr(this, Offset));
709709 return symbol_iterator(SymbolRef(Sym, this));
710 }
711
712 section_iterator
713 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
714 return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
710715 }
711716
712717 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
22232228 }
22242229
22252230 SectionRef
2226 MachOObjectFile::getRelocationSection(
2231 MachOObjectFile::getAnyRelocationSection(
22272232 const MachO::any_relocation_info &RE) const {
22282233 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
22292234 return *section_end();
0 RUN: llvm-rtdyld -printline %p/Inputs/test-inline.o \
11 RUN: | FileCheck %s -check-prefix TEST_INLINE
2 RUN: llvm-rtdyld -printdebugline %p/Inputs/test-inline.o \
3 RUN: | FileCheck %s -check-prefix TEST_INLINE
24 RUN: llvm-rtdyld -printline %p/Inputs/test-parameters.o \
5 RUN: | FileCheck %s -check-prefix TEST_PARAMETERS
6 RUN: llvm-rtdyld -printdebugline %p/Inputs/test-parameters.o \
37 RUN: | FileCheck %s -check-prefix TEST_PARAMETERS
48
59 ; This test verifies that relocations are correctly applied to the
64836483 }
64846484
64856485 auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
6486 SectionRef RelocSection = Obj->getRelocationSection(RE);
6486 SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
64876487
64886488 uint64_t SectionAddr = RelocSection.getAddress();
64896489
4747 enum ActionType {
4848 AC_Execute,
4949 AC_PrintLineInfo,
50 AC_PrintDebugLineInfo,
5051 AC_Verify
5152 };
5253
5758 "Load, link, and execute the inputs."),
5859 clEnumValN(AC_PrintLineInfo, "printline",
5960 "Load, link, and print line information for each function."),
61 clEnumValN(AC_PrintDebugLineInfo, "printdebugline",
62 "Load, link, and print line information for each function using the debug object"),
6063 clEnumValN(AC_Verify, "verify",
6164 "Load, link and verify the resulting memory image."),
6265 clEnumValEnd));
188191
189192 /* *** */
190193
191 static int printLineInfoForInput() {
194 static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
195 assert(LoadObjects || !UseDebugObj);
196
192197 // Load any dylibs requested on the command line.
193198 loadDylibs();
194199
215220
216221 ObjectFile &Obj = **MaybeObj;
217222
218 // Load the object file
219 std::unique_ptr LoadedObjInfo =
220 Dyld.loadObject(Obj);
221
222 if (Dyld.hasError())
223 return Error(Dyld.getErrorString());
224
225 // Resolve all the relocations we can.
226 Dyld.resolveRelocations();
227
228 OwningBinary DebugObj = LoadedObjInfo->getObjectForDebug(Obj);
223 OwningBinary DebugObj;
224 std::unique_ptr LoadedObjInfo = nullptr;
225 ObjectFile *SymbolObj = &Obj;
226 if (LoadObjects) {
227 // Load the object file
228 LoadedObjInfo =
229 Dyld.loadObject(Obj);
230
231 if (Dyld.hasError())
232 return Error(Dyld.getErrorString());
233
234 // Resolve all the relocations we can.
235 Dyld.resolveRelocations();
236
237 if (UseDebugObj) {
238 DebugObj = LoadedObjInfo->getObjectForDebug(Obj);
239 SymbolObj = DebugObj.getBinary();
240 }
241 }
229242
230243 std::unique_ptr Context(
231 new DWARFContextInMemory(*DebugObj.getBinary()));
244 new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get()));
232245
233246 // Use symbol info to iterate functions in the object.
234 for (object::symbol_iterator I = DebugObj.getBinary()->symbol_begin(),
235 E = DebugObj.getBinary()->symbol_end();
247 for (object::symbol_iterator I = SymbolObj->symbol_begin(),
248 E = SymbolObj->symbol_end();
236249 I != E; ++I) {
237250 object::SymbolRef::Type SymType;
238251 if (I->getType(SymType)) continue;
244257 if (I->getAddress(Addr)) continue;
245258 if (I->getSize(Size)) continue;
246259
247 outs() << "Function: " << Name << ", Size = " << Size << "\n";
260 // If we're not using the debug object, compute the address of the
261 // symbol in memory (rather than that in the unrelocated object file)
262 // and use that to query the DWARFContext.
263 if (!UseDebugObj && LoadObjects) {
264 object::section_iterator Sec(SymbolObj->section_end());
265 I->getSection(Sec);
266 StringRef SecName;
267 Sec->getName(SecName);
268 uint64_t SectionLoadAddress =
269 LoadedObjInfo->getSectionLoadAddress(SecName);
270 if (SectionLoadAddress != 0)
271 Addr += SectionLoadAddress - Sec->getAddress();
272 }
273
274 outs() << "Function: " << Name << ", Size = " << Size << ", Addr = " << Addr << "\n";
248275
249276 DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
250277 DILineInfoTable::iterator Begin = Lines.begin();
593620 switch (Action) {
594621 case AC_Execute:
595622 return executeInput();
623 case AC_PrintDebugLineInfo:
624 return printLineInfoForInput(true,true);
596625 case AC_PrintLineInfo:
597 return printLineInfoForInput();
626 return printLineInfoForInput(true,false);
598627 case AC_Verify:
599628 return linkAndVerify();
600629 }