#include <vector>
namespace lld {
-class DefinedAtom;
class MutableFile;
/// Once the core linking is done (which resolves references, coalesces atoms
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
add_lld_library(lldPasses
- GOTPass.cpp
- StubsPass.cpp
LayoutPass.cpp
RoundTripNativePass.cpp
RoundTripYAMLPass.cpp
};
-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
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");
}
add_lld_library(lldMachO
+ GOTPass.cpp
MachOLinkingContext.cpp
MachONormalizedFileBinaryReader.cpp
MachONormalizedFileBinaryWriter.cpp
MachONormalizedFileToAtoms.cpp
MachONormalizedFileYAML.cpp
ReferenceKinds.cpp
+ StubsPass.cpp
WriterMachO.cpp
)
-//===- Passes/GOTPass.cpp - Adds GOT entries ------------------------------===//
+//===- lib/ReaderWriter/MachO/GOTPass.cpp ---------------------------------===//
//
// The LLVM Linker
//
#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,
#include "lld/Core/Reference.h"
#include "lld/Core/Pass.h"
+#include "MachOPasses.h"
#include "ReferenceKinds.h"
#include "StubAtoms.hpp"
--- /dev/null
+//===- 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
-//===- Passes/StubsPass.cpp - Adds stubs ----------------------------------===//
+//===- lib/ReaderWriter/MachO/StubsPass.cpp -------------------------------===//
//
// The LLVM Linker
//
#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) {
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/Simple.h"
+#include "MachOPasses.h"
#include "ReferenceKinds.h"
#include "StubAtoms.hpp"
+++ /dev/null
-# 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: ...
+++ /dev/null
-# 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: ...