forked from OSchip/llvm-project
Move GOTPass and StubsPass from Core to MachO
llvm-svn: 212652
This commit is contained in:
parent
79d4ffbc8f
commit
0edfdeb0be
|
@ -18,7 +18,6 @@
|
|||
#include <vector>
|
||||
|
||||
namespace lld {
|
||||
class DefinedAtom;
|
||||
class MutableFile;
|
||||
|
||||
/// Once the core linking is done (which resolves references, coalesces atoms
|
||||
|
@ -43,79 +42,6 @@ protected:
|
|||
Pass() { }
|
||||
};
|
||||
|
||||
/// Pass for adding stubs (PLT entries) for calls to functions
|
||||
/// outside the linkage unit. This class is subclassed by each
|
||||
/// file format Writer which implements the pure virtual methods.
|
||||
class StubsPass : public Pass {
|
||||
public:
|
||||
StubsPass() : Pass() {}
|
||||
|
||||
/// Scans all Atoms looking for call-site uses of SharedLibraryAtoms
|
||||
/// and transfroms the call-site to call a stub instead using the
|
||||
/// helper methods below.
|
||||
void perform(std::unique_ptr<MutableFile> &mergedFile) override;
|
||||
|
||||
/// If true, the pass should use stubs for references
|
||||
/// to shared library symbols. If false, the pass
|
||||
/// will generate relocations on the text segment which the
|
||||
/// runtime loader will use to patch the program at runtime.
|
||||
virtual bool noTextRelocs() = 0;
|
||||
|
||||
/// Returns whether the Reference kind is for a call site. The pass
|
||||
/// uses this to find calls that need to be indirected through a stub.
|
||||
virtual bool isCallSite(const Reference &) = 0;
|
||||
|
||||
/// Returns a file format specific atom for a stub/PLT entry which contains
|
||||
/// instructions which jump to the specified atom. May be called multiple
|
||||
/// times for the same target atom, in which case this method should return
|
||||
/// the same stub atom.
|
||||
virtual const DefinedAtom *getStub(const Atom &target) = 0;
|
||||
|
||||
/// After the default implementation of perform() is done calling getStub(),
|
||||
/// it will call this method to add all the stub (and support) atoms to the
|
||||
/// master file object.
|
||||
virtual void addStubAtoms(MutableFile &masterFile) = 0;
|
||||
|
||||
private:
|
||||
void replaceCalleeWithStub(const Atom *target, const Reference *ref);
|
||||
};
|
||||
|
||||
/// Pass for adding GOT entries for pointers to functions/data
|
||||
/// outside the linkage unit. This class is subclassed by each
|
||||
/// file format Writer which implements the pure virtual methods.
|
||||
class GOTPass : public Pass {
|
||||
public:
|
||||
GOTPass() : Pass() {}
|
||||
|
||||
/// Scans all Atoms looking for pointer to SharedLibraryAtoms
|
||||
/// and transfroms them to a pointer to a GOT entry using the
|
||||
/// helper methods below.
|
||||
void perform(std::unique_ptr<MutableFile> &mergedFile) override;
|
||||
|
||||
/// If true, the pass will use GOT entries for references
|
||||
/// to shared library symbols. If false, the pass
|
||||
/// will generate relocations on the text segment which the
|
||||
/// runtime loader will use to patch the program at runtime.
|
||||
virtual bool noTextRelocs() = 0;
|
||||
|
||||
/// Returns whether the Reference kind is a pre-instantiated GOT access.
|
||||
/// The default implementation of perform() uses this to figure out
|
||||
/// what GOT entries to instantiate.
|
||||
virtual bool isGOTAccess(const Reference &, bool &canBypassGOT) = 0;
|
||||
|
||||
/// The file format Writer needs to alter the reference kind from a
|
||||
/// pre-instantiated GOT access to an actual access. If targetIsNowGOT is
|
||||
/// true, the pass has instantiated a GOT atom and altered the reference's
|
||||
/// target to point to that atom. If targetIsNowGOT is false, the pass
|
||||
/// determined a GOT entry is not needed because the reference site can
|
||||
/// directly access the target.
|
||||
virtual void updateReferenceToGOT(const Reference*, bool targetIsNowGOT) = 0;
|
||||
|
||||
/// Returns a file format specific atom for a GOT entry targeting
|
||||
/// the specified atom.
|
||||
virtual const DefinedAtom *makeGOTEntry(const Atom &target) = 0;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
#endif // LLD_CORE_PASS_H
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
add_lld_library(lldPasses
|
||||
GOTPass.cpp
|
||||
StubsPass.cpp
|
||||
LayoutPass.cpp
|
||||
RoundTripNativePass.cpp
|
||||
RoundTripYAMLPass.cpp
|
||||
|
|
|
@ -184,67 +184,6 @@ private:
|
|||
};
|
||||
|
||||
|
||||
class TestingStubsPass : public StubsPass {
|
||||
public:
|
||||
TestingStubsPass(const LinkingContext &ctx) : _file(ctx) {}
|
||||
|
||||
bool noTextRelocs() override { return true; }
|
||||
|
||||
bool isCallSite(const Reference &ref) override {
|
||||
if (ref.kindNamespace() != Reference::KindNamespace::testing)
|
||||
return false;
|
||||
return (ref.kindValue() == CoreLinkingContext::TEST_RELOC_CALL32);
|
||||
}
|
||||
|
||||
const DefinedAtom *getStub(const Atom &target) override {
|
||||
const DefinedAtom *result = new TestingStubAtom(_file, target);
|
||||
_file.addAtom(*result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void addStubAtoms(MutableFile &mergedFile) override {
|
||||
for (const DefinedAtom *stub : _file.defined()) {
|
||||
mergedFile.addAtom(*stub);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TestingPassFile _file;
|
||||
};
|
||||
|
||||
class TestingGOTPass : public GOTPass {
|
||||
public:
|
||||
TestingGOTPass(const LinkingContext &ctx) : _file(ctx) {}
|
||||
|
||||
bool noTextRelocs() override { return true; }
|
||||
|
||||
bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override {
|
||||
if (ref.kindNamespace() != Reference::KindNamespace::testing)
|
||||
return false;
|
||||
switch (ref.kindValue()) {
|
||||
case CoreLinkingContext::TEST_RELOC_GOT_LOAD32:
|
||||
canBypassGOT = true;
|
||||
return true;
|
||||
case CoreLinkingContext::TEST_RELOC_GOT_USE32:
|
||||
canBypassGOT = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) override {
|
||||
const_cast<Reference *>(ref)->setKindValue(
|
||||
targetIsNowGOT ? CoreLinkingContext::TEST_RELOC_PCREL32
|
||||
: CoreLinkingContext::TEST_RELOC_LEA32_WAS_GOT);
|
||||
}
|
||||
|
||||
const DefinedAtom *makeGOTEntry(const Atom &target) override {
|
||||
return new TestingGOTAtom(_file, target);
|
||||
}
|
||||
|
||||
private:
|
||||
TestingPassFile _file;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -259,10 +198,6 @@ void CoreLinkingContext::addPasses(PassManager &pm) {
|
|||
for (StringRef name : _passNames) {
|
||||
if (name.equals("layout"))
|
||||
pm.add(std::unique_ptr<Pass>(new LayoutPass(registry())));
|
||||
else if (name.equals("GOT"))
|
||||
pm.add(std::unique_ptr<Pass>(new TestingGOTPass(*this)));
|
||||
else if (name.equals("stubs"))
|
||||
pm.add(std::unique_ptr<Pass>(new TestingStubsPass(*this)));
|
||||
else
|
||||
llvm_unreachable("bad pass name");
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
add_lld_library(lldMachO
|
||||
GOTPass.cpp
|
||||
MachOLinkingContext.cpp
|
||||
MachONormalizedFileBinaryReader.cpp
|
||||
MachONormalizedFileBinaryWriter.cpp
|
||||
|
@ -6,6 +7,7 @@ add_lld_library(lldMachO
|
|||
MachONormalizedFileToAtoms.cpp
|
||||
MachONormalizedFileYAML.cpp
|
||||
ReferenceKinds.cpp
|
||||
StubsPass.cpp
|
||||
WriterMachO.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===- Passes/GOTPass.cpp - Adds GOT entries ------------------------------===//
|
||||
//===- lib/ReaderWriter/MachO/GOTPass.cpp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
|
@ -35,10 +35,11 @@
|
|||
#include "lld/Core/DefinedAtom.h"
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/Pass.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
#include "MachOPasses.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
static bool shouldReplaceTargetWithGOTAtom(const Atom *target,
|
|
@ -16,6 +16,7 @@
|
|||
#include "lld/Core/Reference.h"
|
||||
#include "lld/Core/Pass.h"
|
||||
|
||||
#include "MachOPasses.h"
|
||||
#include "ReferenceKinds.h"
|
||||
#include "StubAtoms.hpp"
|
||||
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
//===- lib/ReaderWriter/MachO/MachOPasses.h -------------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_READER_WRITER_MACHO_PASSES_H
|
||||
#define LLD_READER_WRITER_MACHO_PASSES_H
|
||||
|
||||
#include "lld/Core/Atom.h"
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/Pass.h"
|
||||
#include "lld/Core/range.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace lld {
|
||||
class DefinedAtom;
|
||||
class MutableFile;
|
||||
|
||||
|
||||
/// Pass for adding stubs (PLT entries) for calls to functions
|
||||
/// outside the linkage unit. This class is subclassed by each
|
||||
/// file format Writer which implements the pure virtual methods.
|
||||
class StubsPass : public Pass {
|
||||
public:
|
||||
StubsPass() : Pass() {}
|
||||
|
||||
/// Scans all Atoms looking for call-site uses of SharedLibraryAtoms
|
||||
/// and transfroms the call-site to call a stub instead using the
|
||||
/// helper methods below.
|
||||
void perform(std::unique_ptr<MutableFile> &mergedFile) override;
|
||||
|
||||
/// If true, the pass should use stubs for references
|
||||
/// to shared library symbols. If false, the pass
|
||||
/// will generate relocations on the text segment which the
|
||||
/// runtime loader will use to patch the program at runtime.
|
||||
virtual bool noTextRelocs() = 0;
|
||||
|
||||
/// Returns whether the Reference kind is for a call site. The pass
|
||||
/// uses this to find calls that need to be indirected through a stub.
|
||||
virtual bool isCallSite(const Reference &) = 0;
|
||||
|
||||
/// Returns a file format specific atom for a stub/PLT entry which contains
|
||||
/// instructions which jump to the specified atom. May be called multiple
|
||||
/// times for the same target atom, in which case this method should return
|
||||
/// the same stub atom.
|
||||
virtual const DefinedAtom *getStub(const Atom &target) = 0;
|
||||
|
||||
/// After the default implementation of perform() is done calling getStub(),
|
||||
/// it will call this method to add all the stub (and support) atoms to the
|
||||
/// master file object.
|
||||
virtual void addStubAtoms(MutableFile &masterFile) = 0;
|
||||
|
||||
private:
|
||||
void replaceCalleeWithStub(const Atom *target, const Reference *ref);
|
||||
};
|
||||
|
||||
/// Pass for adding GOT entries for pointers to functions/data
|
||||
/// outside the linkage unit. This class is subclassed by each
|
||||
/// file format Writer which implements the pure virtual methods.
|
||||
class GOTPass : public Pass {
|
||||
public:
|
||||
GOTPass() : Pass() {}
|
||||
|
||||
/// Scans all Atoms looking for pointer to SharedLibraryAtoms
|
||||
/// and transfroms them to a pointer to a GOT entry using the
|
||||
/// helper methods below.
|
||||
void perform(std::unique_ptr<MutableFile> &mergedFile) override;
|
||||
|
||||
/// If true, the pass will use GOT entries for references
|
||||
/// to shared library symbols. If false, the pass
|
||||
/// will generate relocations on the text segment which the
|
||||
/// runtime loader will use to patch the program at runtime.
|
||||
virtual bool noTextRelocs() = 0;
|
||||
|
||||
/// Returns whether the Reference kind is a pre-instantiated GOT access.
|
||||
/// The default implementation of perform() uses this to figure out
|
||||
/// what GOT entries to instantiate.
|
||||
virtual bool isGOTAccess(const Reference &, bool &canBypassGOT) = 0;
|
||||
|
||||
/// The file format Writer needs to alter the reference kind from a
|
||||
/// pre-instantiated GOT access to an actual access. If targetIsNowGOT is
|
||||
/// true, the pass has instantiated a GOT atom and altered the reference's
|
||||
/// target to point to that atom. If targetIsNowGOT is false, the pass
|
||||
/// determined a GOT entry is not needed because the reference site can
|
||||
/// directly access the target.
|
||||
virtual void updateReferenceToGOT(const Reference*, bool targetIsNowGOT) = 0;
|
||||
|
||||
/// Returns a file format specific atom for a GOT entry targeting
|
||||
/// the specified atom.
|
||||
virtual const DefinedAtom *makeGOTEntry(const Atom &target) = 0;
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
||||
#endif // LLD_READER_WRITER_MACHO_PASSES_H
|
|
@ -1,4 +1,4 @@
|
|||
//===- Passes/StubsPass.cpp - Adds stubs ----------------------------------===//
|
||||
//===- lib/ReaderWriter/MachO/StubsPass.cpp -------------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
|
@ -17,10 +17,11 @@
|
|||
#include "lld/Core/DefinedAtom.h"
|
||||
#include "lld/Core/File.h"
|
||||
#include "lld/Core/LLVM.h"
|
||||
#include "lld/Core/Pass.h"
|
||||
#include "lld/Core/Reference.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
#include "MachOPasses.h"
|
||||
|
||||
namespace lld {
|
||||
|
||||
void StubsPass::perform(std::unique_ptr<MutableFile> &mergedFile) {
|
|
@ -19,6 +19,7 @@
|
|||
#include "lld/Core/SharedLibraryAtom.h"
|
||||
#include "lld/Core/Simple.h"
|
||||
|
||||
#include "MachOPasses.h"
|
||||
#include "ReferenceKinds.h"
|
||||
#include "StubAtoms.hpp"
|
||||
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
# RUN: lld -core %s --add-pass GOT | FileCheck %s
|
||||
|
||||
#
|
||||
# Test that GOT pass instantiates GOT entires and alters references
|
||||
#
|
||||
|
||||
---
|
||||
defined-atoms:
|
||||
- name: foo
|
||||
type: code
|
||||
content: [ 48, 8B, 0D, 00, 00, 00, 00,
|
||||
48, 8B, 0D, 00, 00, 00, 00,
|
||||
48, 8B, 0D, 00, 00, 00, 00,
|
||||
48, 83, 3D, 00, 00, 00, 00, 00,
|
||||
48, 83, 3D, 00, 00, 00, 00, 00,
|
||||
48, 83, 3D, 00, 00, 00, 00, 00,
|
||||
48, 83, 3D, 00, 00, 00, 00, 00 ]
|
||||
references:
|
||||
- offset: 3
|
||||
kind: gotLoad32
|
||||
target: malloc
|
||||
- offset: 10
|
||||
kind: gotLoad32
|
||||
target: myPrivate
|
||||
- offset: 17
|
||||
kind: gotLoad32
|
||||
target: myInterposable
|
||||
- offset: 24
|
||||
kind: gotUse32
|
||||
target: malloc
|
||||
- offset: 32
|
||||
kind: gotUse32
|
||||
target: myPrivate
|
||||
- offset: 40
|
||||
kind: gotUse32
|
||||
target: myInterposable
|
||||
|
||||
- name: myPrivate
|
||||
scope: global
|
||||
interposable: no
|
||||
|
||||
- name: myInterposable
|
||||
scope: global
|
||||
interposable: yes
|
||||
|
||||
shared-library-atoms:
|
||||
- name: malloc
|
||||
load-name: libc.so
|
||||
|
||||
...
|
||||
|
||||
# CHECK: defined-atoms:
|
||||
# CHECK: name: foo
|
||||
# CHECK: references:
|
||||
# CHECK: kind: pcrel32
|
||||
# CHECK: offset: 3
|
||||
# CHECK: target: L
|
||||
# CHECK: kind: lea32wasGot
|
||||
# CHECK: offset: 10
|
||||
# CHECK: target: myPrivate
|
||||
# CHECK: kind: pcrel32
|
||||
# CHECK: offset: 17
|
||||
# CHECK: target: L
|
||||
# CHECK: kind: pcrel32
|
||||
# CHECK: offset: 24
|
||||
# CHECK: target: L
|
||||
# CHECK: kind: pcrel32
|
||||
# CHECK: offset: 32
|
||||
# CHECK: target: L
|
||||
# CHECK: kind: pcrel32
|
||||
# CHECK: offset: 40
|
||||
# CHECK: target: L
|
||||
# CHECK: name: myPrivate
|
||||
# CHECK: name: myInterposable
|
||||
# CHECK: interposable: yes
|
||||
# CHECK: name: L
|
||||
# CHECK: type: got
|
||||
# CHECK: type: got
|
||||
# CHECK: type: got
|
||||
# CHECK: shared-library-atoms:
|
||||
# CHECK: name: malloc
|
||||
# CHECK: ...
|
|
@ -1,47 +0,0 @@
|
|||
# RUN: lld -core %s --add-pass stubs | FileCheck %s
|
||||
|
||||
#
|
||||
# Test that stubs pass adds stubs and rebinds call sites to the stub
|
||||
#
|
||||
|
||||
---
|
||||
defined-atoms:
|
||||
- name: foo
|
||||
type: code
|
||||
content: [ E8, 00, 00, 00, 00, E8, 00, 00, 00,
|
||||
00, 48 ,8B, 05, 00, 00, 00, 00 ]
|
||||
references:
|
||||
- offset: 1
|
||||
kind: call32
|
||||
target: malloc
|
||||
- offset: 6
|
||||
kind: call32
|
||||
target: free
|
||||
- offset: 13
|
||||
kind: gotLoad32
|
||||
target: malloc
|
||||
|
||||
shared-library-atoms:
|
||||
- name: malloc
|
||||
load-name: libc.so
|
||||
|
||||
- name: free
|
||||
load-name: libc.so
|
||||
|
||||
...
|
||||
|
||||
# CHECK: name: foo
|
||||
# CHECK: references:
|
||||
# CHECK: kind: call32
|
||||
# CHECK: target: L
|
||||
# CHECK: kind: call32
|
||||
# CHECK: target: L
|
||||
# CHECK: kind: gotLoad32
|
||||
# CHECK: target: malloc
|
||||
# CHECK: name: L
|
||||
# CHECK: type: stub
|
||||
# CHECK: name: L
|
||||
# CHECK: type: stub
|
||||
# CHECK: name: malloc
|
||||
# CHECK: name: free
|
||||
# CHECK: ...
|
Loading…
Reference in New Issue