Move GOTPass and StubsPass from Core to MachO

llvm-svn: 212652
This commit is contained in:
Nick Kledzik 2014-07-09 21:04:24 +00:00
parent 79d4ffbc8f
commit 0edfdeb0be
11 changed files with 111 additions and 274 deletions

View File

@ -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

View File

@ -1,6 +1,4 @@
add_lld_library(lldPasses
GOTPass.cpp
StubsPass.cpp
LayoutPass.cpp
RoundTripNativePass.cpp
RoundTripYAMLPass.cpp

View File

@ -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");
}

View File

@ -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
)

View File

@ -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,

View File

@ -16,6 +16,7 @@
#include "lld/Core/Reference.h"
#include "lld/Core/Pass.h"
#include "MachOPasses.h"
#include "ReferenceKinds.h"
#include "StubAtoms.hpp"

View File

@ -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

View File

@ -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) {

View File

@ -19,6 +19,7 @@
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/Simple.h"
#include "MachOPasses.h"
#include "ReferenceKinds.h"
#include "StubAtoms.hpp"

View File

@ -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: ...

View File

@ -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: ...