mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
[MCJIT] Refactor and add stub inspection to the RuntimeDyldChecker framework.
This patch introduces a 'stub_addr' builtin that can be used to find the address of the stub for a given (<file>, <section>, <symbol>) tuple. This address can be used both to verify the contents of stubs (by loading from the returned address) and to verify references to stubs (by comparing against the returned address). Example (1) - Verifying stub contents: Load 8 bytes (assuming a 64-bit target) from the stub for 'x' in the __text section of f.o, and compare that value against the addres of 'x'. # rtdyld-check: *{8}(stub_addr(f.o, __text, x) = x Example (2) - Verifying references to stubs: Decode the immediate of the instruction at label 'l', and verify that it's equal to the offset from the next instruction's PC to the stub for 'y' in the __text section of f.o (i.e. it's the correct PC-rel difference). # rtdyld-check: decode_operand(l, 4) = stub_addr(f.o, __text, y) - next_pc(l) l: movq y@GOTPCREL(%rip), %rax Since stub inspection requires cooperation with RuntimeDyldImpl this patch pimpl-ifies RuntimeDyldChecker. Its implementation is moved in to a new class, RuntimeDyldCheckerImpl, that has access to the definition of RuntimeDyldImpl. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213698 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -46,6 +46,9 @@ public:
|
|||||||
const char *getBufferStart() const { return Buffer->getBufferStart(); }
|
const char *getBufferStart() const { return Buffer->getBufferStart(); }
|
||||||
size_t getBufferSize() const { return Buffer->getBufferSize(); }
|
size_t getBufferSize() const { return Buffer->getBufferSize(); }
|
||||||
StringRef getBuffer() const { return Buffer->getBuffer(); }
|
StringRef getBuffer() const { return Buffer->getBuffer(); }
|
||||||
|
StringRef getBufferIdentifier() const {
|
||||||
|
return Buffer->getBufferIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// The memory contained in an ObjectBuffer
|
// The memory contained in an ObjectBuffer
|
||||||
|
@@ -50,6 +50,11 @@ public:
|
|||||||
|
|
||||||
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
|
virtual /* Triple::ArchType */ unsigned getArch() const = 0;
|
||||||
|
|
||||||
|
// Return the name associated with this ObjectImage.
|
||||||
|
// This is usually the name of the file or MemoryBuffer that the the
|
||||||
|
// ObjectBuffer was constructed from.
|
||||||
|
StringRef getImageName() const { return Buffer->getBufferIdentifier(); }
|
||||||
|
|
||||||
// Subclasses can override these methods to update the image with loaded
|
// Subclasses can override these methods to update the image with loaded
|
||||||
// addresses for sections and common symbols
|
// addresses for sections and common symbols
|
||||||
virtual void updateSectionAddress(const object::SectionRef &Sec,
|
virtual void updateSectionAddress(const object::SectionRef &Sec,
|
||||||
|
@@ -26,10 +26,11 @@ namespace object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class RuntimeDyldImpl;
|
class RuntimeDyldImpl;
|
||||||
|
class RuntimeDyldCheckerImpl;
|
||||||
class ObjectImage;
|
class ObjectImage;
|
||||||
|
|
||||||
class RuntimeDyld {
|
class RuntimeDyld {
|
||||||
friend class RuntimeDyldChecker;
|
friend class RuntimeDyldCheckerImpl;
|
||||||
|
|
||||||
RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
|
RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
|
||||||
void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
|
void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION;
|
||||||
@@ -39,6 +40,7 @@ class RuntimeDyld {
|
|||||||
RuntimeDyldImpl *Dyld;
|
RuntimeDyldImpl *Dyld;
|
||||||
RTDyldMemoryManager *MM;
|
RTDyldMemoryManager *MM;
|
||||||
bool ProcessAllSections;
|
bool ProcessAllSections;
|
||||||
|
RuntimeDyldCheckerImpl *Checker;
|
||||||
protected:
|
protected:
|
||||||
// Change the address associated with a section when resolving relocations.
|
// Change the address associated with a section when resolving relocations.
|
||||||
// Any relocations already associated with the symbol will be re-resolved.
|
// Any relocations already associated with the symbol will be re-resolved.
|
||||||
|
@@ -10,15 +10,16 @@
|
|||||||
#ifndef LLVM_RUNTIMEDYLDCHECKER_H
|
#ifndef LLVM_RUNTIMEDYLDCHECKER_H
|
||||||
#define LLVM_RUNTIMEDYLDCHECKER_H
|
#define LLVM_RUNTIMEDYLDCHECKER_H
|
||||||
|
|
||||||
#include "RuntimeDyld.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/Support/Debug.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class MCDisassembler;
|
class MCDisassembler;
|
||||||
|
class MemoryBuffer;
|
||||||
class MCInstPrinter;
|
class MCInstPrinter;
|
||||||
|
class RuntimeDyld;
|
||||||
|
class RuntimeDyldCheckerImpl;
|
||||||
|
class raw_ostream;
|
||||||
|
|
||||||
/// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has
|
/// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has
|
||||||
/// correctly applied relocations.
|
/// correctly applied relocations.
|
||||||
@@ -61,14 +62,10 @@ class MCInstPrinter;
|
|||||||
/// | expr '>>' expr
|
/// | expr '>>' expr
|
||||||
///
|
///
|
||||||
class RuntimeDyldChecker {
|
class RuntimeDyldChecker {
|
||||||
friend class RuntimeDyldCheckerExprEval;
|
|
||||||
public:
|
public:
|
||||||
RuntimeDyldChecker(RuntimeDyld &RTDyld,
|
RuntimeDyldChecker(RuntimeDyld &RTDyld, MCDisassembler *Disassembler,
|
||||||
MCDisassembler *Disassembler,
|
MCInstPrinter *InstPrinter, raw_ostream &ErrStream);
|
||||||
MCInstPrinter *InstPrinter,
|
~RuntimeDyldChecker();
|
||||||
llvm::raw_ostream &ErrStream)
|
|
||||||
: RTDyld(*RTDyld.Dyld), Disassembler(Disassembler),
|
|
||||||
InstPrinter(InstPrinter), ErrStream(ErrStream) {}
|
|
||||||
|
|
||||||
/// \brief Check a single expression against the attached RuntimeDyld
|
/// \brief Check a single expression against the attached RuntimeDyld
|
||||||
/// instance.
|
/// instance.
|
||||||
@@ -80,17 +77,7 @@ public:
|
|||||||
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
|
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::unique_ptr<RuntimeDyldCheckerImpl> Impl;
|
||||||
bool isSymbolValid(StringRef Symbol) const;
|
|
||||||
uint64_t getSymbolAddress(StringRef Symbol) const;
|
|
||||||
uint64_t readMemoryAtSymbol(StringRef Symbol, int64_t Offset,
|
|
||||||
unsigned Size) const;
|
|
||||||
StringRef getSubsectionStartingAt(StringRef Name) const;
|
|
||||||
|
|
||||||
RuntimeDyldImpl &RTDyld;
|
|
||||||
MCDisassembler *Disassembler;
|
|
||||||
MCInstPrinter *InstPrinter;
|
|
||||||
llvm::raw_ostream &ErrStream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
#include "JITRegistrar.h"
|
#include "JITRegistrar.h"
|
||||||
#include "ObjectImageCommon.h"
|
#include "ObjectImageCommon.h"
|
||||||
|
#include "RuntimeDyldCheckerImpl.h"
|
||||||
#include "RuntimeDyldELF.h"
|
#include "RuntimeDyldELF.h"
|
||||||
#include "RuntimeDyldImpl.h"
|
#include "RuntimeDyldImpl.h"
|
||||||
#include "RuntimeDyldMachO.h"
|
#include "RuntimeDyldMachO.h"
|
||||||
@@ -204,6 +205,13 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) {
|
|||||||
for (; I != E;)
|
for (; I != E;)
|
||||||
I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols,
|
I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols,
|
||||||
Stubs);
|
Stubs);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// If there is an attached checker, notify it about the stubs for this
|
||||||
|
// section so that they can be verified.
|
||||||
|
if (Checker)
|
||||||
|
Checker->registerStubMap(Obj->getImageName(), SectionID, Stubs);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give the subclasses a chance to tie-up any loose ends.
|
// Give the subclasses a chance to tie-up any loose ends.
|
||||||
@@ -695,22 +703,26 @@ RuntimeDyld::RuntimeDyld(RTDyldMemoryManager *mm) {
|
|||||||
Dyld = nullptr;
|
Dyld = nullptr;
|
||||||
MM = mm;
|
MM = mm;
|
||||||
ProcessAllSections = false;
|
ProcessAllSections = false;
|
||||||
|
Checker = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeDyld::~RuntimeDyld() { delete Dyld; }
|
RuntimeDyld::~RuntimeDyld() { delete Dyld; }
|
||||||
|
|
||||||
static std::unique_ptr<RuntimeDyldELF>
|
static std::unique_ptr<RuntimeDyldELF>
|
||||||
createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections) {
|
createRuntimeDyldELF(RTDyldMemoryManager *MM, bool ProcessAllSections,
|
||||||
|
RuntimeDyldCheckerImpl *Checker) {
|
||||||
std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM));
|
std::unique_ptr<RuntimeDyldELF> Dyld(new RuntimeDyldELF(MM));
|
||||||
Dyld->setProcessAllSections(ProcessAllSections);
|
Dyld->setProcessAllSections(ProcessAllSections);
|
||||||
|
Dyld->setRuntimeDyldChecker(Checker);
|
||||||
return Dyld;
|
return Dyld;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unique_ptr<RuntimeDyldMachO>
|
static std::unique_ptr<RuntimeDyldMachO>
|
||||||
createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM,
|
createRuntimeDyldMachO(Triple::ArchType Arch, RTDyldMemoryManager *MM,
|
||||||
bool ProcessAllSections) {
|
bool ProcessAllSections, RuntimeDyldCheckerImpl *Checker) {
|
||||||
std::unique_ptr<RuntimeDyldMachO> Dyld(RuntimeDyldMachO::create(Arch, MM));
|
std::unique_ptr<RuntimeDyldMachO> Dyld(RuntimeDyldMachO::create(Arch, MM));
|
||||||
Dyld->setProcessAllSections(ProcessAllSections);
|
Dyld->setProcessAllSections(ProcessAllSections);
|
||||||
|
Dyld->setRuntimeDyldChecker(Checker);
|
||||||
return Dyld;
|
return Dyld;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -722,13 +734,13 @@ ObjectImage *RuntimeDyld::loadObject(std::unique_ptr<ObjectFile> InputObject) {
|
|||||||
if (InputObject->isELF()) {
|
if (InputObject->isELF()) {
|
||||||
InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(std::move(InputObject)));
|
InputImage.reset(RuntimeDyldELF::createObjectImageFromFile(std::move(InputObject)));
|
||||||
if (!Dyld)
|
if (!Dyld)
|
||||||
Dyld = createRuntimeDyldELF(MM, ProcessAllSections).release();
|
Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker).release();
|
||||||
} else if (InputObject->isMachO()) {
|
} else if (InputObject->isMachO()) {
|
||||||
InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(std::move(InputObject)));
|
InputImage.reset(RuntimeDyldMachO::createObjectImageFromFile(std::move(InputObject)));
|
||||||
if (!Dyld)
|
if (!Dyld)
|
||||||
Dyld = createRuntimeDyldMachO(
|
Dyld = createRuntimeDyldMachO(
|
||||||
static_cast<Triple::ArchType>(InputImage->getArch()),
|
static_cast<Triple::ArchType>(InputImage->getArch()),
|
||||||
MM, ProcessAllSections).release();
|
MM, ProcessAllSections, Checker).release();
|
||||||
} else
|
} else
|
||||||
report_fatal_error("Incompatible object format!");
|
report_fatal_error("Incompatible object format!");
|
||||||
|
|
||||||
@@ -750,7 +762,7 @@ ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) {
|
|||||||
case sys::fs::file_magic::elf_core:
|
case sys::fs::file_magic::elf_core:
|
||||||
InputImage.reset(RuntimeDyldELF::createObjectImage(InputBuffer));
|
InputImage.reset(RuntimeDyldELF::createObjectImage(InputBuffer));
|
||||||
if (!Dyld)
|
if (!Dyld)
|
||||||
Dyld = createRuntimeDyldELF(MM, ProcessAllSections).release();
|
Dyld = createRuntimeDyldELF(MM, ProcessAllSections, Checker).release();
|
||||||
break;
|
break;
|
||||||
case sys::fs::file_magic::macho_object:
|
case sys::fs::file_magic::macho_object:
|
||||||
case sys::fs::file_magic::macho_executable:
|
case sys::fs::file_magic::macho_executable:
|
||||||
@@ -766,7 +778,7 @@ ObjectImage *RuntimeDyld::loadObject(ObjectBuffer *InputBuffer) {
|
|||||||
if (!Dyld)
|
if (!Dyld)
|
||||||
Dyld = createRuntimeDyldMachO(
|
Dyld = createRuntimeDyldMachO(
|
||||||
static_cast<Triple::ArchType>(InputImage->getArch()),
|
static_cast<Triple::ArchType>(InputImage->getArch()),
|
||||||
MM, ProcessAllSections).release();
|
MM, ProcessAllSections, Checker).release();
|
||||||
break;
|
break;
|
||||||
case sys::fs::file_magic::unknown:
|
case sys::fs::file_magic::unknown:
|
||||||
case sys::fs::file_magic::bitcode:
|
case sys::fs::file_magic::bitcode:
|
||||||
|
File diff suppressed because it is too large
Load Diff
60
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
Normal file
60
lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
//===-- RuntimeDyldCheckerImpl.h -- RuntimeDyld test framework --*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_RUNTIMEDYLDCHECKERIMPL_H
|
||||||
|
#define LLVM_RUNTIMEDYLDCHECKERIMPL_H
|
||||||
|
|
||||||
|
#include "RuntimeDyldImpl.h"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class RuntimeDyldCheckerImpl {
|
||||||
|
friend class RuntimeDyldImpl;
|
||||||
|
friend class RuntimeDyldCheckerExprEval;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, MCDisassembler *Disassembler,
|
||||||
|
MCInstPrinter *InstPrinter,
|
||||||
|
llvm::raw_ostream &ErrStream);
|
||||||
|
|
||||||
|
bool check(StringRef CheckExpr) const;
|
||||||
|
bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RuntimeDyldImpl &getRTDyld() const { return *RTDyld.Dyld; }
|
||||||
|
|
||||||
|
bool isSymbolValid(StringRef Symbol) const;
|
||||||
|
uint64_t getSymbolLinkerAddr(StringRef Symbol) const;
|
||||||
|
uint64_t getSymbolRemoteAddr(StringRef Symbol) const;
|
||||||
|
uint64_t readMemoryAtAddr(uint64_t Addr, unsigned Size) const;
|
||||||
|
std::pair<uint64_t, std::string> getStubAddrFor(StringRef FileName,
|
||||||
|
StringRef SectionName,
|
||||||
|
StringRef Symbol,
|
||||||
|
bool IsInsideLoad) const;
|
||||||
|
StringRef getSubsectionStartingAt(StringRef Name) const;
|
||||||
|
|
||||||
|
void registerStubMap(StringRef FileName, unsigned SectionID,
|
||||||
|
const RuntimeDyldImpl::StubMap &RTDyldStubs);
|
||||||
|
|
||||||
|
RuntimeDyld &RTDyld;
|
||||||
|
MCDisassembler *Disassembler;
|
||||||
|
MCInstPrinter *InstPrinter;
|
||||||
|
llvm::raw_ostream &ErrStream;
|
||||||
|
|
||||||
|
// StubMap typedefs.
|
||||||
|
typedef std::pair<unsigned, uint64_t> StubLoc;
|
||||||
|
typedef std::map<std::string, StubLoc> SymbolStubMap;
|
||||||
|
typedef std::map<std::string, SymbolStubMap> SectionStubMap;
|
||||||
|
typedef std::map<std::string, SectionStubMap> StubMap;
|
||||||
|
StubMap Stubs;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // LLVM_RUNTIMEDYLDCHECKERIMPL_H
|
@@ -159,7 +159,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class RuntimeDyldImpl {
|
class RuntimeDyldImpl {
|
||||||
friend class RuntimeDyldChecker;
|
friend class RuntimeDyldCheckerImpl;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint64_t getAnySymbolRemoteAddress(StringRef Symbol) {
|
uint64_t getAnySymbolRemoteAddress(StringRef Symbol) {
|
||||||
@@ -172,6 +172,9 @@ protected:
|
|||||||
// The MemoryManager to load objects into.
|
// The MemoryManager to load objects into.
|
||||||
RTDyldMemoryManager *MemMgr;
|
RTDyldMemoryManager *MemMgr;
|
||||||
|
|
||||||
|
// Attached RuntimeDyldChecker instance. Null if no instance attached.
|
||||||
|
RuntimeDyldCheckerImpl *Checker;
|
||||||
|
|
||||||
// A list of all sections emitted by the dynamic linker. These sections are
|
// A list of all sections emitted by the dynamic linker. These sections are
|
||||||
// referenced in the code by means of their index in this list - SectionID.
|
// referenced in the code by means of their index in this list - SectionID.
|
||||||
typedef SmallVector<SectionEntry, 64> SectionList;
|
typedef SmallVector<SectionEntry, 64> SectionList;
|
||||||
@@ -211,6 +214,7 @@ protected:
|
|||||||
// modules. This map is indexed by symbol name.
|
// modules. This map is indexed by symbol name.
|
||||||
StringMap<RelocationList> ExternalSymbolRelocations;
|
StringMap<RelocationList> ExternalSymbolRelocations;
|
||||||
|
|
||||||
|
|
||||||
typedef std::map<RelocationValueRef, uintptr_t> StubMap;
|
typedef std::map<RelocationValueRef, uintptr_t> StubMap;
|
||||||
|
|
||||||
Triple::ArchType Arch;
|
Triple::ArchType Arch;
|
||||||
@@ -349,7 +353,7 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
RuntimeDyldImpl(RTDyldMemoryManager *mm)
|
RuntimeDyldImpl(RTDyldMemoryManager *mm)
|
||||||
: MemMgr(mm), ProcessAllSections(false), HasError(false) {
|
: MemMgr(mm), Checker(nullptr), ProcessAllSections(false), HasError(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~RuntimeDyldImpl();
|
virtual ~RuntimeDyldImpl();
|
||||||
@@ -358,6 +362,10 @@ public:
|
|||||||
this->ProcessAllSections = ProcessAllSections;
|
this->ProcessAllSections = ProcessAllSections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setRuntimeDyldChecker(RuntimeDyldCheckerImpl *Checker) {
|
||||||
|
this->Checker = Checker;
|
||||||
|
}
|
||||||
|
|
||||||
ObjectImage *loadObject(ObjectImage *InputObject);
|
ObjectImage *loadObject(ObjectImage *InputObject);
|
||||||
|
|
||||||
uint8_t* getSymbolAddress(StringRef Name) {
|
uint8_t* getSymbolAddress(StringRef Name) {
|
||||||
|
@@ -37,6 +37,7 @@ protected:
|
|||||||
: EHFrameSID(RTDYLD_INVALID_SECTION_ID),
|
: EHFrameSID(RTDYLD_INVALID_SECTION_ID),
|
||||||
TextSID(RTDYLD_INVALID_SECTION_ID),
|
TextSID(RTDYLD_INVALID_SECTION_ID),
|
||||||
ExceptTabSID(RTDYLD_INVALID_SECTION_ID) {}
|
ExceptTabSID(RTDYLD_INVALID_SECTION_ID) {}
|
||||||
|
|
||||||
EHFrameRelatedSections(SID EH, SID T, SID Ex)
|
EHFrameRelatedSections(SID EH, SID T, SID Ex)
|
||||||
: EHFrameSID(EH), TextSID(T), ExceptTabSID(Ex) {}
|
: EHFrameSID(EH), TextSID(T), ExceptTabSID(Ex) {}
|
||||||
SID EHFrameSID;
|
SID EHFrameSID;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -relocation-model=pic -filetype=obj -o %t.o %s
|
# RUN: llvm-mc -triple=x86_64-apple-macosx10.9 -relocation-model=pic -filetype=obj -o %T/foo.o %s
|
||||||
# RUN: llvm-rtdyld -triple=x86_64-apple-macosx10.9 -verify -check=%s %t.o
|
# RUN: sed "s,<filename>,%T/foo.o,g" %s > %T/foo.s
|
||||||
# RUN: rm %t.o
|
# RUN: llvm-rtdyld -triple=x86_64-apple-macosx10.9 -verify -check=%T/foo.s %T/foo.o
|
||||||
|
|
||||||
.section __TEXT,__text,regular,pure_instructions
|
.section __TEXT,__text,regular,pure_instructions
|
||||||
.globl foo
|
.globl foo
|
||||||
@@ -20,9 +20,20 @@ insn1:
|
|||||||
# rtdyld-check: decode_operand(insn2, 4) = x - next_pc(insn2)
|
# rtdyld-check: decode_operand(insn2, 4) = x - next_pc(insn2)
|
||||||
insn2:
|
insn2:
|
||||||
movl x(%rip), %eax
|
movl x(%rip), %eax
|
||||||
movl $0, %eax
|
|
||||||
|
# Test PC-rel GOT relocation.
|
||||||
|
# Verify both the contents of the GOT entry for y, and that the movq instruction
|
||||||
|
# references the correct GOT entry address:
|
||||||
|
# rtdyld-check: *{8}(stub_addr(<filename>, __text, y)) = y
|
||||||
|
# rtdyld-check: decode_operand(insn3, 4) = stub_addr(<filename>, __text, y) - next_pc(insn3)
|
||||||
|
insn3:
|
||||||
|
movq y@GOTPCREL(%rip), %rax
|
||||||
|
|
||||||
|
movl $0, %eax
|
||||||
retq
|
retq
|
||||||
|
|
||||||
|
.comm y,4,2
|
||||||
|
|
||||||
.section __DATA,__data
|
.section __DATA,__data
|
||||||
.globl x
|
.globl x
|
||||||
.align 2
|
.align 2
|
||||||
|
@@ -347,6 +347,8 @@ static int linkAndVerify() {
|
|||||||
// Instantiate a dynamic linker.
|
// Instantiate a dynamic linker.
|
||||||
TrivialMemoryManager MemMgr;
|
TrivialMemoryManager MemMgr;
|
||||||
RuntimeDyld Dyld(&MemMgr);
|
RuntimeDyld Dyld(&MemMgr);
|
||||||
|
RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(),
|
||||||
|
llvm::dbgs());
|
||||||
|
|
||||||
// If we don't have any input files, read from stdin.
|
// If we don't have any input files, read from stdin.
|
||||||
if (!InputFileList.size())
|
if (!InputFileList.size())
|
||||||
@@ -370,8 +372,6 @@ static int linkAndVerify() {
|
|||||||
// Resolve all the relocations we can.
|
// Resolve all the relocations we can.
|
||||||
Dyld.resolveRelocations();
|
Dyld.resolveRelocations();
|
||||||
|
|
||||||
RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(),
|
|
||||||
llvm::dbgs());
|
|
||||||
return checkAllExpressions(Checker);
|
return checkAllExpressions(Checker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user