mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-19 18:24:00 +00:00
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
This commit is contained in:
@ -136,6 +136,43 @@ private:
|
|||||||
const DIContextKind Kind;
|
const DIContextKind Kind;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// An inferface for inquiring the load address of a loaded object file
|
||||||
|
/// to be used by the DIContext implementations when applying relocations
|
||||||
|
/// on the fly.
|
||||||
|
class LoadedObjectInfo {
|
||||||
|
public:
|
||||||
|
LoadedObjectInfo() {}
|
||||||
|
virtual ~LoadedObjectInfo() {}
|
||||||
|
|
||||||
|
/// Obtain the Load Address of a section by Name.
|
||||||
|
///
|
||||||
|
/// Calculate the address of the section identified by the passed in Name.
|
||||||
|
/// The section need not be present in the local address space. The addresses
|
||||||
|
/// need to be consistent with the addresses used to query the DIContext and
|
||||||
|
/// the output of this function should be deterministic, i.e. repeated calls with
|
||||||
|
/// the same Name should give the same address.
|
||||||
|
virtual uint64_t getSectionLoadAddress(StringRef Name) const = 0;
|
||||||
|
|
||||||
|
/// If conveniently available, return the content of the given Section.
|
||||||
|
///
|
||||||
|
/// When the section is available in the local address space, in relocated (loaded)
|
||||||
|
/// form, e.g. because it was relocated by a JIT for execution, this function
|
||||||
|
/// should provide the contents of said section in `Data`. If the loaded section
|
||||||
|
/// is not available, or the cost of retrieving it would be prohibitive, this
|
||||||
|
/// function should return false. In that case, relocations will be read from the
|
||||||
|
/// local (unrelocated) object file and applied on the fly. Note that this method
|
||||||
|
/// is used purely for optimzation purposes in the common case of JITting in the
|
||||||
|
/// local address space, so returning false should always be correct.
|
||||||
|
virtual bool getLoadedSectionContents(StringRef Name, StringRef &Data) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Obtain a copy of this LoadedObjectInfo.
|
||||||
|
///
|
||||||
|
/// The caller is responsible for deallocation once the copy is no longer required.
|
||||||
|
virtual LoadedObjectInfo *clone() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -255,7 +255,8 @@ class DWARFContextInMemory : public DWARFContext {
|
|||||||
SmallVector<SmallString<32>, 4> UncompressedSections;
|
SmallVector<SmallString<32>, 4> UncompressedSections;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DWARFContextInMemory(const object::ObjectFile &Obj);
|
DWARFContextInMemory(const object::ObjectFile &Obj,
|
||||||
|
const LoadedObjectInfo *L = nullptr);
|
||||||
bool isLittleEndian() const override { return IsLittleEndian; }
|
bool isLittleEndian() const override { return IsLittleEndian; }
|
||||||
uint8_t getAddressSize() const override { return AddressSize; }
|
uint8_t getAddressSize() const override { return AddressSize; }
|
||||||
const DWARFSection &getInfoSection() override { return InfoSection; }
|
const DWARFSection &getInfoSection() override { return InfoSection; }
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "JITSymbolFlags.h"
|
#include "JITSymbolFlags.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Support/Memory.h"
|
#include "llvm/Support/Memory.h"
|
||||||
|
#include "llvm/DebugInfo/DIContext.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
@ -54,7 +55,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Information about the loaded object.
|
/// \brief Information about the loaded object.
|
||||||
class LoadedObjectInfo {
|
class LoadedObjectInfo : public llvm::LoadedObjectInfo {
|
||||||
friend class RuntimeDyldImpl;
|
friend class RuntimeDyldImpl;
|
||||||
public:
|
public:
|
||||||
LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
|
LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
|
||||||
|
@ -350,6 +350,10 @@ public:
|
|||||||
return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE;
|
return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isSection() const {
|
||||||
|
return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION;
|
||||||
|
}
|
||||||
|
|
||||||
bool isSectionDefinition() const {
|
bool isSectionDefinition() const {
|
||||||
// C++/CLI creates external ABS symbols for non-const appdomain globals.
|
// C++/CLI creates external ABS symbols for non-const appdomain globals.
|
||||||
// These are also followed by an auxiliary section definition.
|
// These are also followed by an auxiliary section definition.
|
||||||
@ -612,6 +616,7 @@ protected:
|
|||||||
std::error_code getRelocationOffset(DataRefImpl Rel,
|
std::error_code getRelocationOffset(DataRefImpl Rel,
|
||||||
uint64_t &Res) const override;
|
uint64_t &Res) const override;
|
||||||
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
|
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
|
||||||
|
section_iterator getRelocationSection(DataRefImpl Rel) const override;
|
||||||
std::error_code getRelocationType(DataRefImpl Rel,
|
std::error_code getRelocationType(DataRefImpl Rel,
|
||||||
uint64_t &Res) const override;
|
uint64_t &Res) const override;
|
||||||
std::error_code
|
std::error_code
|
||||||
|
@ -86,6 +86,7 @@ protected:
|
|||||||
std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override;
|
std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override;
|
||||||
std::error_code getSymbolType(DataRefImpl Symb,
|
std::error_code getSymbolType(DataRefImpl Symb,
|
||||||
SymbolRef::Type &Res) const override;
|
SymbolRef::Type &Res) const override;
|
||||||
|
section_iterator getSymbolSection(const Elf_Sym *Symb) const;
|
||||||
std::error_code getSymbolSection(DataRefImpl Symb,
|
std::error_code getSymbolSection(DataRefImpl Symb,
|
||||||
section_iterator &Res) const override;
|
section_iterator &Res) const override;
|
||||||
|
|
||||||
@ -112,6 +113,7 @@ protected:
|
|||||||
std::error_code getRelocationOffset(DataRefImpl Rel,
|
std::error_code getRelocationOffset(DataRefImpl Rel,
|
||||||
uint64_t &Res) const override;
|
uint64_t &Res) const override;
|
||||||
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
|
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
|
||||||
|
section_iterator getRelocationSection(DataRefImpl Rel) const override;
|
||||||
std::error_code getRelocationType(DataRefImpl Rel,
|
std::error_code getRelocationType(DataRefImpl Rel,
|
||||||
uint64_t &Res) const override;
|
uint64_t &Res) const override;
|
||||||
std::error_code
|
std::error_code
|
||||||
@ -416,18 +418,23 @@ uint32_t ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
std::error_code
|
section_iterator
|
||||||
ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
|
ELFObjectFile<ELFT>::getSymbolSection(const Elf_Sym *ESym) const {
|
||||||
section_iterator &Res) const {
|
|
||||||
const Elf_Sym *ESym = getSymbol(Symb);
|
|
||||||
const Elf_Shdr *ESec = EF.getSection(ESym);
|
const Elf_Shdr *ESec = EF.getSection(ESym);
|
||||||
if (!ESec)
|
if (!ESec)
|
||||||
Res = section_end();
|
return section_end();
|
||||||
else {
|
else {
|
||||||
DataRefImpl Sec;
|
DataRefImpl Sec;
|
||||||
Sec.p = reinterpret_cast<intptr_t>(ESec);
|
Sec.p = reinterpret_cast<intptr_t>(ESec);
|
||||||
Res = section_iterator(SectionRef(Sec, this));
|
return section_iterator(SectionRef(Sec, this));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
std::error_code
|
||||||
|
ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
|
||||||
|
section_iterator &Res) const {
|
||||||
|
Res = getSymbolSection(getSymbol(Symb));
|
||||||
return object_error::success;
|
return object_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,6 +595,20 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
|
|||||||
return symbol_iterator(SymbolRef(SymbolData, this));
|
return symbol_iterator(SymbolRef(SymbolData, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ELF relocations can target sections, by targetting a symbol of type
|
||||||
|
// STT_SECTION
|
||||||
|
template <class ELFT>
|
||||||
|
section_iterator
|
||||||
|
ELFObjectFile<ELFT>::getRelocationSection(DataRefImpl Rel) const {
|
||||||
|
symbol_iterator Sym = getRelocationSymbol(Rel);
|
||||||
|
if (Sym == symbol_end())
|
||||||
|
return section_end();
|
||||||
|
const Elf_Sym *ESym = getSymbol(Sym->getRawDataRefImpl());
|
||||||
|
if (ESym->getType() != ELF::STT_SECTION)
|
||||||
|
return section_end();
|
||||||
|
return getSymbolSection(ESym);
|
||||||
|
}
|
||||||
|
|
||||||
template <class ELFT>
|
template <class ELFT>
|
||||||
std::error_code
|
std::error_code
|
||||||
ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel,
|
ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel,
|
||||||
|
@ -235,6 +235,7 @@ public:
|
|||||||
std::error_code getRelocationOffset(DataRefImpl Rel,
|
std::error_code getRelocationOffset(DataRefImpl Rel,
|
||||||
uint64_t &Res) const override;
|
uint64_t &Res) const override;
|
||||||
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
|
symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
|
||||||
|
section_iterator getRelocationSection(DataRefImpl Rel) const override;
|
||||||
std::error_code getRelocationType(DataRefImpl Rel,
|
std::error_code getRelocationType(DataRefImpl Rel,
|
||||||
uint64_t &Res) const override;
|
uint64_t &Res) const override;
|
||||||
std::error_code
|
std::error_code
|
||||||
@ -326,7 +327,7 @@ public:
|
|||||||
unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const;
|
unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const;
|
||||||
unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const;
|
unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const;
|
||||||
unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const;
|
unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const;
|
||||||
SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const;
|
SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const;
|
||||||
|
|
||||||
// Walk load commands.
|
// Walk load commands.
|
||||||
LoadCommandInfo getFirstLoadCommandInfo() const;
|
LoadCommandInfo getFirstLoadCommandInfo() const;
|
||||||
|
@ -32,6 +32,8 @@ class MachOObjectFile;
|
|||||||
|
|
||||||
class SymbolRef;
|
class SymbolRef;
|
||||||
class symbol_iterator;
|
class symbol_iterator;
|
||||||
|
class SectionRef;
|
||||||
|
typedef content_iterator<SectionRef> section_iterator;
|
||||||
|
|
||||||
/// RelocationRef - This is a value type class that represents a single
|
/// RelocationRef - This is a value type class that represents a single
|
||||||
/// relocation in the list of relocations in the object file.
|
/// relocation in the list of relocations in the object file.
|
||||||
@ -51,6 +53,7 @@ public:
|
|||||||
std::error_code getAddress(uint64_t &Result) const;
|
std::error_code getAddress(uint64_t &Result) const;
|
||||||
std::error_code getOffset(uint64_t &Result) const;
|
std::error_code getOffset(uint64_t &Result) const;
|
||||||
symbol_iterator getSymbol() const;
|
symbol_iterator getSymbol() const;
|
||||||
|
section_iterator getSection() const;
|
||||||
std::error_code getType(uint64_t &Result) const;
|
std::error_code getType(uint64_t &Result) const;
|
||||||
|
|
||||||
/// @brief Indicates whether this relocation should hidden when listing
|
/// @brief Indicates whether this relocation should hidden when listing
|
||||||
@ -76,8 +79,6 @@ typedef content_iterator<RelocationRef> relocation_iterator;
|
|||||||
|
|
||||||
/// SectionRef - This is a value type class that represents a single section in
|
/// SectionRef - This is a value type class that represents a single section in
|
||||||
/// the list of sections in the object file.
|
/// the list of sections in the object file.
|
||||||
class SectionRef;
|
|
||||||
typedef content_iterator<SectionRef> section_iterator;
|
|
||||||
class SectionRef {
|
class SectionRef {
|
||||||
friend class SymbolRef;
|
friend class SymbolRef;
|
||||||
DataRefImpl SectionPimpl;
|
DataRefImpl SectionPimpl;
|
||||||
@ -247,6 +248,7 @@ protected:
|
|||||||
virtual std::error_code getRelocationOffset(DataRefImpl Rel,
|
virtual std::error_code getRelocationOffset(DataRefImpl Rel,
|
||||||
uint64_t &Res) const = 0;
|
uint64_t &Res) const = 0;
|
||||||
virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0;
|
virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0;
|
||||||
|
virtual section_iterator getRelocationSection(DataRefImpl Rel) const = 0;
|
||||||
virtual std::error_code getRelocationType(DataRefImpl Rel,
|
virtual std::error_code getRelocationType(DataRefImpl Rel,
|
||||||
uint64_t &Res) const = 0;
|
uint64_t &Res) const = 0;
|
||||||
virtual std::error_code
|
virtual std::error_code
|
||||||
@ -467,6 +469,10 @@ inline symbol_iterator RelocationRef::getSymbol() const {
|
|||||||
return OwningObject->getRelocationSymbol(RelocationPimpl);
|
return OwningObject->getRelocationSymbol(RelocationPimpl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline section_iterator RelocationRef::getSection() const {
|
||||||
|
return OwningObject->getRelocationSection(RelocationPimpl);
|
||||||
|
}
|
||||||
|
|
||||||
inline std::error_code RelocationRef::getType(uint64_t &Result) const {
|
inline std::error_code RelocationRef::getType(uint64_t &Result) const {
|
||||||
return OwningObject->getRelocationType(RelocationPimpl, Result);
|
return OwningObject->getRelocationType(RelocationPimpl, Result);
|
||||||
}
|
}
|
||||||
|
@ -540,7 +540,8 @@ static bool consumeCompressedDebugSectionHeader(StringRef &data,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj)
|
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
|
||||||
|
const LoadedObjectInfo *L)
|
||||||
: IsLittleEndian(Obj.isLittleEndian()),
|
: IsLittleEndian(Obj.isLittleEndian()),
|
||||||
AddressSize(Obj.getBytesInAddress()) {
|
AddressSize(Obj.getBytesInAddress()) {
|
||||||
for (const SectionRef &Section : Obj.sections()) {
|
for (const SectionRef &Section : Obj.sections()) {
|
||||||
@ -554,7 +555,12 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj)
|
|||||||
if (IsVirtual)
|
if (IsVirtual)
|
||||||
continue;
|
continue;
|
||||||
StringRef data;
|
StringRef data;
|
||||||
Section.getContents(data);
|
|
||||||
|
// Try to obtain an already relocated version of this section.
|
||||||
|
// Else use the unrelocated section from the object file. We'll have to
|
||||||
|
// apply relocations ourselves later.
|
||||||
|
if (!L || !L->getLoadedSectionContents(name,data))
|
||||||
|
Section.getContents(data);
|
||||||
|
|
||||||
name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
|
name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
|
||||||
|
|
||||||
@ -622,7 +628,15 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
StringRef RelSecName;
|
StringRef RelSecName;
|
||||||
|
StringRef RelSecData;
|
||||||
RelocatedSection->getName(RelSecName);
|
RelocatedSection->getName(RelSecName);
|
||||||
|
|
||||||
|
// If the section we're relocating was relocated already by the JIT,
|
||||||
|
// then we used the relocated version above, so we do not need to process
|
||||||
|
// relocations for it now.
|
||||||
|
if (L && L->getLoadedSectionContents(RelSecName,RelSecData))
|
||||||
|
continue;
|
||||||
|
|
||||||
RelSecName = RelSecName.substr(
|
RelSecName = RelSecName.substr(
|
||||||
RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.
|
RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.
|
||||||
|
|
||||||
@ -658,9 +672,33 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj)
|
|||||||
uint64_t Type;
|
uint64_t Type;
|
||||||
Reloc.getType(Type);
|
Reloc.getType(Type);
|
||||||
uint64_t SymAddr = 0;
|
uint64_t SymAddr = 0;
|
||||||
|
uint64_t SectionLoadAddress = 0;
|
||||||
object::symbol_iterator Sym = Reloc.getSymbol();
|
object::symbol_iterator Sym = Reloc.getSymbol();
|
||||||
if (Sym != Obj.symbol_end())
|
object::section_iterator RSec = Reloc.getSection();
|
||||||
|
|
||||||
|
// First calculate the address of the symbol or section as it appears
|
||||||
|
// in the objct file
|
||||||
|
if (Sym != Obj.symbol_end()) {
|
||||||
Sym->getAddress(SymAddr);
|
Sym->getAddress(SymAddr);
|
||||||
|
// Also remember what section this symbol is in for later
|
||||||
|
Sym->getSection(RSec);
|
||||||
|
} else if (RSec != Obj.section_end())
|
||||||
|
SymAddr = RSec->getAddress();
|
||||||
|
|
||||||
|
// If we are given load addresses for the sections, we need to adjust:
|
||||||
|
// SymAddr = (Address of Symbol Or Section in File) -
|
||||||
|
// (Address of Section in File) +
|
||||||
|
// (Load Address of Section)
|
||||||
|
if (L != nullptr && RSec != Obj.section_end()) {
|
||||||
|
// RSec is now either the section being targetted or the section
|
||||||
|
// containing the symbol being targetted. In either case,
|
||||||
|
// we need to perform the same computation.
|
||||||
|
StringRef SecName;
|
||||||
|
RSec->getName(SecName);
|
||||||
|
SectionLoadAddress = L->getSectionLoadAddress(SecName);
|
||||||
|
if (SectionLoadAddress != 0)
|
||||||
|
SymAddr += SectionLoadAddress - RSec->getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
object::RelocVisitor V(Obj);
|
object::RelocVisitor V(Obj);
|
||||||
object::RelocToApply R(V.visit(Type, Reloc, SymAddr));
|
object::RelocToApply R(V.visit(Type, Reloc, SymAddr));
|
||||||
|
@ -34,6 +34,8 @@ public:
|
|||||||
getObjectForDebug(const ObjectFile &Obj) const override {
|
getObjectForDebug(const ObjectFile &Obj) const override {
|
||||||
return OwningBinary<ObjectFile>();
|
return OwningBinary<ObjectFile>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RuntimeDyld::LoadedObjectInfo *clone() const { return new LoadedCOFFObjectInfo(*this); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +112,8 @@ public:
|
|||||||
|
|
||||||
OwningBinary<ObjectFile>
|
OwningBinary<ObjectFile>
|
||||||
getObjectForDebug(const ObjectFile &Obj) const override;
|
getObjectForDebug(const ObjectFile &Obj) const override;
|
||||||
|
|
||||||
|
RuntimeDyld::LoadedObjectInfo *clone() const { return new LoadedELFObjectInfo(*this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ELFT>
|
template <typename ELFT>
|
||||||
|
@ -203,7 +203,7 @@ protected:
|
|||||||
SectionList Sections;
|
SectionList Sections;
|
||||||
|
|
||||||
typedef unsigned SID; // Type for SectionIDs
|
typedef unsigned SID; // Type for SectionIDs
|
||||||
#define RTDYLD_INVALID_SECTION_ID ((SID)(-1))
|
#define RTDYLD_INVALID_SECTION_ID ((RuntimeDyldImpl::SID)(-1))
|
||||||
|
|
||||||
// Keep a map of sections from object file to the SectionID which
|
// Keep a map of sections from object file to the SectionID which
|
||||||
// references it.
|
// references it.
|
||||||
|
@ -36,6 +36,8 @@ public:
|
|||||||
getObjectForDebug(const ObjectFile &Obj) const override {
|
getObjectForDebug(const ObjectFile &Obj) const override {
|
||||||
return OwningBinary<ObjectFile>();
|
return OwningBinary<ObjectFile>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RuntimeDyld::LoadedObjectInfo *clone() const { return new LoadedMachOObjectInfo(*this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -75,7 +77,7 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef(
|
|||||||
Value.Offset = RE.Addend;
|
Value.Offset = RE.Addend;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SectionRef Sec = Obj.getRelocationSection(RelInfo);
|
SectionRef Sec = Obj.getAnyRelocationSection(RelInfo);
|
||||||
bool IsCode = Sec.isText();
|
bool IsCode = Sec.isText();
|
||||||
Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID);
|
Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID);
|
||||||
uint64_t Addr = Sec.getAddress();
|
uint64_t Addr = Sec.getAddress();
|
||||||
|
@ -1044,6 +1044,19 @@ symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
|
|||||||
return symbol_iterator(SymbolRef(Ref, this));
|
return symbol_iterator(SymbolRef(Ref, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section_iterator COFFObjectFile::getRelocationSection(DataRefImpl Rel) const {
|
||||||
|
symbol_iterator Sym = getRelocationSymbol(Rel);
|
||||||
|
if (Sym == symbol_end())
|
||||||
|
return section_end();
|
||||||
|
COFFSymbolRef Symb = getCOFFSymbol(*Sym);
|
||||||
|
if (!Symb.isSection())
|
||||||
|
return section_end();
|
||||||
|
section_iterator Res(section_end());
|
||||||
|
if (getSymbolSection(Sym->getRawDataRefImpl(),Res))
|
||||||
|
return section_end();
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
|
std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
|
||||||
uint64_t &Res) const {
|
uint64_t &Res) const {
|
||||||
const coff_relocation* R = toRel(Rel);
|
const coff_relocation* R = toRel(Rel);
|
||||||
|
@ -710,6 +710,11 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
|
|||||||
return symbol_iterator(SymbolRef(Sym, this));
|
return symbol_iterator(SymbolRef(Sym, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section_iterator
|
||||||
|
MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
|
||||||
|
return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
|
||||||
|
}
|
||||||
|
|
||||||
std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
|
std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
|
||||||
uint64_t &Res) const {
|
uint64_t &Res) const {
|
||||||
MachO::any_relocation_info RE = getRelocation(Rel);
|
MachO::any_relocation_info RE = getRelocation(Rel);
|
||||||
@ -2224,7 +2229,7 @@ MachOObjectFile::getAnyRelocationType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
SectionRef
|
SectionRef
|
||||||
MachOObjectFile::getRelocationSection(
|
MachOObjectFile::getAnyRelocationSection(
|
||||||
const MachO::any_relocation_info &RE) const {
|
const MachO::any_relocation_info &RE) const {
|
||||||
if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
|
if (isRelocationScattered(RE) || getPlainRelocationExternal(RE))
|
||||||
return *section_end();
|
return *section_end();
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
RUN: llvm-rtdyld -printline %p/Inputs/test-inline.o \
|
RUN: llvm-rtdyld -printline %p/Inputs/test-inline.o \
|
||||||
RUN: | FileCheck %s -check-prefix TEST_INLINE
|
RUN: | FileCheck %s -check-prefix TEST_INLINE
|
||||||
|
RUN: llvm-rtdyld -printdebugline %p/Inputs/test-inline.o \
|
||||||
|
RUN: | FileCheck %s -check-prefix TEST_INLINE
|
||||||
RUN: llvm-rtdyld -printline %p/Inputs/test-parameters.o \
|
RUN: llvm-rtdyld -printline %p/Inputs/test-parameters.o \
|
||||||
RUN: | FileCheck %s -check-prefix TEST_PARAMETERS
|
RUN: | FileCheck %s -check-prefix TEST_PARAMETERS
|
||||||
|
RUN: llvm-rtdyld -printdebugline %p/Inputs/test-parameters.o \
|
||||||
|
RUN: | FileCheck %s -check-prefix TEST_PARAMETERS
|
||||||
|
|
||||||
; This test verifies that relocations are correctly applied to the
|
; This test verifies that relocations are correctly applied to the
|
||||||
; .debug_line section and exercises DIContext::getLineInfoForAddressRange().
|
; .debug_line section and exercises DIContext::getLineInfoForAddressRange().
|
||||||
|
@ -6484,7 +6484,7 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
|
auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
|
||||||
SectionRef RelocSection = Obj->getRelocationSection(RE);
|
SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
|
||||||
|
|
||||||
uint64_t SectionAddr = RelocSection.getAddress();
|
uint64_t SectionAddr = RelocSection.getAddress();
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ InputFileList(cl::Positional, cl::ZeroOrMore,
|
|||||||
enum ActionType {
|
enum ActionType {
|
||||||
AC_Execute,
|
AC_Execute,
|
||||||
AC_PrintLineInfo,
|
AC_PrintLineInfo,
|
||||||
|
AC_PrintDebugLineInfo,
|
||||||
AC_Verify
|
AC_Verify
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,6 +59,8 @@ Action(cl::desc("Action to perform:"),
|
|||||||
"Load, link, and execute the inputs."),
|
"Load, link, and execute the inputs."),
|
||||||
clEnumValN(AC_PrintLineInfo, "printline",
|
clEnumValN(AC_PrintLineInfo, "printline",
|
||||||
"Load, link, and print line information for each function."),
|
"Load, link, and print line information for each function."),
|
||||||
|
clEnumValN(AC_PrintDebugLineInfo, "printdebugline",
|
||||||
|
"Load, link, and print line information for each function using the debug object"),
|
||||||
clEnumValN(AC_Verify, "verify",
|
clEnumValN(AC_Verify, "verify",
|
||||||
"Load, link and verify the resulting memory image."),
|
"Load, link and verify the resulting memory image."),
|
||||||
clEnumValEnd));
|
clEnumValEnd));
|
||||||
@ -189,7 +192,9 @@ static void loadDylibs() {
|
|||||||
|
|
||||||
/* *** */
|
/* *** */
|
||||||
|
|
||||||
static int printLineInfoForInput() {
|
static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) {
|
||||||
|
assert(LoadObjects || !UseDebugObj);
|
||||||
|
|
||||||
// Load any dylibs requested on the command line.
|
// Load any dylibs requested on the command line.
|
||||||
loadDylibs();
|
loadDylibs();
|
||||||
|
|
||||||
@ -216,24 +221,32 @@ static int printLineInfoForInput() {
|
|||||||
|
|
||||||
ObjectFile &Obj = **MaybeObj;
|
ObjectFile &Obj = **MaybeObj;
|
||||||
|
|
||||||
// Load the object file
|
OwningBinary<ObjectFile> DebugObj;
|
||||||
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo =
|
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObjInfo = nullptr;
|
||||||
Dyld.loadObject(Obj);
|
ObjectFile *SymbolObj = &Obj;
|
||||||
|
if (LoadObjects) {
|
||||||
|
// Load the object file
|
||||||
|
LoadedObjInfo =
|
||||||
|
Dyld.loadObject(Obj);
|
||||||
|
|
||||||
if (Dyld.hasError())
|
if (Dyld.hasError())
|
||||||
return Error(Dyld.getErrorString());
|
return Error(Dyld.getErrorString());
|
||||||
|
|
||||||
// Resolve all the relocations we can.
|
// Resolve all the relocations we can.
|
||||||
Dyld.resolveRelocations();
|
Dyld.resolveRelocations();
|
||||||
|
|
||||||
OwningBinary<ObjectFile> DebugObj = LoadedObjInfo->getObjectForDebug(Obj);
|
if (UseDebugObj) {
|
||||||
|
DebugObj = LoadedObjInfo->getObjectForDebug(Obj);
|
||||||
|
SymbolObj = DebugObj.getBinary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<DIContext> Context(
|
std::unique_ptr<DIContext> Context(
|
||||||
new DWARFContextInMemory(*DebugObj.getBinary()));
|
new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get()));
|
||||||
|
|
||||||
// Use symbol info to iterate functions in the object.
|
// Use symbol info to iterate functions in the object.
|
||||||
for (object::symbol_iterator I = DebugObj.getBinary()->symbol_begin(),
|
for (object::symbol_iterator I = SymbolObj->symbol_begin(),
|
||||||
E = DebugObj.getBinary()->symbol_end();
|
E = SymbolObj->symbol_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
object::SymbolRef::Type SymType;
|
object::SymbolRef::Type SymType;
|
||||||
if (I->getType(SymType)) continue;
|
if (I->getType(SymType)) continue;
|
||||||
@ -245,7 +258,21 @@ static int printLineInfoForInput() {
|
|||||||
if (I->getAddress(Addr)) continue;
|
if (I->getAddress(Addr)) continue;
|
||||||
if (I->getSize(Size)) continue;
|
if (I->getSize(Size)) continue;
|
||||||
|
|
||||||
outs() << "Function: " << Name << ", Size = " << Size << "\n";
|
// If we're not using the debug object, compute the address of the
|
||||||
|
// symbol in memory (rather than that in the unrelocated object file)
|
||||||
|
// and use that to query the DWARFContext.
|
||||||
|
if (!UseDebugObj && LoadObjects) {
|
||||||
|
object::section_iterator Sec(SymbolObj->section_end());
|
||||||
|
I->getSection(Sec);
|
||||||
|
StringRef SecName;
|
||||||
|
Sec->getName(SecName);
|
||||||
|
uint64_t SectionLoadAddress =
|
||||||
|
LoadedObjInfo->getSectionLoadAddress(SecName);
|
||||||
|
if (SectionLoadAddress != 0)
|
||||||
|
Addr += SectionLoadAddress - Sec->getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
outs() << "Function: " << Name << ", Size = " << Size << ", Addr = " << Addr << "\n";
|
||||||
|
|
||||||
DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
|
DILineInfoTable Lines = Context->getLineInfoForAddressRange(Addr, Size);
|
||||||
DILineInfoTable::iterator Begin = Lines.begin();
|
DILineInfoTable::iterator Begin = Lines.begin();
|
||||||
@ -594,8 +621,10 @@ int main(int argc, char **argv) {
|
|||||||
switch (Action) {
|
switch (Action) {
|
||||||
case AC_Execute:
|
case AC_Execute:
|
||||||
return executeInput();
|
return executeInput();
|
||||||
|
case AC_PrintDebugLineInfo:
|
||||||
|
return printLineInfoForInput(true,true);
|
||||||
case AC_PrintLineInfo:
|
case AC_PrintLineInfo:
|
||||||
return printLineInfoForInput();
|
return printLineInfoForInput(true,false);
|
||||||
case AC_Verify:
|
case AC_Verify:
|
||||||
return linkAndVerify();
|
return linkAndVerify();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user