summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2012-05-31 22:34:00 +0000
committerNick Kledzik <kledzik@apple.com>2012-05-31 22:34:00 +0000
commitabb6981f68a0cf631b6d7d36e67127bb1af50713 (patch)
tree63d6fd7aeef209f7528fecf1a151df50f61f7fa9
parent5168a72b2628288c5ba3143745554e2eadbb67b0 (diff)
downloadbcm5719-llvm-abb6981f68a0cf631b6d7d36e67127bb1af50713.tar.gz
bcm5719-llvm-abb6981f68a0cf631b6d7d36e67127bb1af50713.zip
Major refactoring: Remove Platform concept. In its place there are
now Reader and Writer subclasses for each file format. Each Reader and Writer subclass defines an "options" class which controls how that Reader or Writer operates. llvm-svn: 157774
-rw-r--r--lld/docs/README.txt5
-rw-r--r--lld/docs/design.rst72
-rw-r--r--lld/include/lld/Core/AliasAtom.h56
-rw-r--r--lld/include/lld/Core/ArchiveLibraryFile.h5
-rw-r--r--lld/include/lld/Core/DefinedAtom.h2
-rw-r--r--lld/include/lld/Core/InputFiles.h6
-rw-r--r--lld/include/lld/Core/LLVM.h2
-rw-r--r--lld/include/lld/Core/NativeReader.h40
-rw-r--r--lld/include/lld/Core/NativeWriter.h34
-rw-r--r--lld/include/lld/Core/Pass.h76
-rw-r--r--lld/include/lld/Core/Platform.h99
-rw-r--r--lld/include/lld/Core/SharedLibraryFile.h6
-rw-r--r--lld/include/lld/Core/YamlReader.h50
-rw-r--r--lld/include/lld/Core/YamlWriter.h31
-rw-r--r--lld/include/lld/Reader/Reader.h29
-rw-r--r--lld/include/lld/ReaderWriter/Reader.h74
-rw-r--r--lld/include/lld/ReaderWriter/ReaderELF.h65
-rw-r--r--lld/include/lld/ReaderWriter/ReaderMachO.h68
-rw-r--r--lld/include/lld/ReaderWriter/ReaderNative.h63
-rw-r--r--lld/include/lld/ReaderWriter/ReaderPECOFF.h64
-rw-r--r--lld/include/lld/ReaderWriter/ReaderYAML.h73
-rw-r--r--lld/include/lld/ReaderWriter/Writer.h86
-rw-r--r--lld/include/lld/ReaderWriter/WriterELF.h64
-rw-r--r--lld/include/lld/ReaderWriter/WriterMachO.h109
-rw-r--r--lld/include/lld/ReaderWriter/WriterNative.h63
-rw-r--r--lld/include/lld/ReaderWriter/WriterPECOFF.h63
-rw-r--r--lld/include/lld/ReaderWriter/WriterYAML.h82
-rw-r--r--lld/lib/CMakeLists.txt3
-rw-r--r--lld/lib/Core/CMakeLists.txt8
-rw-r--r--lld/lib/Core/InputFiles.cpp6
-rw-r--r--lld/lib/Core/Resolver.cpp50
-rw-r--r--lld/lib/Core/SymbolTable.cpp6
-rw-r--r--lld/lib/Passes/GOTPass.cpp24
-rw-r--r--lld/lib/Passes/StubsPass.cpp26
-rw-r--r--lld/lib/Platforms/CMakeLists.txt1
-rw-r--r--lld/lib/Platforms/Darwin/CMakeLists.txt5
-rw-r--r--lld/lib/Platforms/Darwin/DarwinPlatform.cpp180
-rw-r--r--lld/lib/Platforms/Darwin/DarwinPlatform.h61
-rw-r--r--lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp90
-rw-r--r--lld/lib/Platforms/Darwin/DarwinReferenceKinds.h54
-rw-r--r--lld/lib/Platforms/Darwin/ExecutableAtoms.hpp84
-rw-r--r--lld/lib/Platforms/Darwin/ExecutableWriter.h35
-rw-r--r--lld/lib/Reader/CMakeLists.txt3
-rw-r--r--lld/lib/ReaderWriter/CMakeLists.txt9
-rw-r--r--lld/lib/ReaderWriter/ELF/CMakeLists.txt4
-rw-r--r--lld/lib/ReaderWriter/ELF/ReaderELF.cpp41
-rw-r--r--lld/lib/ReaderWriter/ELF/WriterELF.cpp35
-rw-r--r--lld/lib/ReaderWriter/MachO/CMakeLists.txt4
-rw-r--r--lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp50
-rw-r--r--lld/lib/ReaderWriter/MachO/GOTPass.hpp51
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOFormat.hpp (renamed from lld/lib/Platforms/Darwin/MachOFormat.hpp)46
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp103
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.h77
-rw-r--r--lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp (renamed from lld/lib/Platforms/Darwin/SimpleAtoms.hpp)12
-rw-r--r--lld/lib/ReaderWriter/MachO/StubAtoms.hpp (renamed from lld/lib/Platforms/Darwin/StubAtoms.hpp)30
-rw-r--r--lld/lib/ReaderWriter/MachO/StubsPass.hpp145
-rw-r--r--lld/lib/ReaderWriter/MachO/WriterMachO.cpp (renamed from lld/lib/Platforms/Darwin/ExecutableWriter.cpp)412
-rw-r--r--lld/lib/ReaderWriter/Native/CMakeLists.txt4
-rw-r--r--lld/lib/ReaderWriter/Native/NativeFileFormat.h (renamed from lld/lib/Core/NativeFileFormat.h)8
-rw-r--r--lld/lib/ReaderWriter/Native/ReaderNative.cpp (renamed from lld/lib/Core/NativeReader.cpp)204
-rw-r--r--lld/lib/ReaderWriter/Native/WriterNative.cpp (renamed from lld/lib/Core/NativeWriter.cpp)70
-rw-r--r--lld/lib/ReaderWriter/PECOFF/CMakeLists.txt4
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp (renamed from lld/lib/Reader/COFFReader.cpp)50
-rw-r--r--lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp35
-rw-r--r--lld/lib/ReaderWriter/Reader.cpp42
-rw-r--r--lld/lib/ReaderWriter/Writer.cpp (renamed from lld/lib/Core/Platform.cpp)16
-rw-r--r--lld/lib/ReaderWriter/YAML/CMakeLists.txt5
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderYAML.cpp (renamed from lld/lib/Core/YamlReader.cpp)93
-rw-r--r--lld/lib/ReaderWriter/YAML/WriterYAML.cpp (renamed from lld/lib/Core/YamlWriter.cpp)83
-rw-r--r--lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp (renamed from lld/lib/Core/YamlKeyValues.cpp)2
-rw-r--r--lld/lib/ReaderWriter/YAML/YamlKeyValues.h (renamed from lld/lib/Core/YamlKeyValues.h)2
-rw-r--r--lld/tools/lld-core/CMakeLists.txt10
-rw-r--r--lld/tools/lld-core/TestingHelpers.hpp403
-rw-r--r--lld/tools/lld-core/lld-core.cpp480
74 files changed, 2848 insertions, 1705 deletions
diff --git a/lld/docs/README.txt b/lld/docs/README.txt
index e50ae59a6c8..eb09a2d2b7e 100644
--- a/lld/docs/README.txt
+++ b/lld/docs/README.txt
@@ -5,3 +5,8 @@ The lld documentation is written using the Sphinx documentation generator. It is
currently tested with Sphinx 1.1.3.
We currently use the 'nature' theme and a Beaker inspired structure.
+
+To rebuild documents into html:
+
+ [/lld/docs]> make html
+
diff --git a/lld/docs/design.rst b/lld/docs/design.rst
index 8c40ee92419..19ea8110d3a 100644
--- a/lld/docs/design.rst
+++ b/lld/docs/design.rst
@@ -108,13 +108,32 @@ The overall steps in linking are:
The Resolving and Passes steps are done purely on the master graph of atoms, so
they have no notion of file formats such as mach-o or ELF.
+
+Input Files
+~~~~~~~~~~~
+
+Existing developer tools using different file formats for object files.
+A goal of lld is to be file format independent. This is done
+through a plug-in model for reading object files. The lld::Reader is the base
+class for all object file readers. A Reader follows the factory method pattern.
+A Reader instantiates an lld::File object (which is a graph of Atoms) from a
+given object file (on disk or in-memory).
+
+Every Reader subclass defines its own "options" class (for instance the mach-o
+Reader defines the class ReaderOptionsMachO). This options class is the
+one-and-only way to control how the Reader operates when parsing an input file
+into an Atom graph. For instance, you may want the Reader to only accept
+certain architectures. The options class can be instantiated from command
+line options, or it can be subclassed and the ivars programatically set.
+
+
Resolving
~~~~~~~~~
-The resolving step takes all the atoms' graphs from each object file and combines
-them into one master object graph. Unfortunately, it is not as simple as
-appending the atom list from each file into one big list. There are many cases
-where atoms need to be coalesced. That is, two or more atoms need to be
+The resolving step takes all the atoms' graphs from each object file and
+combines them into one master object graph. Unfortunately, it is not as simple
+as appending the atom list from each file into one big list. There are many
+cases where atoms need to be coalesced. That is, two or more atoms need to be
coalesced into one atom. This is necessary to support: C language "tentative
definitions", C++ weak symbols for templates and inlines defined in headers,
replacing undefined atoms with actual definition atoms, and for merging copies
@@ -189,6 +208,7 @@ each proxy atom needed, and these new atoms are added to the current lld::File
object. Next, all the noted call sites to shared library atoms have their
References altered to point to the stub atom instead of the shared library atom.
+
Generate Output File
~~~~~~~~~~~~~~~~~~~~
@@ -196,17 +216,31 @@ Once the passes are done, the output file writer is given current lld::File
object. The writer's job is to create the executable content file wrapper and
place the content of the atoms into it.
-Sometimes the output generator needs access to particular atoms (for instance,
-it may need to know which atom is "main" in order to specifiy the entry
-point in the executable. The way to do this is to have the platform create
-an Atom with a Reference to the required atom(s) and provide this atom
-in the initialize set of atoms for the resolver. If a particular symbol name
-is required, this arrangment will also cause core linking to fail if the
-symbol is not defined (e.g. "main" is undefined).
+lld uses a plug-in model for writing output files. All concrete writers (e.g.
+ELF, mach-o, etc) are subclasses of the lld::Writer classs.
-Sometimes a platform supports lazily created symbols. To support this, the
-platform can create a File object which vends no initial atoms, but does
-lazily supply atoms by name as needed.
+Unlike the Reader class which has just one method to instantiate an lld::File,
+the Writer class has multiple methods. The crucial method is to generate the
+output file, but there are also methods which allow the Writer to contribute
+Atoms to the resolver and specify passes to run.
+
+An example of contributing
+atoms is that if the Writer knows a main executable is being linked and such
+an executable requires a specially named entry point (e.g. "_main"), the Writer
+can add an UndefinedAtom with that special name to the resolver. This will
+cause the resolver to issue an error if that symbol is not defined.
+
+Sometimes a Writer supports lazily created symbols, such as names for the start
+of sections. To support this, the Writer can create a File object which vends
+no initial atoms, but does lazily supply atoms by name as needed.
+
+Every Writer subclass defines its own "options" class (for instance the mach-o
+Writer defines the class WriterOptionsMachO). This options class is the
+one-and-only way to control how the Writer operates when producing an output
+file from an Atom graph. For instance, you may want the Writer to optimize
+the output for certain OS versions, or strip local symbols, etc. The options
+class can be instantiated from command line options, or it can be subclassed
+and the ivars programatically set.
lld::File representations
@@ -262,6 +296,10 @@ With this model for the native file format, files can be read and turned
into the in-memory graph of lld::Atoms with just a few memory allocations.
And the format can easily adapt over time to new features.
+The binary file format follows the ReaderWriter patterns used in lld. The lld
+library comes with the classes: ReaderNative and WriterNative. So, switching
+between file formats is as easy as switching which Reader subclass is used.
+
Textual representations in YAML
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -300,8 +338,12 @@ feature trying to be tested. By writing test cases in the linkers own textual
format, we can exactly specify every attribute of every atom and thus target
specific linker logic.
+The textual/YAML format follows the ReaderWriter patterns used in lld. The lld
+library comes with the classes: ReaderYAML and WriterYAML.
+
+
Testing
-~~~~~~~
+-------
The lld project contains a test suite which is being built up as new code is
added to lld. All new lld functionality should have a tests added to the test
diff --git a/lld/include/lld/Core/AliasAtom.h b/lld/include/lld/Core/AliasAtom.h
deleted file mode 100644
index 22dfca162ec..00000000000
--- a/lld/include/lld/Core/AliasAtom.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//===- Core/AliasAtom.h - Alias to another Atom ---------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_ALIAS_ATOM_H_
-#define LLD_CORE_ALIAS_ATOM_H_
-
-#include "lld/Core/Atom.h"
-
-#include "llvm/ADT/StringRef.h"
-
-namespace lld {
-
-class AliasAtom : public Atom {
-public:
- AliasAtom(StringRef nm, const Atom &target, Atom::Scope scope)
- : Atom( target.definition()
- , Atom::combineNever
- , scope
- , target.contentType()
- , target.sectionChoice()
- , target.userVisibleName()
- , target.deadStrip()
- , target.isThumb()
- , true
- , target.alignment()
- )
- , _name(nm)
- , _aliasOf(target) {}
-
- // overrides of Atom
- virtual const File *file() const {
- return _aliasOf.file();
- }
-
- virtual bool translationUnitSource(StringRef &path) const {
- return _aliasOf.translationUnitSource(path);
- }
-
- virtual StringRef name() const {
- return _name;
- }
-
-private:
- const StringRef _name;
- const Atom &_aliasOf;
-};
-
-} // namespace lld
-
-#endif // LLD_CORE_ALIAS_ATOM_H_
diff --git a/lld/include/lld/Core/ArchiveLibraryFile.h b/lld/include/lld/Core/ArchiveLibraryFile.h
index f80b11a5221..fbeb2964838 100644
--- a/lld/include/lld/Core/ArchiveLibraryFile.h
+++ b/lld/include/lld/Core/ArchiveLibraryFile.h
@@ -26,8 +26,6 @@ namespace lld {
///
class ArchiveLibraryFile : public File {
public:
- ArchiveLibraryFile(StringRef path) : File(path) {
- }
virtual ~ArchiveLibraryFile() {
}
@@ -47,6 +45,9 @@ public:
/// specified name and return the File object for that member, or nullptr.
virtual const File *find(StringRef name, bool dataSymbolOnly) const = 0;
+protected:
+ /// only subclasses of ArchiveLibraryFile can be instantiated
+ ArchiveLibraryFile(StringRef path) : File(path) { }
};
} // namespace lld
diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h
index 05bbf15e780..b7e269f3559 100644
--- a/lld/include/lld/Core/DefinedAtom.h
+++ b/lld/include/lld/Core/DefinedAtom.h
@@ -1,4 +1,4 @@
-//===- Core/DefinedAtom.h - The Fundamental Unit of Linking ---------------===//
+//===- Core/DefinedAtom.h - An Atom with content --------------------------===//
//
// The LLVM Linker
//
diff --git a/lld/include/lld/Core/InputFiles.h b/lld/include/lld/Core/InputFiles.h
index f3111f8d16a..c98f0d4d613 100644
--- a/lld/include/lld/Core/InputFiles.h
+++ b/lld/include/lld/Core/InputFiles.h
@@ -37,12 +37,14 @@ public:
InputFiles();
virtual ~InputFiles();
- /// Used by platforms to insert platform specific files.
+ /// Used by Writers to insert writer specific files.
virtual void prependFile(const File&);
- /// Used by platforms to insert platform specific files.
+ /// Used by Writers to insert writer specific files.
virtual void appendFile(const File&);
+ /// Transfers ownership of a vector of Files to this InputFile object.
+ virtual void appendFiles(std::vector<std::unique_ptr<File>> &files);
/// @brief iterates all atoms in initial files
virtual void forEachInitialAtom(Handler &) const;
diff --git a/lld/include/lld/Core/LLVM.h b/lld/include/lld/Core/LLVM.h
index 873dce80ffb..25bd3702ccb 100644
--- a/lld/include/lld/Core/LLVM.h
+++ b/lld/include/lld/Core/LLVM.h
@@ -23,6 +23,7 @@ namespace llvm {
// ADT's.
class StringRef;
class Twine;
+ class MemoryBuffer;
template<typename T> class ArrayRef;
template<class T> class OwningPtr;
template<unsigned InternalLen> class SmallString;
@@ -55,6 +56,7 @@ namespace lld {
// ADT's.
using llvm::StringRef;
using llvm::Twine;
+ using llvm::MemoryBuffer;
using llvm::ArrayRef;
using llvm::OwningPtr;
using llvm::SmallString;
diff --git a/lld/include/lld/Core/NativeReader.h b/lld/include/lld/Core/NativeReader.h
deleted file mode 100644
index 1f17d07d0ef..00000000000
--- a/lld/include/lld/Core/NativeReader.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===- Core/NativeReader.h - Reads llvm native object files ---------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_NATIVE_READER_H_
-#define LLD_CORE_NATIVE_READER_H_
-
-#include "lld/Core/File.h"
-
-#include "llvm/Support/system_error.h"
-
-#include <memory>
-#include <vector>
-
-namespace llvm {
- class MemoryBuffer;
- class StringRef;
-}
-
-namespace lld {
- /// parseNativeObjectFileOrSTDIN - Open the specified native object file (use
- /// stdin if the path is "-") and instantiate into an lld::File object.
- error_code parseNativeObjectFileOrSTDIN( StringRef path
- , std::unique_ptr<File> &result);
-
-
- /// parseNativeObjectFile - Parse the specified native object file
- /// (in a buffer) and instantiate into an lld::File object.
- error_code parseNativeObjectFile( std::unique_ptr<llvm::MemoryBuffer> &mb
- , StringRef path
- , std::unique_ptr<File> &result);
-
-} // namespace lld
-
-#endif // LLD_CORE_NATIVE_READER_H_
diff --git a/lld/include/lld/Core/NativeWriter.h b/lld/include/lld/Core/NativeWriter.h
deleted file mode 100644
index 80c9fe2aaa2..00000000000
--- a/lld/include/lld/Core/NativeWriter.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- Core/NativeWriter.h - Writes native object file --------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_NATIVE_WRITER_H_
-#define LLD_CORE_NATIVE_WRITER_H_
-
-#include "lld/Core/File.h"
-
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
- class StringRef;
-}
-
-
-namespace lld {
-
- /// writeNativeObjectFile - writes the lld::File object in native object
- /// file format to the specified file path.
- int writeNativeObjectFile(const lld::File &, StringRef path);
-
- /// writeNativeObjectFile - writes the lld::File object in native object
- /// file format to the specified stream.
- int writeNativeObjectFile(const lld::File &, raw_ostream &);
-
-} // namespace lld
-
-#endif // LLD_CORE_NATIVE_WRITER_H_
diff --git a/lld/include/lld/Core/Pass.h b/lld/include/lld/Core/Pass.h
index de72b7d1be9..28859f0d3c1 100644
--- a/lld/include/lld/Core/Pass.h
+++ b/lld/include/lld/Core/Pass.h
@@ -11,11 +11,12 @@
#define LLD_CORE_PASS_H_
#include "lld/Core/Atom.h"
-#include "lld/Core/Platform.h"
+#include "lld/Core/Reference.h"
#include <vector>
namespace lld {
+class DefinedAtom;
///
@@ -34,43 +35,88 @@ namespace lld {
class Pass {
public:
/// Do the actual work of the Pass.
- virtual void perform() = 0;
+ virtual void perform(File& mergedFile) = 0;
protected:
// Only subclassess can be instantiated.
- Pass(File& f, Platform& p) : _file(f), _platform(p) {}
-
-
- File& _file;
- Platform& _platform;
+ Pass() { }
};
///
/// Pass for adding stubs (PLT entries) for calls to functions
-/// outside the linkage unit.
+/// 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(File& f, Platform& p) : Pass(f, p) {}
+ StubsPass() : Pass() {}
/// Scans all Atoms looking for call-site uses of SharedLibraryAtoms
- /// and transfroms the call-site to call a stub instead.
- virtual void perform();
+ /// and transfroms the call-site to call a stub instead using the
+ /// helper methods below.
+ virtual void perform(File& mergedFile);
+
+ /// 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(Reference::Kind) = 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(File &masterFile) = 0;
};
+
///
/// Pass for adding GOT entries for pointers to functions/data
-/// outside the linkage unit.
+/// 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(File& f, Platform& p) : Pass(f, p) {}
+ GOTPass() : Pass() {}
/// Scans all Atoms looking for pointer to SharedLibraryAtoms
- /// and transfroms them to a pointer to a GOT entry.
- virtual void perform();
+ /// and transfroms them to a pointer to a GOT entry using the
+ /// helper methods below.
+ virtual void perform(File& mergedFile);
+
+ /// 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(Reference::Kind, 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;
};
diff --git a/lld/include/lld/Core/Platform.h b/lld/include/lld/Core/Platform.h
deleted file mode 100644
index 2b2c8e8b5a2..00000000000
--- a/lld/include/lld/Core/Platform.h
+++ /dev/null
@@ -1,99 +0,0 @@
-//===- Core/Platform.h - Platform Interface -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_PLATFORM_H_
-#define LLD_CORE_PLATFORM_H_
-
-#include "lld/Core/Reference.h"
-#include "lld/Core/LLVM.h"
-#include <vector>
-
-namespace lld {
-class Atom;
-class DefinedAtom;
-class UndefinedAtom;
-class SharedLibraryAtom;
-class File;
-class InputFiles;
-
-
-/// The Platform class encapsulated plaform specific linking knowledge.
-///
-/// Much of what it does is driving by platform specific linker options.
-class Platform {
-public:
- virtual ~Platform();
-
- virtual void addFiles(InputFiles&) = 0;
-
- /// Converts a reference kind string to a in-memory numeric value.
- /// For use with parsing YAML encoded object files.
- virtual Reference::Kind kindFromString(StringRef) = 0;
-
- /// Converts an in-memory reference kind value to a string.
- /// For use with writing YAML encoded object files.
- virtual StringRef kindToString(Reference::Kind) = 0;
-
- /// If true, the linker will use stubs and GOT entries for
- /// references to shared library symbols. If false, the linker
- /// will generate relocations on the text segment which the
- /// runtime loader will use to patch the program at runtime.
- virtual bool noTextRelocs() = 0;
-
- /// Returns if the Reference kind is for a call site. The "stubs" Pass uses
- /// this to find calls that need to be indirected through a stub.
- virtual bool isCallSite(Reference::Kind) = 0;
-
- /// Returns if the Reference kind is a pre-instantiated GOT access.
- /// The "got" Pass uses this to figure out what GOT entries to instantiate.
- virtual bool isGOTAccess(Reference::Kind, bool& canBypassGOT) = 0;
-
- /// The platform needs to alter the reference kind from a pre-instantiated
- /// GOT access to an actual access. If targetIsNowGOT is true, the "got"
- /// Pass has instantiated a GOT atom and altered the reference's target
- /// to point to that atom. If targetIsNowGOT is false, the "got" 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 platform specific atom for a stub/PLT entry which will
- /// 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. The platform needs to maintain a list of all stubs (and
- /// associated atoms) it has created for use by addStubAtoms().
- virtual const DefinedAtom* getStub(const Atom &target, File&) = 0;
-
- /// After the stubs Pass is done calling getStub(), the Pass will call
- /// this method to add all the stub (and support) atoms to the master
- /// file object.
- virtual void addStubAtoms(File &file) = 0;
-
- /// Create a platform specific GOT atom.
- virtual const DefinedAtom* makeGOTEntry(const Atom&, File&) = 0;
-
- /// Write an executable file from the supplied file object to the
- /// supplied stream.
- virtual void writeExecutable(const lld::File &, raw_ostream &out) = 0;
-
-protected:
- Platform();
-};
-
-
-
-///
-/// Creates a platform object for linking as done on Darwin (iOS/OSX).
-///
-extern Platform *createDarwinPlatform();
-
-
-
-} // namespace lld
-
-#endif // LLD_CORE_PLATFORM_H_
diff --git a/lld/include/lld/Core/SharedLibraryFile.h b/lld/include/lld/Core/SharedLibraryFile.h
index b3cb00c94c7..9d08b0f00c5 100644
--- a/lld/include/lld/Core/SharedLibraryFile.h
+++ b/lld/include/lld/Core/SharedLibraryFile.h
@@ -22,8 +22,6 @@ namespace lld {
///
class SharedLibraryFile : public File {
public:
- SharedLibraryFile(StringRef path) : File(path) {
- }
virtual ~SharedLibraryFile() {
}
@@ -44,7 +42,9 @@ public:
/// symbol. Otherwise return nullptr.
virtual const SharedLibraryAtom *exports(StringRef name,
bool dataSymbolOnly) const;
-
+protected:
+ /// only subclasses of SharedLibraryFile can be instantiated
+ SharedLibraryFile(StringRef path) : File(path) { }
};
} // namespace lld
diff --git a/lld/include/lld/Core/YamlReader.h b/lld/include/lld/Core/YamlReader.h
deleted file mode 100644
index 5a6328c23d5..00000000000
--- a/lld/include/lld/Core/YamlReader.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//===- Core/YamlReader.h - Reads YAML -------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_YAML_READER_H_
-#define LLD_CORE_YAML_READER_H_
-
-#include "lld/Core/LLVM.h"
-
-#include "llvm/Support/system_error.h"
-
-#include <memory>
-#include <vector>
-
-namespace llvm {
-class MemoryBuffer;
-class StringRef;
-}
-
-namespace lld {
-
-class Platform;
-class File;
-
-namespace yaml {
-
- /// parseObjectTextFileOrSTDIN - Open the specified YAML file (use stdin if
- /// the path is "-") and parse into lld::File object(s) and append each to
- /// the specified vector<File*>.
- error_code parseObjectTextFileOrSTDIN( StringRef path
- , Platform&
- , std::vector<
- std::unique_ptr<const File>>&);
-
-
- /// parseObjectText - Parse the specified YAML formatted MemoryBuffer
- /// into lld::File object(s) and append each to the specified vector<File*>.
- error_code parseObjectText( llvm::MemoryBuffer *mb
- , Platform&
- , std::vector<std::unique_ptr<const File>>&);
-
-} // namespace yaml
-} // namespace lld
-
-#endif // LLD_CORE_YAML_READER_H_
diff --git a/lld/include/lld/Core/YamlWriter.h b/lld/include/lld/Core/YamlWriter.h
deleted file mode 100644
index 949e11a19da..00000000000
--- a/lld/include/lld/Core/YamlWriter.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- Core/YamlWriter.h - Writes YAML formatted object files -------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_CORE_YAML_WRITER_H_
-#define LLD_CORE_YAML_WRITER_H_
-
-#include "lld/Core/LLVM.h"
-
-#include "llvm/Support/raw_ostream.h"
-
-namespace lld {
-
-class Platform;
-class File;
-
-namespace yaml {
-
- /// writeObjectText - writes the lld::File object as in YAML
- /// format to the specified stream.
- void writeObjectText(const lld::File &, Platform &, raw_ostream &);
-
-} // namespace yaml
-} // namespace lld
-
-#endif // LLD_CORE_YAML_WRITER_H_
diff --git a/lld/include/lld/Reader/Reader.h b/lld/include/lld/Reader/Reader.h
deleted file mode 100644
index c74615b0bfe..00000000000
--- a/lld/include/lld/Reader/Reader.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//===- Reader.h - Create object file readers ------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_READER_H_
-#define LLD_READER_READER_H_
-
-#include "llvm/ADT/OwningPtr.h"
-
-#include <memory>
-
-namespace llvm {
- class error_code;
- class MemoryBuffer;
-}
-
-namespace lld {
- class File;
-
- llvm::error_code parseCOFFObjectFile(std::unique_ptr<llvm::MemoryBuffer> MB,
- std::unique_ptr<File> &Result);
-}
-
-#endif
diff --git a/lld/include/lld/ReaderWriter/Reader.h b/lld/include/lld/ReaderWriter/Reader.h
new file mode 100644
index 00000000000..8f590bc333b
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/Reader.h
@@ -0,0 +1,74 @@
+//===- ReaderWriter/Reader.h - Abstract File Format Reading Interface -----===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_H_
+#define LLD_READERWRITER_READER_H_
+
+#include "lld/Core/LLVM.h"
+#include <memory>
+#include <vector>
+
+namespace lld {
+class File;
+
+///
+/// The Reader is an abstract class for reading object files,
+/// library files, and executable files. Each file format
+/// (e.g. ELF, mach-o, PECOFF, native, etc) have a concrete subclass
+/// of Reader.
+///
+class Reader {
+public:
+ virtual ~Reader();
+
+
+ /// Parse a file given its file system path and create a File object.
+ virtual error_code readFile(StringRef path,
+ std::vector<std::unique_ptr<File>> &result);
+
+ /// Parse a supplied buffer (already filled with the contents of a file)
+ /// and create a File object.
+ /// On success, the resulting File object takes ownership of
+ /// the MemoryBuffer.
+ virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+ std::vector<std::unique_ptr<File>> &result) = 0;
+
+protected:
+ // only concrete subclasses can be instantiated
+ Reader();
+};
+
+
+
+///
+/// The ReaderOptions encapsulates the options used by all Readers.
+/// Each file format defines a subclass of ReaderOptions
+/// to hold file format specific options. The option objects are the only
+/// way to control the behaviour of Readers.
+///
+class ReaderOptions {
+public:
+ // Any options common to all file format Readers will go here.
+
+protected:
+ // only concrete subclasses can be instantiated
+ ReaderOptions();
+};
+
+
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_H_
+
+
+
+
diff --git a/lld/include/lld/ReaderWriter/ReaderELF.h b/lld/include/lld/ReaderWriter/ReaderELF.h
new file mode 100644
index 00000000000..5644b81fa25
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/ReaderELF.h
@@ -0,0 +1,65 @@
+//===- ReaderWriter/ReaderELF.h - ELF File Format Reading Interface -------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_ELF_H_
+#define LLD_READERWRITER_READER_ELF_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+
+
+namespace lld {
+
+///
+/// The ReaderOptionsELF class encapsulates options needed
+/// to process mach-o files. You can create an ReaderOptionsELF
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsELF : public ReaderOptions {
+public:
+ virtual ~ReaderOptionsELF();
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ ReaderOptionsELF(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ ReaderOptionsELF();
+
+
+
+protected:
+};
+
+
+
+
+///
+/// The only way to instantiate a ReaderELF object
+/// is via this createReaderELF function. The is no public
+/// ReaderELF class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsELF
+/// object.
+/// The Reader object created retains a reference to the
+/// ReaderOptionsELF object supplied, so the objects object must not be
+/// destroyed before the Reader object.
+///
+Reader* createReaderELF(const ReaderOptionsELF &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_ELF_H_
diff --git a/lld/include/lld/ReaderWriter/ReaderMachO.h b/lld/include/lld/ReaderWriter/ReaderMachO.h
new file mode 100644
index 00000000000..669a199b7ab
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/ReaderMachO.h
@@ -0,0 +1,68 @@
+//===- ReaderWriter/ReaderMachO.h - MachO File Format Reading Interface ---===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READER_WRITER_READER_MACHO_H_
+#define LLD_READER_WRITER_READER_MACHO_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+///
+/// The ReaderOptionsMachO class encapsulates options needed
+/// to process mach-o files. You can create an ReaderOptionsMachO
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsMachO : public ReaderOptions {
+public:
+ virtual ~ReaderOptionsMachO() { }
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ ReaderOptionsMachO(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ ReaderOptionsMachO();
+
+
+ StringRef archName() const { return _archName; }
+
+protected:
+ StringRef _archName;
+};
+
+
+
+
+///
+/// The only way to instantiate a ReaderMachO object
+/// is via this createReaderMachO function. The is no public
+/// ReaderMachO class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsMachO
+/// object.
+/// The Reader object created retains a reference to the
+/// ReaderOptionsMachO object supplied, so the objects object must not be
+/// destroyed before the Reader object.
+///
+Reader* createReaderMachO(const ReaderOptionsMachO &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READER_WRITER_READER_MACHO_H_
diff --git a/lld/include/lld/ReaderWriter/ReaderNative.h b/lld/include/lld/ReaderWriter/ReaderNative.h
new file mode 100644
index 00000000000..21f4415536d
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/ReaderNative.h
@@ -0,0 +1,63 @@
+//===- ReaderWriter/ReaderNative.h - Native File Format Reading Interface ---===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_NATIVE_H_
+#define LLD_READERWRITER_READER_NATIVE_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+
+
+namespace lld {
+
+///
+/// The ReaderOptionsNative class encapsulates options needed
+/// to process mach-o files. You can create an ReaderOptionsNative
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsNative : public ReaderOptions {
+public:
+ virtual ~ReaderOptionsNative();
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ ReaderOptionsNative(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ ReaderOptionsNative();
+
+protected:
+};
+
+
+
+
+///
+/// The only way to instantiate a ReaderNative object
+/// is via this createReaderNative function. The is no public
+/// ReaderNative class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsNative
+/// object.
+/// The Reader object created retains a reference to the
+/// ReaderOptionsNative object supplied, so the objects object must not be
+/// destroyed before the Reader object.
+///
+Reader* createReaderNative(const ReaderOptionsNative &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_NATIVE_H_
diff --git a/lld/include/lld/ReaderWriter/ReaderPECOFF.h b/lld/include/lld/ReaderWriter/ReaderPECOFF.h
new file mode 100644
index 00000000000..cb1dc375491
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/ReaderPECOFF.h
@@ -0,0 +1,64 @@
+//===- ReaderWriter/ReaderPECOFF.h - PECOFF File Format Reading Interface ---===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_PECOFF_H_
+#define LLD_READERWRITER_READER_PECOFF_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+
+
+namespace lld {
+
+///
+/// The ReaderOptionsPECOFF class encapsulates options needed
+/// to process mach-o files. You can create an ReaderOptionsPECOFF
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsPECOFF : public ReaderOptions {
+public:
+ virtual ~ReaderOptionsPECOFF();
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ ReaderOptionsPECOFF(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ ReaderOptionsPECOFF();
+
+
+protected:
+};
+
+
+
+
+///
+/// The only way to instantiate a ReaderPECOFF object
+/// is via this createReaderPECOFF function. The is no public
+/// ReaderPECOFF class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsPECOFF
+/// object.
+/// The Reader object created retains a reference to the
+/// ReaderOptionsPECOFF object supplied, so the objects object must not be
+/// destroyed before the Reader object.
+///
+Reader* createReaderPECOFF(const ReaderOptionsPECOFF &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_PECOFF_H_
diff --git a/lld/include/lld/ReaderWriter/ReaderYAML.h b/lld/include/lld/ReaderWriter/ReaderYAML.h
new file mode 100644
index 00000000000..c49711f5b7b
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/ReaderYAML.h
@@ -0,0 +1,73 @@
+//===- ReaderWriter/ReaderYAML.h - YAML File Format Reading Interface -----===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_READER_YAML_H_
+#define LLD_READERWRITER_READER_YAML_H_
+
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+///
+/// The ReaderOptionsYAML class encapsulates options needed
+/// to process mach-o files. You can create an ReaderOptionsYAML
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class ReaderOptionsYAML : public ReaderOptions {
+public:
+ virtual ~ReaderOptionsYAML();
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ ReaderOptionsYAML(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ ReaderOptionsYAML();
+
+
+ /// Converts a reference kind string to a in-memory numeric value.
+ /// Used when parsing YAML encoded object files.
+ virtual Reference::Kind kindFromString(StringRef) const = 0;
+
+
+protected:
+};
+
+
+
+
+///
+/// The only way to instantiate a ReaderYAML object
+/// is via this createReaderYAML function. The is no public
+/// ReaderYAML class that you might be tempted to subclass.
+/// Support for all variants must be represented in the ReaderOptionsYAML
+/// object.
+/// The Reader object created retains a reference to the
+/// ReaderOptionsYAML object supplied, so the objects object must not be
+/// destroyed before the Reader object.
+///
+Reader* createReaderYAML(const ReaderOptionsYAML &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_READER_YAML_H_
+
+
diff --git a/lld/include/lld/ReaderWriter/Writer.h b/lld/include/lld/ReaderWriter/Writer.h
new file mode 100644
index 00000000000..7165fb6abde
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/Writer.h
@@ -0,0 +1,86 @@
+//===- ReaderWriter/Writer.h - Abstract File Format Interface -------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_H_
+#define LLD_READERWRITER_WRITER_H_
+
+#include "lld/Core/LLVM.h"
+#include <memory>
+#include <vector>
+
+namespace lld {
+class File;
+class InputFiles;
+class StubsPass;
+class GOTPass;
+
+
+///
+/// The Writer is an abstract class for writing object files,
+/// shared library files, and executable files. Each file format
+/// (e.g. ELF, mach-o, PECOFF, native, etc) have a concrete subclass
+/// of Writer.
+///
+class Writer {
+public:
+ virtual ~Writer();
+
+ /// Write a file from the supplied File object
+ virtual error_code writeFile(const lld::File &linkedFile, StringRef path) = 0;
+
+ /// Return a Pass object for creating stubs/PLT entries
+ virtual StubsPass *stubPass() {
+ return nullptr;
+ }
+
+ /// Return a Pass object for creating GOT entries
+ virtual GOTPass *gotPass() {
+ return nullptr;
+ }
+
+ /// This method is called by Core Linking to give the Writer a chance to
+ /// add file format specific "files" to set of files to be linked.
+ /// This is how file format specific atoms can be added to the link.
+ virtual void addFiles(InputFiles&) {
+ }
+
+
+protected:
+ // only concrete subclasses can be instantiated
+ Writer();
+};
+
+
+
+///
+/// The WriterOptions encapsulates the options used by Writers.
+/// Each file format defines a subclass of WriterOptions
+/// to hold file format specific options. The option objects are the only
+/// way to control the behaviour of Writers.
+///
+class WriterOptions {
+public:
+ // Any options common to all file formats will go here.
+
+protected:
+ // only concrete subclasses can be instantiated
+ WriterOptions();
+};
+
+
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_H_
+
+
+
+
diff --git a/lld/include/lld/ReaderWriter/WriterELF.h b/lld/include/lld/ReaderWriter/WriterELF.h
new file mode 100644
index 00000000000..6a182de4912
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/WriterELF.h
@@ -0,0 +1,64 @@
+//===- ReaderWriter/WriterELF.h - ELF File Format Writing Interface -------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_ELF_H_
+#define LLD_READERWRITER_WRITER_ELF_H_
+
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+///
+/// The WriterOptionsELF class encapsulates options needed
+/// to process mach-o files. You can create an WriterOptionsELF
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsELF : public WriterOptions {
+public:
+ virtual ~WriterOptionsELF();
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ WriterOptionsELF(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ WriterOptionsELF();
+
+protected:
+};
+
+
+
+
+///
+/// The only way to instantiate a WriterELF object
+/// is via this createWriterELF function. The is no public
+/// WriterELF class that you might be tempted to subclass.
+/// Support for all variants must be represented in the WriterOptionsELF
+/// object.
+/// The Writer object created retains a reference to the
+/// WriterOptionsELF object supplied, so it must not be destroyed
+/// before the Writer object.
+///
+Writer* createWriterELF(const WriterOptionsELF &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_ELF_H_
diff --git a/lld/include/lld/ReaderWriter/WriterMachO.h b/lld/include/lld/ReaderWriter/WriterMachO.h
new file mode 100644
index 00000000000..b1a84137c5a
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/WriterMachO.h
@@ -0,0 +1,109 @@
+//===- ReaderWriter/WriterMachO.h - MachO File Format Reading Interface ---===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_MACHO_H_
+#define LLD_READERWRITER_WRITER_MACHO_H_
+
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+///
+/// The WriterOptionsMachO class encapsulates options needed
+/// to process mach-o files. You can create an WriterOptionsMachO
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsMachO : public WriterOptions {
+public:
+ virtual ~WriterOptionsMachO();
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ WriterOptionsMachO(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ WriterOptionsMachO();
+
+
+
+ enum OutputKind {
+ outputDynamicExecutable,
+ outputDylib,
+ outputBundle,
+ outputObjectFile
+ };
+
+ enum Architecture {
+ arch_x86_64,
+ arch_x86,
+ arch_arm,
+ };
+
+ OutputKind outputKind() const { return _outputkind; }
+ Architecture architecture() const { return _architecture; }
+ StringRef archName() const { return _archName; }
+ uint64_t pageZeroSize() const { return _pageZeroSize; }
+ uint32_t cpuType() const { return _cpuType; }
+ uint32_t cpuSubtype() const { return _cpuSubtype; }
+ bool noTextRelocations() const { return _noTextRelocations; }
+
+protected:
+ OutputKind _outputkind;
+ StringRef _archName;
+ Architecture _architecture;
+ uint64_t _pageZeroSize;
+ uint32_t _cpuType;
+ uint32_t _cpuSubtype;
+ bool _noTextRelocations;
+};
+
+
+
+
+///
+/// The only way to instantiate a WriterMachO object
+/// is via this createWriterMachO function. The is no public
+/// WriterMachO class that you might be tempted to subclass.
+/// Support for all variants must be represented in the
+/// WriterOptionsMachO object.
+/// The Writer object created retains a reference to the
+/// WriterOptionsMachO object supplied, so it must not be destroyed
+/// before the Writer object.
+///
+Writer* createWriterMachO(const WriterOptionsMachO &options);
+
+
+///
+/// Returns an options object that can be used with the
+/// WriterYAML to write mach-o object files as YAML.
+///
+const class WriterOptionsYAML& writerOptionsMachOAsYAML();
+
+
+///
+/// Returns an options object that can be used with the
+/// ReaderYAML to reader YAML encoded mach-o files.
+///
+const class ReaderOptionsYAML& readerOptionsMachOAsYAML();
+
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_MACHO_H_
diff --git a/lld/include/lld/ReaderWriter/WriterNative.h b/lld/include/lld/ReaderWriter/WriterNative.h
new file mode 100644
index 00000000000..fdc99cf28a5
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/WriterNative.h
@@ -0,0 +1,63 @@
+//===- ReaderWriter/WriterNative.h - Native File Format Reading Interface ---===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_NATIVE_H_
+#define LLD_READERWRITER_WRITER_NATIVE_H_
+
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/Core/LLVM.h"
+
+
+namespace lld {
+
+///
+/// The WriterOptionsNative class encapsulates options needed
+/// to process mach-o files. You can create an WriterOptionsNative
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsNative : public WriterOptions {
+public:
+ virtual ~WriterOptionsNative();
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ WriterOptionsNative(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ WriterOptionsNative();
+
+protected:
+};
+
+
+
+
+///
+/// The only way to instantiate a WriterNative object
+/// is via this createWriterNative function. The is no public
+/// WriterNative class that you might be tempted to subclass.
+/// Support for all variants must be represented in the WriterOptionsNative
+/// object.
+/// The Writer object created retains a reference to the
+/// WriterOptionsNative object supplied, so it must not be destroyed
+/// before the Writer object.
+///
+Writer* createWriterNative(const WriterOptionsNative &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_NATIVE_H_
diff --git a/lld/include/lld/ReaderWriter/WriterPECOFF.h b/lld/include/lld/ReaderWriter/WriterPECOFF.h
new file mode 100644
index 00000000000..740190729e0
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/WriterPECOFF.h
@@ -0,0 +1,63 @@
+//===- ReaderWriter/WriterPECOFF.h - PECOFF File Format Writing Interface -===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_PECOFF_H_
+#define LLD_READERWRITER_WRITER_PECOFF_H_
+
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+///
+/// The WriterOptionsPECOFF class encapsulates options needed
+/// to process mach-o files. You can create an WriterOptionsPECOFF
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsPECOFF : public WriterOptions {
+public:
+ virtual ~WriterOptionsPECOFF();
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ WriterOptionsPECOFF(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ WriterOptionsPECOFF();
+
+protected:
+};
+
+
+
+///
+/// The only way to instantiate a WriterPECOFF object
+/// is via this createWriterPECOFF function. The is no public
+/// WriterPECOFF class that you might be tempted to subclass.
+/// Support for all variants must be represented in the WriterOptionsPECOFF
+/// object.
+/// The Writer object created retains a reference to the
+/// WriterOptionsPECOFF object supplied, so it must not be destroyed
+/// before the Writer object.
+///
+Writer* createWriterPECOFF(const WriterOptionsPECOFF &options);
+
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_PECOFF_H_
diff --git a/lld/include/lld/ReaderWriter/WriterYAML.h b/lld/include/lld/ReaderWriter/WriterYAML.h
new file mode 100644
index 00000000000..26dfbb852c5
--- /dev/null
+++ b/lld/include/lld/ReaderWriter/WriterYAML.h
@@ -0,0 +1,82 @@
+//===- ReaderWriter/WriterYAML.h - YAML File Format Writing Interface -----===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_READERWRITER_WRITER_YAML_H_
+#define LLD_READERWRITER_WRITER_YAML_H_
+
+#include "lld/ReaderWriter/Writer.h"
+
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Pass.h"
+
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+
+///
+/// The WriterOptionsYAML class encapsulates options needed
+/// to process mach-o files. You can create an WriterOptionsYAML
+/// instance from command line arguments or by subclassing and setting the
+/// instance variables in the subclass's constructor.
+///
+class WriterOptionsYAML : public WriterOptions {
+public:
+ virtual ~WriterOptionsYAML();
+
+ ///
+ /// Creates a Options object from darwin linker command line arguments.
+ /// FIXME: to be replaced with new option processing mechanism.
+ ///
+ WriterOptionsYAML(int argc, const char* argv[]);
+
+ ///
+ /// Creates a Options object with default settings. For use when
+ /// programmatically constructing options.
+ ///
+ WriterOptionsYAML();
+
+
+ /// Converts an in-memory reference kind value to a string.
+ /// Used when writing YAML encoded object files.
+ virtual StringRef kindToString(Reference::Kind) const = 0;
+
+
+ /// Enable Stubs pass to be run
+ virtual StubsPass *stubPass() const {
+ return nullptr;
+ }
+
+ /// Enable GOT pass to be run
+ virtual GOTPass *gotPass() const {
+ return nullptr;
+ }
+
+};
+
+
+
+
+///
+/// The only way to instantiate a WriterYAML object
+/// is via this createWriterYAML function. The is no public
+/// WriterYAML class that you might be tempted to subclass.
+/// Support for all variants must be represented in the WriterOptionsYAML
+/// object.
+/// The Writer object created retains a reference to the
+/// WriterOptionsYAML object supplied, so it must not be destroyed
+/// before the Writer object.
+///
+Writer* createWriterYAML(const WriterOptionsYAML &options);
+
+
+} // namespace lld
+
+#endif // LLD_READERWRITER_WRITER_YAML_H_
diff --git a/lld/lib/CMakeLists.txt b/lld/lib/CMakeLists.txt
index 2ce187cf1d6..6a0bf989e0a 100644
--- a/lld/lib/CMakeLists.txt
+++ b/lld/lib/CMakeLists.txt
@@ -1,4 +1,3 @@
add_subdirectory(Core)
add_subdirectory(Passes)
-add_subdirectory(Platforms)
-add_subdirectory(Reader)
+add_subdirectory(ReaderWriter)
diff --git a/lld/lib/Core/CMakeLists.txt b/lld/lib/Core/CMakeLists.txt
index 076d3351504..1a38b39d2a3 100644
--- a/lld/lib/Core/CMakeLists.txt
+++ b/lld/lib/Core/CMakeLists.txt
@@ -2,14 +2,6 @@ add_lld_library(lldCore
Error.cpp
File.cpp
InputFiles.cpp
- NativeFileFormat.h
- NativeReader.cpp
- NativeWriter.cpp
- Platform.cpp
Resolver.cpp
SymbolTable.cpp
- YamlKeyValues.cpp
- YamlKeyValues.h
- YamlReader.cpp
- YamlWriter.cpp
)
diff --git a/lld/lib/Core/InputFiles.cpp b/lld/lib/Core/InputFiles.cpp
index e9a423d9a30..78c8405c5ed 100644
--- a/lld/lib/Core/InputFiles.cpp
+++ b/lld/lib/Core/InputFiles.cpp
@@ -35,6 +35,12 @@ void InputFiles::appendFile(const File &file) {
_files.push_back(&file);
}
+void InputFiles::appendFiles(std::vector<std::unique_ptr<File>> &files) {
+ for (std::unique_ptr<File> &f : files) {
+ _files.push_back(f.release());
+ }
+}
+
bool InputFiles::searchLibraries(StringRef name, bool searchSharedLibs,
bool searchArchives, bool dataSymbolOnly,
diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp
index f16a67a94fe..d50a772fed3 100644
--- a/lld/lib/Core/Resolver.cpp
+++ b/lld/lib/Core/Resolver.cpp
@@ -7,15 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Resolver.h"
#include "lld/Core/Atom.h"
#include "lld/Core/File.h"
+#include "lld/Core/LLVM.h"
#include "lld/Core/InputFiles.h"
#include "lld/Core/LLVM.h"
+#include "lld/Core/Resolver.h"
#include "lld/Core/SymbolTable.h"
#include "lld/Core/UndefinedAtom.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"
@@ -65,6 +67,8 @@ private:
// add all atoms from all initial .o files
void Resolver::buildInitialAtomList() {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver initial atom list:\n");
+
// each input files contributes initial atoms
_atoms.reserve(1024);
_inputFiles.forEachInitialAtom(*this);
@@ -79,7 +83,14 @@ void Resolver::doFile(const File &file) {
void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
- // add to list of known atoms
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << " UndefinedAtom: "
+ << llvm::format("0x%09lX", &atom)
+ << ", name="
+ << atom.name()
+ << "\n");
+
+ // add to list of known atoms
_atoms.push_back(&atom);
// tell symbol table
@@ -89,6 +100,13 @@ void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
// called on each atom when a file is added
void Resolver::doDefinedAtom(const DefinedAtom &atom) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << " DefinedAtom: "
+ << llvm::format("0x%09lX", &atom)
+ << ", name="
+ << atom.name()
+ << "\n");
+
// add to list of known atoms
_atoms.push_back(&atom);
@@ -97,7 +115,7 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) {
// tell symbol table about non-static atoms
_symbolTable.add(atom);
}
-
+
if (_options.deadCodeStripping()) {
// add to set of dead-strip-roots, all symbols that
// the compiler marks as don't strip
@@ -107,6 +125,13 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) {
}
void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << " SharedLibraryAtom: "
+ << llvm::format("0x%09lX", &atom)
+ << ", name="
+ << atom.name()
+ << "\n");
+
// add to list of known atoms
_atoms.push_back(&atom);
@@ -115,6 +140,13 @@ void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
}
void Resolver::doAbsoluteAtom(const AbsoluteAtom& atom) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << " AbsoluteAtom: "
+ << llvm::format("0x%09lX", &atom)
+ << ", name="
+ << atom.name()
+ << "\n");
+
// add to list of known atoms
_atoms.push_back(&atom);
@@ -159,7 +191,7 @@ void Resolver::resolveUndefines() {
_symbolTable.tentativeDefinitions(tentDefNames);
for ( StringRef tentDefName : tentDefNames ) {
// Load for previous tentative may also have loaded
- // something that overrode this tentative, so always check.
+ // something that overrode this tentative, so always check.
const Atom *curAtom = _symbolTable.findByName(tentDefName);
assert(curAtom != nullptr);
if (const DefinedAtom* curDefAtom = dyn_cast<DefinedAtom>(curAtom)) {
@@ -228,7 +260,7 @@ void Resolver::deadStripOptimize() {
_deadStripRoots.insert(defAtom);
}
}
-
+
// Or, use list of names that are dead stip roots.
const std::vector<StringRef> &names = _options.deadStripRootNames();
for ( const StringRef &name : names ) {
@@ -332,7 +364,13 @@ void Resolver::MergedFile::addAtom(const Atom& atom) {
}
void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
for ( const Atom *atom : all ) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << llvm::format(" 0x%09lX", atom)
+ << ", name="
+ << atom->name()
+ << "\n");
this->addAtom(*atom);
}
}
diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp
index 0bfe6da6a78..8707fbeb421 100644
--- a/lld/lib/Core/SymbolTable.cpp
+++ b/lld/lib/Core/SymbolTable.cpp
@@ -173,7 +173,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
else {
if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
// FIXME: need diagonstics interface for writing warning messages
- llvm::errs() << "lld warning: undefined symbol "
+ llvm::errs() << "lld warning: undefined symbol "
<< existingUndef->name()
<< " has different weakness in "
<< existingUndef->file().path()
@@ -198,7 +198,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
useNew = false;
if ( _options.warnIfCoalesableAtomsHaveDifferentLoadName() ) {
// FIXME: need diagonstics interface for writing warning messages
- llvm::errs() << "lld warning: shared library symbol "
+ llvm::errs() << "lld warning: shared library symbol "
<< curShLib->name()
<< " has different load path in "
<< curShLib->file().path()
@@ -210,7 +210,7 @@ void SymbolTable::addByName(const Atom & newAtom) {
useNew = false;
if ( _options.warnIfCoalesableAtomsHaveDifferentCanBeNull() ) {
// FIXME: need diagonstics interface for writing warning messages
- llvm::errs() << "lld warning: shared library symbol "
+ llvm::errs() << "lld warning: shared library symbol "
<< curShLib->name()
<< " has different weakness in "
<< curShLib->file().path()
diff --git a/lld/lib/Passes/GOTPass.cpp b/lld/lib/Passes/GOTPass.cpp
index 9bbd08a2b1e..52b70e3c356 100644
--- a/lld/lib/Passes/GOTPass.cpp
+++ b/lld/lib/Passes/GOTPass.cpp
@@ -24,9 +24,9 @@
// is in the same linkage unit and does not need to be interposable, and
// the GOT use is just a load (not some other operation), this pass can
// transform that load into an LEA (add). This optimizes away one memory load
-// at runtime that could stall the pipeline. This optimization only works
+// which at runtime that could stall the pipeline. This optimization only works
// for architectures in which a (GOT) load instruction can be change to an
-// LEA instruction that is the same size. The platform method isGOTAccess()
+// LEA instruction that is the same size. The method isGOTAccess()
// should only return true for "canBypassGOT" if this optimization is supported.
//
//===----------------------------------------------------------------------===//
@@ -35,23 +35,21 @@
#include "lld/Core/File.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Pass.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/Reference.h"
-
#include "llvm/ADT/DenseMap.h"
namespace lld {
-void GOTPass::perform() {
+void GOTPass::perform(File& mergedFile) {
// Use map so all pointers to same symbol use same GOT entry.
llvm::DenseMap<const Atom*, const DefinedAtom*> targetToGOT;
// Scan all references in all atoms.
- for(const DefinedAtom *atom : _file.defined()) {
+ for(const DefinedAtom *atom : mergedFile.defined()) {
for (const Reference *ref : *atom) {
// Look at instructions accessing the GOT.
bool canBypassGOT;
- if ( _platform.isGOTAccess(ref->kind(), canBypassGOT) ) {
+ if ( this->isGOTAccess(ref->kind(), canBypassGOT) ) {
const Atom* target = ref->target();
assert(target != nullptr);
const DefinedAtom* defTarget = dyn_cast<DefinedAtom>(target);
@@ -72,14 +70,14 @@ void GOTPass::perform() {
// GOT to be by-passed, do that optimization and don't create
// GOT entry.
replaceTargetWithGOTAtom = !canBypassGOT;
- }
+ }
if ( replaceTargetWithGOTAtom ) {
// Replace the target with a reference to a GOT entry.
const DefinedAtom* gotEntry = nullptr;
auto pos = targetToGOT.find(target);
if ( pos == targetToGOT.end() ) {
// This is no existing GOT entry. Create a new one.
- gotEntry = _platform.makeGOTEntry(*target, _file);
+ gotEntry = this->makeGOTEntry(*target);
assert(gotEntry != nullptr);
assert(gotEntry->contentType() == DefinedAtom::typeGOT);
targetToGOT[target] = gotEntry;
@@ -92,16 +90,16 @@ void GOTPass::perform() {
// Switch reference to GOT atom.
(const_cast<Reference*>(ref))->setTarget(gotEntry);
}
- // Platform needs to update reference kind to reflect
- // that target is a GOT entry or a direct accesss.
- _platform.updateReferenceToGOT(ref, replaceTargetWithGOTAtom);
+ // Update reference kind to reflect
+ // that target is now a GOT entry or a direct accesss.
+ this->updateReferenceToGOT(ref, replaceTargetWithGOTAtom);
}
}
}
// add all created GOT Atoms to master file
for (auto it=targetToGOT.begin(), end=targetToGOT.end(); it != end; ++it) {
- _file.addAtom(*it->second);
+ mergedFile.addAtom(*it->second);
}
diff --git a/lld/lib/Passes/StubsPass.cpp b/lld/lib/Passes/StubsPass.cpp
index b81d0a27a39..c468959d2cc 100644
--- a/lld/lib/Passes/StubsPass.cpp
+++ b/lld/lib/Passes/StubsPass.cpp
@@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
//
-// This linker pass updates call sites which have references to shared library
+// This linker pass updates call-sites which have references to shared library
// atoms to instead have a reference to a stub (PLT entry) for the specified
-// symbol. The platform object does the work of creating the platform-specific
-// StubAtom.
+// symbol. Each file format defines a subclass of StubsPass which implements
+// the abstract methods for creating the file format specific StubAtoms.
//
//===----------------------------------------------------------------------===//
@@ -18,30 +18,28 @@
#include "lld/Core/File.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Pass.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/Reference.h"
-
#include "llvm/ADT/DenseMap.h"
namespace lld {
-void StubsPass::perform() {
+void StubsPass::perform(File& mergedFile) {
// Skip this pass if output format uses text relocations instead of stubs.
- if ( !_platform.noTextRelocs() )
+ if ( ! this->noTextRelocs() )
return;
// Scan all references in all atoms.
- for(const DefinedAtom *atom : _file.defined()) {
+ for(const DefinedAtom *atom : mergedFile.defined()) {
for (const Reference *ref : *atom) {
// Look at call-sites.
- if ( _platform.isCallSite(ref->kind()) ) {
+ if (this->isCallSite(ref->kind()) ) {
const Atom* target = ref->target();
assert(target != nullptr);
bool replaceCalleeWithStub = false;
if ( target->definition() == Atom::definitionSharedLibrary ) {
// Calls to shared libraries go through stubs.
replaceCalleeWithStub = true;
- }
+ }
else if (const DefinedAtom* defTarget =
dyn_cast<DefinedAtom>(target)) {
if ( defTarget->interposable() != DefinedAtom::interposeNo ) {
@@ -52,8 +50,8 @@ void StubsPass::perform() {
}
}
if ( replaceCalleeWithStub ) {
- // Ask platform to make stub and other support atoms.
- const DefinedAtom* stub = _platform.getStub(*target, _file);
+ // Make file-format specific stub and other support atoms.
+ const DefinedAtom* stub = this->getStub(*target);
assert(stub != nullptr);
// Switch call site to reference stub atom instead.
(const_cast<Reference*>(ref))->setTarget(stub);
@@ -62,8 +60,8 @@ void StubsPass::perform() {
}
}
- // Tell platform to add all created stubs and support Atoms to file.
- _platform.addStubAtoms(_file);
+ // Add all created stubs and support Atoms.
+ this->addStubAtoms(mergedFile);
}
diff --git a/lld/lib/Platforms/CMakeLists.txt b/lld/lib/Platforms/CMakeLists.txt
deleted file mode 100644
index 6bb912c33a2..00000000000
--- a/lld/lib/Platforms/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-add_subdirectory(Darwin)
diff --git a/lld/lib/Platforms/Darwin/CMakeLists.txt b/lld/lib/Platforms/Darwin/CMakeLists.txt
deleted file mode 100644
index 99dafc1cc83..00000000000
--- a/lld/lib/Platforms/Darwin/CMakeLists.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-add_lld_library(lldDarwinPlatform
- DarwinPlatform.cpp
- DarwinReferenceKinds.cpp
- ExecutableWriter.cpp
- )
diff --git a/lld/lib/Platforms/Darwin/DarwinPlatform.cpp b/lld/lib/Platforms/Darwin/DarwinPlatform.cpp
deleted file mode 100644
index 3fdc039095a..00000000000
--- a/lld/lib/Platforms/Darwin/DarwinPlatform.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-//===- Platforms/Darwin/DarwinPlatform.cpp --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DarwinPlatform.h"
-#include "MachOFormat.hpp"
-#include "StubAtoms.hpp"
-#include "ExecutableAtoms.hpp"
-#include "DarwinReferenceKinds.h"
-#include "ExecutableWriter.h"
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/InputFiles.h"
-
-#include "llvm/Support/ErrorHandling.h"
-
-namespace lld {
-
-Platform *createDarwinPlatform() {
- return new darwin::DarwinPlatform();
-}
-
-
-namespace darwin {
-
-DarwinPlatform::DarwinPlatform()
- : _helperCommonAtom(nullptr), _cRuntimeFile(nullptr) {
-}
-
-void DarwinPlatform::addFiles(InputFiles &inputFiles) {
- _cRuntimeFile = new CRuntimeFile();
- inputFiles.prependFile(*_cRuntimeFile);
-}
-
-Reference::Kind DarwinPlatform::kindFromString(StringRef kindName) {
- return ReferenceKind::fromString(kindName);
-}
-
-
-StringRef DarwinPlatform::kindToString(Reference::Kind kindValue) {
- return ReferenceKind::toString(kindValue);
-}
-
-bool DarwinPlatform::noTextRelocs() {
- return true;
-}
-
-
-bool DarwinPlatform::isCallSite(Reference::Kind kind) {
- return ReferenceKind::isCallSite(kind);
-}
-
-
-bool DarwinPlatform::isGOTAccess(Reference::Kind, bool& canBypassGOT) {
- return false;
-}
-
-
-void DarwinPlatform::updateReferenceToGOT(const Reference*, bool nowGOT) {
-}
-
-
-const DefinedAtom* DarwinPlatform::getStub(const Atom& target, File& file) {
- auto pos = _targetToStub.find(&target);
- if ( pos != _targetToStub.end() ) {
- // Reuse an existing stub.
- assert(pos->second != nullptr);
- return pos->second;
- }
- else {
- // There is no existing stub, so create a new one.
- if ( _helperCommonAtom == nullptr ) {
- // Lazily create common helper code and data.
- _helperCacheAtom = new X86_64NonLazyPointerAtom(file);
- _stubBinderAtom = new StubBinderAtom(file);
- _helperBinderAtom = new X86_64NonLazyPointerAtom(file, *_stubBinderAtom);
- _helperCommonAtom = new X86_64StubHelperCommonAtom(file,
- *_helperCacheAtom, *_helperBinderAtom);
- }
- const DefinedAtom* helper = new X86_64StubHelperAtom(file,
- *_helperCommonAtom);
- _stubHelperAtoms.push_back(helper);
- const DefinedAtom* lp = new X86_64LazyPointerAtom(file, *helper, target);
- assert(lp->contentType() == DefinedAtom::typeLazyPointer);
- const DefinedAtom* stub = new X86_64StubAtom(file, *lp);
- assert(stub->contentType() == DefinedAtom::typeStub);
- _targetToStub[&target] = stub;
- _lazyPointers.push_back(lp);
- return stub;
- }
-}
-
-
-void DarwinPlatform::addStubAtoms(File &file) {
- // Add all stubs to master file.
- for (auto it=_targetToStub.begin(), end=_targetToStub.end(); it != end; ++it) {
- file.addAtom(*it->second);
- }
- // Add helper code atoms.
- file.addAtom(*_helperCommonAtom);
- for (const DefinedAtom *lp : _stubHelperAtoms) {
- file.addAtom(*lp);
- }
- // Add GOT slots used for lazy binding.
- file.addAtom(*_helperBinderAtom);
- file.addAtom(*_helperCacheAtom);
- // Add all lazy pointers to master file.
- for (const DefinedAtom *lp : _lazyPointers) {
- file.addAtom(*lp);
- }
- // Add sharedlibrary atom
- file.addAtom(*_stubBinderAtom);
-}
-
-
-const DefinedAtom* DarwinPlatform::makeGOTEntry(const Atom&, File&) {
- return nullptr;
-}
-
-void DarwinPlatform::applyFixup(Reference::Kind kind, uint64_t addend,
- uint8_t* location, uint64_t fixupAddress,
- uint64_t targetAddress) {
- //fprintf(stderr, "applyFixup(kind=%s, addend=0x%0llX, "
- // "fixupAddress=0x%0llX, targetAddress=0x%0llX\n",
- // kindToString(kind).data(), addend,
- // fixupAddress, targetAddress);
- if ( ReferenceKind::isRipRel32(kind) ) {
- // compute rip relative value and update.
- int32_t* loc32 = reinterpret_cast<int32_t*>(location);
- *loc32 = (targetAddress - (fixupAddress+4)) + addend;
- }
- else if ( kind == ReferenceKind::pointer64 ) {
- uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
- *loc64 = targetAddress + addend;
- }
-}
-
-void DarwinPlatform::writeExecutable(const lld::File &file, raw_ostream &out) {
- lld::darwin::writeExecutable(file, *this, out);
-}
-
-
-uint64_t DarwinPlatform::pageZeroSize() {
- return 0x100000000;
-}
-
-
-void DarwinPlatform::initializeMachHeader(const lld::File& file,
- mach_header& mh) {
- // FIXME: Need to get cpu info from file object
- mh.magic = MAGIC_64;
- mh.cputype = CPU_TYPE_X86_64;
- mh.cpusubtype = CPU_SUBTYPE_X86_64_ALL;
- mh.filetype = MH_EXECUTE;
- mh.ncmds = 0;
- mh.sizeofcmds = 0;
- mh.flags = 0;
- mh.reserved = 0;
-}
-
-const Atom *DarwinPlatform::mainAtom() {
- assert(_cRuntimeFile != nullptr);
- const Atom *result = _cRuntimeFile->mainAtom();
- assert(result != nullptr);
- if ( result->definition() == Atom::definitionUndefined )
- llvm::report_fatal_error("_main not found");
- return _cRuntimeFile->mainAtom();
-}
-
-
-
-} // namespace darwin
-} // namespace lld
diff --git a/lld/lib/Platforms/Darwin/DarwinPlatform.h b/lld/lib/Platforms/Darwin/DarwinPlatform.h
deleted file mode 100644
index c05fb9c2bbb..00000000000
--- a/lld/lib/Platforms/Darwin/DarwinPlatform.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- Platform/DarwinPlatform.h - Darwin Platform Implementation ---------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_PLATFORM_DARWIN_PLATFORM_H_
-#define LLD_PLATFORM_DARWIN_PLATFORM_H_
-
-#include "lld/Core/Platform.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-
-namespace lld {
-namespace darwin {
-
-class DarwinPlatform : public Platform {
-public:
- DarwinPlatform();
-
-/// @name Platform methods
-/// @{
- virtual void addFiles(InputFiles&);
- virtual Reference::Kind kindFromString(llvm::StringRef);
- virtual llvm::StringRef kindToString(Reference::Kind);
- virtual bool noTextRelocs();
- virtual bool isCallSite(Reference::Kind);
- virtual bool isGOTAccess(Reference::Kind, bool& canBypassGOT);
- virtual void updateReferenceToGOT(const Reference*, bool targetIsNowGOT);
- virtual const DefinedAtom* getStub(const Atom&, File&);
- virtual void addStubAtoms(File &file);
- virtual const DefinedAtom* makeGOTEntry(const Atom&, File&);
- virtual void applyFixup(Reference::Kind, uint64_t addend, uint8_t*,
- uint64_t fixupAddress, uint64_t targetAddress);
- virtual void writeExecutable(const lld::File &, raw_ostream &out);
-/// @}
-/// @name Darwin specific methods
-/// @{
- uint64_t pageZeroSize();
- void initializeMachHeader(const lld::File& file, class mach_header& mh);
- const Atom *mainAtom();
-/// @}
-
-private:
- llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
- std::vector<const DefinedAtom*> _lazyPointers;
- std::vector<const DefinedAtom*> _stubHelperAtoms;
- const SharedLibraryAtom *_stubBinderAtom;
- const DefinedAtom* _helperCommonAtom;
- const DefinedAtom* _helperCacheAtom;
- const DefinedAtom* _helperBinderAtom;
- class CRuntimeFile *_cRuntimeFile;
-};
-
-} // namespace darwin
-} // namespace lld
-
-#endif // LLD_PLATFORM_DARWIN_PLATFORM_H_
diff --git a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp b/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp
deleted file mode 100644
index 3cc676c6884..00000000000
--- a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-//===- Platforms/Darwin/DarwinReferenceKinds.cpp --------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "DarwinReferenceKinds.h"
-#include "llvm/ADT/StringRef.h"
-
-
-namespace lld {
-namespace darwin {
-
-
-struct Mapping {
- const char* string;
- Reference::Kind value;
- uint32_t flags;
-};
-
-enum {
- flagsNone = 0x0000,
- flagsIsCallSite = 0x0001,
- flagsUsesGOT = 0x0002,
- flagsisGOTLoad = 0x0006,
- flags32RipRel = 0x1000,
-};
-
-
-static const Mapping sKindMappings[] = {
- { "none", ReferenceKind::none, flagsNone },
- { "call32", ReferenceKind::call32, flagsIsCallSite | flags32RipRel },
- { "pcrel32", ReferenceKind::pcRel32, flags32RipRel },
- { "gotLoad32", ReferenceKind::gotLoad32, flagsisGOTLoad | flags32RipRel },
- { "gotUse32", ReferenceKind::gotUse32, flagsUsesGOT | flags32RipRel },
- { "lea32wasGot", ReferenceKind::lea32WasGot, flags32RipRel },
- { "lazyTarget", ReferenceKind::lazyTarget, flagsNone },
- { "lazyImm", ReferenceKind::lazyImm, flagsNone },
- { "gotTarget", ReferenceKind::gotTarget, flagsNone },
- { "pointer64", ReferenceKind::pointer64, flagsNone },
- { NULL, ReferenceKind::none, flagsNone }
-};
-
-
-Reference::Kind ReferenceKind::fromString(StringRef kindName) {
- for (const Mapping* p = sKindMappings; p->string != NULL; ++p) {
- if ( kindName.equals(p->string) )
- return p->value;
- }
- assert(0 && "unknown darwin reference kind");
- return ReferenceKind::none;
-}
-
-StringRef ReferenceKind::toString(Reference::Kind kindValue) {
- for (const Mapping* p = sKindMappings; p->string != NULL; ++p) {
- if ( kindValue == p->value)
- return p->string;
- }
- return StringRef("???");
-}
-
-bool ReferenceKind::isCallSite(Reference::Kind kindValue) {
- for (const Mapping* p = sKindMappings; p->string != NULL; ++p) {
- if ( kindValue == p->value )
- return (p->flags & flagsIsCallSite);
- }
- return false;
-}
-
-bool ReferenceKind::isRipRel32(Reference::Kind kindValue) {
- for (const Mapping* p = sKindMappings; p->string != NULL; ++p) {
- if ( kindValue == p->value )
- return (p->flags & flags32RipRel);
- }
- return false;
-}
-
-
-
-
-
-} // namespace darwin
-} // namespace lld
-
-
-
diff --git a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.h b/lld/lib/Platforms/Darwin/DarwinReferenceKinds.h
deleted file mode 100644
index 9cb254235cf..00000000000
--- a/lld/lib/Platforms/Darwin/DarwinReferenceKinds.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- Platforms/Darwin/DarwinReferenceKinds.h ----------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "lld/Core/LLVM.h"
-#include "lld/Core/Reference.h"
-
-
-#ifndef LLD_PLATFORM_DARWIN_REFERENCE_KINDS_H_
-#define LLD_PLATFORM_DARWIN_REFERENCE_KINDS_H_
-
-namespace lld {
-namespace darwin {
-
-
-class ReferenceKind {
-public:
- enum {
- none = 0,
- call32 = 1,
- pcRel32 = 2,
- gotLoad32 = 3,
- gotUse32 = 4,
- lea32WasGot = 5,
- lazyTarget = 6,
- lazyImm = 7,
- gotTarget = 8,
- pointer64 = 9,
- };
-
- static Reference::Kind fromString(StringRef kindName);
-
- static StringRef toString(Reference::Kind kindValue);
-
- static bool isCallSite(Reference::Kind kindValue);
-
- static bool isRipRel32(Reference::Kind kindValue);
-};
-
-
-
-} // namespace darwin
-} // namespace lld
-
-
-
-#endif // LLD_PLATFORM_DARWIN_REFERENCE_KINDS_H_
-
diff --git a/lld/lib/Platforms/Darwin/ExecutableAtoms.hpp b/lld/lib/Platforms/Darwin/ExecutableAtoms.hpp
deleted file mode 100644
index 31bd181ccb3..00000000000
--- a/lld/lib/Platforms/Darwin/ExecutableAtoms.hpp
+++ /dev/null
@@ -1,84 +0,0 @@
-//===- Platforms/Darwin/x86_64StubAtom.hpp --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
-#define LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
-
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-
-#include "DarwinReferenceKinds.h"
-#include "SimpleAtoms.hpp"
-
-namespace lld {
-namespace darwin {
-
-
-//
-// EntryPointReferenceAtom is used to:
-// 1) Require "_main" is defined.
-// 2) Give Darwin Platform a pointer to the atom named "_main"
-//
-class EntryPointReferenceAtom : public SimpleDefinedAtom {
-public:
- EntryPointReferenceAtom(const File &file)
- : SimpleDefinedAtom(file)
- , _mainUndefAtom(file, "_main") {
- this->addReference(ReferenceKind::none, 0, &_mainUndefAtom, 0);
- }
-
- virtual ContentType contentType() const {
- return DefinedAtom::typeCode;
- }
-
- virtual uint64_t size() const {
- return 0;
- }
-
- virtual ContentPermissions permissions() const {
- return DefinedAtom::permR_X;
- }
-
- virtual ArrayRef<uint8_t> rawContent() const {
- return ArrayRef<uint8_t>();
- }
-private:
- friend class CRuntimeFile;
- SimpleUndefinedAtom _mainUndefAtom;
-};
-
-
-class CRuntimeFile : public SimpleFile {
-public:
- CRuntimeFile()
- : SimpleFile("C runtime")
- , _atom(*this) {
- this->addAtom(_atom);
- this->addAtom(_atom._mainUndefAtom);
- }
-
- const Atom *mainAtom() {
- const Reference *ref = *(_atom.begin());
- return ref->target();
- }
-
-private:
- EntryPointReferenceAtom _atom;
-};
-
-
-
-} // namespace darwin
-} // namespace lld
-
-
-#endif // LLD_PLATFORM_DARWIN_EXECUTABLE_ATOM_H_
diff --git a/lld/lib/Platforms/Darwin/ExecutableWriter.h b/lld/lib/Platforms/Darwin/ExecutableWriter.h
deleted file mode 100644
index 5980f85b6ad..00000000000
--- a/lld/lib/Platforms/Darwin/ExecutableWriter.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- Platforms/Darwin/ExecutableWriter.h --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "lld/Core/LLVM.h"
-
-
-#ifndef LLD_PLATFORM_DARWIN_EXECUTABLE_WRITER_H_
-#define LLD_PLATFORM_DARWIN_EXECUTABLE_WRITER_H_
-
-namespace lld {
-
-class File;
-
-namespace darwin {
-
-class DarwinPlatform;
-
-void writeExecutable(const lld::File &file, DarwinPlatform &platform,
- raw_ostream &out);
-
-
-} // namespace darwin
-} // namespace lld
-
-
-
-#endif // LLD_PLATFORM_DARWIN_EXECUTABLE_WRITER_H_
-
diff --git a/lld/lib/Reader/CMakeLists.txt b/lld/lib/Reader/CMakeLists.txt
deleted file mode 100644
index c8f2421649c..00000000000
--- a/lld/lib/Reader/CMakeLists.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-add_lld_library(lldReader
- COFFReader.cpp
- )
diff --git a/lld/lib/ReaderWriter/CMakeLists.txt b/lld/lib/ReaderWriter/CMakeLists.txt
new file mode 100644
index 00000000000..85ec90bc60f
--- /dev/null
+++ b/lld/lib/ReaderWriter/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_subdirectory(ELF)
+add_subdirectory(MachO)
+add_subdirectory(Native)
+add_subdirectory(PECOFF)
+add_subdirectory(YAML)
+add_lld_library(lldReaderWriter
+ Reader.cpp
+ Writer.cpp
+ )
diff --git a/lld/lib/ReaderWriter/ELF/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/CMakeLists.txt
new file mode 100644
index 00000000000..4a28b631915
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_lld_library(lldELF
+ ReaderELF.cpp
+ WriterELF.cpp
+ )
diff --git a/lld/lib/ReaderWriter/ELF/ReaderELF.cpp b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp
new file mode 100644
index 00000000000..ba23990ea0a
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/ReaderELF.cpp
@@ -0,0 +1,41 @@
+//===- lib/ReaderWriter/ELF/ReaderELF.cpp --------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/ReaderELF.h"
+#include "lld/Core/File.h"
+
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include <map>
+#include <vector>
+
+
+namespace lld {
+
+ReaderOptionsELF::ReaderOptionsELF() {
+}
+
+ReaderOptionsELF::~ReaderOptionsELF() {
+}
+
+
+
+Reader* createReaderELF(const ReaderOptionsELF &options) {
+ assert(0 && "ELF Reader not yet implemented");
+ return nullptr;
+}
+
+
+} // namespace
+
diff --git a/lld/lib/ReaderWriter/ELF/WriterELF.cpp b/lld/lib/ReaderWriter/ELF/WriterELF.cpp
new file mode 100644
index 00000000000..fe445b6f08e
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/WriterELF.cpp
@@ -0,0 +1,35 @@
+//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/WriterELF.h"
+
+#include "llvm/Support/Debug.h"
+
+
+namespace lld {
+namespace elf {
+
+// define ELF writer class here
+
+
+} // namespace elf
+
+Writer* createWriterELF(const WriterOptionsELF &options) {
+ assert(0 && "ELF support not implemented yet");
+ return nullptr;
+}
+
+WriterOptionsELF::WriterOptionsELF() {
+}
+
+WriterOptionsELF::~WriterOptionsELF() {
+}
+
+} // namespace lld
+
diff --git a/lld/lib/ReaderWriter/MachO/CMakeLists.txt b/lld/lib/ReaderWriter/MachO/CMakeLists.txt
new file mode 100644
index 00000000000..c6a1059802c
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_lld_library(lldMachO
+ WriterMachO.cpp
+ ReferenceKinds.cpp
+ )
diff --git a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
new file mode 100644
index 00000000000..ac80059624c
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
@@ -0,0 +1,50 @@
+//===- lib/ReaderWriter/MachO/ExecutableAtoms.hpp -------------------------===//
+//
+// 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_EXECUTABLE_ATOM_H_
+#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOM_H_
+
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+
+#include "lld/ReaderWriter/WriterMachO.h"
+
+#include "SimpleAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+//
+// CRuntimeFile adds an UndefinedAtom for "_main" so that the Resolving
+// phase will fail if "_main" is undefined.
+//
+class CRuntimeFile : public SimpleFile {
+public:
+ CRuntimeFile(const WriterOptionsMachO &options)
+ : SimpleFile("C runtime"), _undefMain(*this, "_main") {
+ // only main executables need _main
+ if ( options.outputKind() == WriterOptionsMachO::outputDynamicExecutable)
+ this->addAtom(_undefMain);
+ }
+
+private:
+ SimpleUndefinedAtom _undefMain;
+};
+
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOM_H_
diff --git a/lld/lib/ReaderWriter/MachO/GOTPass.hpp b/lld/lib/ReaderWriter/MachO/GOTPass.hpp
new file mode 100644
index 00000000000..6a7c451e448
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/GOTPass.hpp
@@ -0,0 +1,51 @@
+//===- lib/ReaderWriter/MachO/GOTPass.hpp ---------------------------------===//
+//
+// 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_GOT_PASS_H_
+#define LLD_READER_WRITER_MACHO_GOT_PASS_H_
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Pass.h"
+
+#include "ReferenceKinds.h"
+#include "StubAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+class GOTPass : public lld::GOTPass {
+public:
+ virtual bool noTextRelocs() {
+ return true;
+ }
+
+ virtual bool isGOTAccess(Reference::Kind, bool& canBypassGOT) {
+ return false;
+ }
+
+ virtual void updateReferenceToGOT(const Reference*, bool targetIsNowGOT) {
+
+ }
+
+ virtual const DefinedAtom* makeGOTEntry(const Atom&) {
+ return nullptr;
+ }
+
+};
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+#endif // LLD_READER_WRITER_MACHO_GOT_PASS_H_
diff --git a/lld/lib/Platforms/Darwin/MachOFormat.hpp b/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
index 55340aa6145..e6a04e1dd74 100644
--- a/lld/lib/Platforms/Darwin/MachOFormat.hpp
+++ b/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
@@ -1,4 +1,4 @@
-//===- Platforms/Darwin/MachOFormat.hpp -----------------------------------===//
+//===- lib/ReaderWriter/MachO/MachOFormat.hpp -----------------------------===//
//
// The LLVM Linker
//
@@ -15,22 +15,22 @@
//
#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Memory.h"
-
-#ifndef LLD_PLATFORM_DARWIN_MACHO_FORMAT_H_
-#define LLD_PLATFORM_DARWIN_MACHO_FORMAT_H_
+#ifndef LLD_READER_WRITER_MACHO_FORMAT_H_
+#define LLD_READER_WRITER_MACHO_FORMAT_H_
namespace lld {
-namespace darwin {
+namespace mach_o {
class load_command {
public:
uint32_t cmd;
uint32_t cmdsize;
- void write(raw_ostream& out) {
- out.write((char*)&cmd, cmdsize);
+ void copyTo(uint8_t* to, bool swap=false) {
+ ::memcpy(to, (uint8_t*)&cmd, cmdsize);
}
};
@@ -50,9 +50,13 @@ enum {
};
enum {
- MH_EXECUTE = 0x2,
- MH_DYLIB = 0x6,
- MH_BUNDLE = 0x8
+ MH_OBJECT = 0x1,
+ MH_EXECUTE = 0x2,
+ MH_DYLIB = 0x6,
+ MH_DYLINKER = 0x7,
+ MH_BUNDLE = 0x8,
+ MH_DYLIB_STUB = 0x9,
+ MH_KEXT_BUNDLE= 0xB
};
@@ -65,14 +69,14 @@ public:
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
- uint32_t reserved;
+ uint32_t reserved;
uint64_t size() {
return (magic == 0xfeedfacf) ? 32 : 28;
}
- void write(raw_ostream& out) {
- out.write((char*)&magic, this->size());
+ void copyTo(uint8_t* to, bool swap=false) {
+ ::memcpy(to, (char*)&magic, this->size());
}
void recordLoadCommand(const class load_command* lc) {
@@ -140,7 +144,11 @@ public:
// The segment_command_64 load commands has a nsect trailing
// section_64 records appended to the end.
static segment_command_64* make(unsigned sectCount) {
- unsigned size = sizeof(segment_command_64) + sectCount* sizeof(section_64);
+ // Compute size in portable way. Can't use offsetof() in non-POD class.
+ // Can't use zero size sections[] array above.
+ // So, since sizeof() already includes one section_64, subtract it off.
+ unsigned size = sizeof(segment_command_64)
+ + ((int)sectCount -1) * sizeof(section_64);
segment_command_64* result = reinterpret_cast<segment_command_64*>
(::calloc(1, size));
result->cmd = LC_SEGMENT_64;
@@ -194,8 +202,8 @@ public:
uint16_t n_desc;
uint64_t n_value;
- void write(raw_ostream& out) {
- out.write((char*)&n_strx, 16);
+ void copyTo(uint8_t* to, bool swap=false) {
+ ::memcpy(to, (uint8_t*)&n_strx, 16);
}
@@ -337,10 +345,10 @@ enum {
-} // namespace darwin
+} // namespace mach_o
} // namespace lld
-#endif // LLD_PLATFORM_DARWIN_MACHO_FORMAT_H_
+#endif // LLD_READER_WRITER_MACHO_FORMAT_H_
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
new file mode 100644
index 00000000000..a0b3dbfa5c6
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
@@ -0,0 +1,103 @@
+//===- lib/FileFormat/MachO/ReferenceKinds.cpp ----------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ReferenceKinds.h"
+
+#include "llvm/ADT/StringRef.h"
+
+
+namespace lld {
+namespace mach_o {
+
+
+struct Mapping {
+ const char* string;
+ Reference::Kind value;
+ uint32_t flags;
+};
+
+enum {
+ flagsNone = 0x0000,
+ flagsIsCallSite = 0x0001,
+ flagsUsesGOT = 0x0002,
+ flagsisGOTLoad = 0x0006,
+ flags32RipRel = 0x1000,
+};
+
+
+static const Mapping sKindMappingsx86_64[] = {
+ { "none", ReferenceKind::x86_64_none, flagsNone },
+ { "call32", ReferenceKind::x86_64_call32, flagsIsCallSite | flags32RipRel },
+ { "pcrel32", ReferenceKind::x86_64_pcRel32, flags32RipRel },
+ { "gotLoad32", ReferenceKind::x86_64_gotLoad32, flagsisGOTLoad | flags32RipRel },
+ { "gotUse32", ReferenceKind::x86_64_gotUse32, flagsUsesGOT | flags32RipRel },
+ { "lea32wasGot", ReferenceKind::x86_64_lea32WasGot, flags32RipRel },
+ { "lazyTarget", ReferenceKind::x86_64_lazyTarget, flagsNone },
+ { "lazyImm", ReferenceKind::x86_64_lazyImm, flagsNone },
+ { "gotTarget", ReferenceKind::x86_64_gotTarget, flagsNone },
+ { "pointer64", ReferenceKind::x86_64_pointer64, flagsNone },
+ { NULL, ReferenceKind::x86_64_none, flagsNone }
+};
+
+
+Reference::Kind ReferenceKind::fromString(StringRef kindName) {
+ for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
+ if ( kindName.equals(p->string) )
+ return p->value;
+ }
+ assert(0 && "unknown darwin reference kind");
+ return 0;
+}
+
+StringRef ReferenceKind::toString(Reference::Kind kindValue) {
+ for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
+ if ( kindValue == p->value)
+ return p->string;
+ }
+ return StringRef("???");
+}
+
+static const Mapping* mappingsForArch(WriterOptionsMachO::Architecture arch) {
+ switch ( arch ) {
+ case WriterOptionsMachO::arch_x86_64:
+ return sKindMappingsx86_64;
+ case WriterOptionsMachO::arch_x86:
+ case WriterOptionsMachO::arch_arm:
+ assert(0 && "references table not yet implemented for arch");
+ return nullptr;
+ }
+}
+
+bool ReferenceKind::isCallSite(WriterOptionsMachO::Architecture arch,
+ Reference::Kind kindValue) {
+ for (const Mapping* p = mappingsForArch(arch); p->string != NULL; ++p) {
+ if ( kindValue == p->value )
+ return (p->flags & flagsIsCallSite);
+ }
+ return false;
+}
+
+bool ReferenceKind::isRipRel32(Reference::Kind kindValue) {
+ for (const Mapping* p = sKindMappingsx86_64; p->string != NULL; ++p) {
+ if ( kindValue == p->value )
+ return (p->flags & flags32RipRel);
+ }
+ return false;
+}
+
+
+
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
new file mode 100644
index 00000000000..8680b346c2d
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
@@ -0,0 +1,77 @@
+//===- lib/FileFormat/MachO/ReferenceKinds.h ------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Reference.h"
+#include "lld/ReaderWriter/WriterMachO.h"
+
+#ifndef LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_
+#define LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_
+
+namespace lld {
+namespace mach_o {
+
+
+class ReferenceKind {
+public:
+ // x86_64 Reference Kinds
+ enum {
+ x86_64_none = 0,
+ x86_64_call32 = 1,
+ x86_64_pcRel32 = 2,
+ x86_64_gotLoad32 = 3,
+ x86_64_gotUse32 = 4,
+ x86_64_lea32WasGot = 5,
+ x86_64_lazyTarget = 6,
+ x86_64_lazyImm = 7,
+ x86_64_gotTarget = 8,
+ x86_64_pointer64 = 9,
+ };
+
+ // x86 Reference Kinds
+ enum {
+ x86_none = 0,
+ x86_call32 = 1,
+ x86_pointer32 = 2,
+ x86_lazyTarget = 3,
+ x86_lazyImm = 4,
+ // FIXME
+ };
+
+ // ARM Reference Kinds
+ enum {
+ arm_none = 0,
+ arm_br22 = 1,
+ arm_pointer32 = 2,
+ arm_lazyTarget = 3,
+ arm_lazyImm = 4,
+ // FIXME
+ };
+
+ static bool isCallSite(WriterOptionsMachO::Architecture arch,
+ Reference::Kind kindValue);
+
+ static bool isRipRel32(Reference::Kind kindValue);
+
+
+ static Reference::Kind fromString(StringRef kindName);
+ static StringRef toString(Reference::Kind kindValue);
+
+};
+
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+
+#endif // LLD_READER_WRITER_MACHO_REFERENCE_KINDS_H_
+
diff --git a/lld/lib/Platforms/Darwin/SimpleAtoms.hpp b/lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp
index f9c7aa0130d..498793f4746 100644
--- a/lld/lib/Platforms/Darwin/SimpleAtoms.hpp
+++ b/lld/lib/ReaderWriter/MachO/SimpleAtoms.hpp
@@ -1,4 +1,4 @@
-//===- Platforms/Darwin/x86_64StubAtom.hpp --------------------------------===//
+//===- lib/ReaderWriter/MachO/SimpleAtoms.hpp -----------------------------===//
//
// The LLVM Linker
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_PLATFORM_DARWIN_SIMPLE_ATOM_H_
-#define LLD_PLATFORM_DARWIN_SIMPLE_ATOM_H_
+#ifndef LLD_READER_WRITER_MACHO_SIMPLE_ATOM_H_
+#define LLD_READER_WRITER_MACHO_SIMPLE_ATOM_H_
#include <vector>
@@ -18,7 +18,7 @@
#include "lld/Core/Reference.h"
namespace lld {
-namespace darwin {
+namespace mach_o {
//
@@ -240,8 +240,8 @@ private:
-} // namespace darwin
+} // namespace mach_o
} // namespace lld
-#endif // LLD_PLATFORM_DARWIN_SIMPLE_ATOM_H_
+#endif // LLD_READER_WRITER_MACHO_SIMPLE_ATOM_H_
diff --git a/lld/lib/Platforms/Darwin/StubAtoms.hpp b/lld/lib/ReaderWriter/MachO/StubAtoms.hpp
index 1023d42010e..3e6bbe19737 100644
--- a/lld/lib/Platforms/Darwin/StubAtoms.hpp
+++ b/lld/lib/ReaderWriter/MachO/StubAtoms.hpp
@@ -1,4 +1,4 @@
-//===- Platforms/Darwin/x86_64StubAtom.hpp --------------------------------===//
+//===- lib/ReaderWriter/MachO/StubAtoms.hpp -------------------------------===//
//
// The LLVM Linker
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
-#define LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
+#ifndef LLD_READER_WRITER_MACHO_STUB_ATOM_H_
+#define LLD_READER_WRITER_MACHO_STUB_ATOM_H_
#include "llvm/ADT/ArrayRef.h"
@@ -17,11 +17,11 @@
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
-#include "DarwinReferenceKinds.h"
+#include "ReferenceKinds.h"
#include "SimpleAtoms.hpp"
namespace lld {
-namespace darwin {
+namespace mach_o {
//
@@ -31,7 +31,7 @@ class X86_64StubAtom : public SimpleDefinedAtom {
public:
X86_64StubAtom(const File &file, const Atom &lazyPointer)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::pcRel32, 2, &lazyPointer, 0);
+ this->addReference(ReferenceKind::x86_64_pcRel32, 2, &lazyPointer, 0);
}
virtual ContentType contentType() const {
@@ -64,8 +64,8 @@ public:
X86_64StubHelperCommonAtom(const File &file, const Atom &cache,
const Atom &binder)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::pcRel32, 3, &cache, 0);
- this->addReference(ReferenceKind::pcRel32, 11, &binder, 0);
+ this->addReference(ReferenceKind::x86_64_pcRel32, 3, &cache, 0);
+ this->addReference(ReferenceKind::x86_64_pcRel32, 11, &binder, 0);
}
virtual ContentType contentType() const {
@@ -101,8 +101,8 @@ class X86_64StubHelperAtom : public SimpleDefinedAtom {
public:
X86_64StubHelperAtom(const File &file, const Atom &helperCommon)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::lazyImm, 1, nullptr, 0);
- this->addReference(ReferenceKind::pcRel32, 6, &helperCommon, 0);
+ this->addReference(ReferenceKind::x86_64_lazyImm, 1, nullptr, 0);
+ this->addReference(ReferenceKind::x86_64_pcRel32, 6, &helperCommon, 0);
}
virtual ContentType contentType() const {
@@ -136,8 +136,8 @@ public:
X86_64LazyPointerAtom(const File &file, const Atom &helper,
const Atom &shlib)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::pointer64, 0, &helper, 0);
- this->addReference(ReferenceKind::lazyTarget, 0, &shlib, 0);
+ this->addReference(ReferenceKind::x86_64_pointer64, 0, &helper, 0);
+ this->addReference(ReferenceKind::x86_64_lazyTarget, 0, &shlib, 0);
}
virtual ContentType contentType() const {
@@ -172,7 +172,7 @@ public:
X86_64NonLazyPointerAtom(const File &file, const Atom &shlib)
: SimpleDefinedAtom(file) {
- this->addReference(ReferenceKind::pointer64, 0, &shlib, 0);
+ this->addReference(ReferenceKind::x86_64_pointer64, 0, &shlib, 0);
}
virtual ContentType contentType() const {
@@ -226,8 +226,8 @@ private:
-} // namespace darwin
+} // namespace mach_o
} // namespace lld
-#endif // LLD_PLATFORM_DARWIN_X86_64_STUB_ATOM_H_
+#endif // LLD_READER_WRITER_MACHO_STUB_ATOM_H_
diff --git a/lld/lib/ReaderWriter/MachO/StubsPass.hpp b/lld/lib/ReaderWriter/MachO/StubsPass.hpp
new file mode 100644
index 00000000000..34beaa220a6
--- /dev/null
+++ b/lld/lib/ReaderWriter/MachO/StubsPass.hpp
@@ -0,0 +1,145 @@
+//===- lib/ReaderWriter/MachO/StubsPass.hpp -------------------------------===//
+//
+// 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_STUBS_PASS_H_
+#define LLD_READER_WRITER_MACHO_STUBS_PASS_H_
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/SharedLibraryAtom.h"
+#include "lld/Core/File.h"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Pass.h"
+
+#include "ReferenceKinds.h"
+#include "SimpleAtoms.hpp"
+#include "StubAtoms.hpp"
+
+namespace lld {
+namespace mach_o {
+
+
+class StubsPass : public lld::StubsPass {
+public:
+ StubsPass(const WriterOptionsMachO &options) : _options(options) {
+ }
+
+ virtual bool noTextRelocs() {
+ return _options.noTextRelocations();
+ }
+
+ virtual bool isCallSite(Reference::Kind kind) {
+ return ReferenceKind::isCallSite(_options.architecture(), kind);
+ }
+
+ virtual const DefinedAtom* getStub(const Atom& target) {
+ auto pos = _targetToStub.find(&target);
+ if ( pos != _targetToStub.end() ) {
+ // Reuse an existing stub.
+ assert(pos->second != nullptr);
+ return pos->second;
+ }
+ else {
+ // There is no existing stub, so create a new one.
+ return this->makeStub(target);
+ }
+ }
+
+ const DefinedAtom* makeStub(const Atom& target) {
+ switch ( _options.architecture() ) {
+ case WriterOptionsMachO::arch_x86_64:
+ return makeStub_x86_64(target);
+
+ case WriterOptionsMachO::arch_x86:
+ return makeStub_x86(target);
+
+ case WriterOptionsMachO::arch_arm:
+ return makeStub_arm(target);
+ }
+ }
+
+ const DefinedAtom* makeStub_x86_64(const Atom& target) {
+ if ( _helperCommonAtom == nullptr ) {
+ // Lazily create common helper code and data.
+ _helperCacheAtom = new X86_64NonLazyPointerAtom(_file);
+ _binderAtom = new StubBinderAtom(_file);
+ _helperBinderAtom = new X86_64NonLazyPointerAtom(_file, *_binderAtom);
+ _helperCommonAtom = new X86_64StubHelperCommonAtom(_file,
+ *_helperCacheAtom, *_helperBinderAtom);
+ }
+ const DefinedAtom* helper = new X86_64StubHelperAtom(_file,
+ *_helperCommonAtom);
+ _stubHelperAtoms.push_back(helper);
+ const DefinedAtom* lp = new X86_64LazyPointerAtom(_file, *helper, target);
+ assert(lp->contentType() == DefinedAtom::typeLazyPointer);
+ _lazyPointers.push_back(lp);
+ const DefinedAtom* stub = new X86_64StubAtom(_file, *lp);
+ assert(stub->contentType() == DefinedAtom::typeStub);
+ _targetToStub[&target] = stub;
+ return stub;
+ }
+
+ const DefinedAtom* makeStub_x86(const Atom& target) {
+ assert(0 && "stubs not yet implemented for x86");
+ return nullptr;
+ }
+
+ const DefinedAtom* makeStub_arm(const Atom& target) {
+ assert(0 && "stubs not yet implemented for arm");
+ return nullptr;
+ }
+
+
+ virtual void addStubAtoms(File &mergedFile) {
+ // Add all stubs to master file.
+ for (auto it : _targetToStub) {
+ mergedFile.addAtom(*it.second);
+ }
+ // Add helper code atoms.
+ mergedFile.addAtom(*_helperCommonAtom);
+ for (const DefinedAtom *lp : _stubHelperAtoms) {
+ mergedFile.addAtom(*lp);
+ }
+ // Add GOT slots used for lazy binding.
+ mergedFile.addAtom(*_helperBinderAtom);
+ mergedFile.addAtom(*_helperCacheAtom);
+ // Add all lazy pointers to master file.
+ for (const DefinedAtom *lp : _lazyPointers) {
+ mergedFile.addAtom(*lp);
+ }
+ // Add sharedlibrary atom
+ mergedFile.addAtom(*_binderAtom);
+ }
+
+private:
+
+ class File : public SimpleFile {
+ public:
+ File() : SimpleFile("MachO Stubs pass") {
+ }
+ };
+
+ const WriterOptionsMachO &_options;
+ File _file;
+ llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
+ std::vector<const DefinedAtom*> _lazyPointers;
+ std::vector<const DefinedAtom*> _stubHelperAtoms;
+ const SharedLibraryAtom *_binderAtom;
+ const DefinedAtom* _helperCommonAtom;
+ const DefinedAtom* _helperCacheAtom;
+ const DefinedAtom* _helperBinderAtom;
+};
+
+
+} // namespace mach_o
+} // namespace lld
+
+
+#endif // LLD_READER_WRITER_MACHO_STUBS_PASS_H_
diff --git a/lld/lib/Platforms/Darwin/ExecutableWriter.cpp b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
index 42c62a55f76..3d91a8a5040 100644
--- a/lld/lib/Platforms/Darwin/ExecutableWriter.cpp
+++ b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
@@ -1,4 +1,4 @@
-//===- Platforms/Darwin/ExecutableWriter.cpp ------------------------------===//
+//===- lib/ReaderWriter/MachO/WriterMachO.cpp -----------------------------===//
//
// The LLVM Linker
//
@@ -7,33 +7,42 @@
//
//===----------------------------------------------------------------------===//
-#include "ExecutableWriter.h"
-#include "MachOFormat.hpp"
-#include "DarwinReferenceKinds.h"
-#include "DarwinPlatform.h"
-
-#include <vector>
-#include <map>
-
-#include <string.h>
+#include "lld/ReaderWriter/WriterMachO.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+//#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/File.h"
+#include "lld/Core/InputFiles.h"
#include "lld/Core/Reference.h"
+#include "lld/Core/SharedLibraryAtom.h"
+
+#include <vector>
+#include <map>
+#include <string.h>
+
+#include "MachOFormat.hpp"
+#include "ReferenceKinds.h"
+#include "ExecutableAtoms.hpp"
+#include "GOTPass.hpp"
+#include "StubsPass.hpp"
namespace lld {
-namespace darwin {
+namespace mach_o {
//
// A mach-o file consists of some meta data (header and load commands),
@@ -66,8 +75,7 @@ class Chunk {
public:
virtual StringRef segmentName() const = 0;
virtual bool occupiesNoDiskSpace();
- virtual void write(raw_ostream &out) = 0;
- static void writeZeros(uint64_t amount, raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer) = 0;
void assignFileOffset(uint64_t &curOff, uint64_t &curAddr);
virtual const char* info() = 0;
uint64_t size() const;
@@ -95,11 +103,11 @@ protected:
class SectionChunk : public Chunk {
public:
static SectionChunk* make(DefinedAtom::ContentType,
- DarwinPlatform &platform,
+ const WriterOptionsMachO &options,
class MachOWriter &writer);
virtual StringRef segmentName() const;
virtual bool occupiesNoDiskSpace();
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual const char* info();
StringRef sectionName();
uint32_t flags() const;
@@ -117,16 +125,20 @@ private:
SectionChunk(StringRef seg,
StringRef sect,
uint32_t flags,
- DarwinPlatform &platform,
+ const WriterOptionsMachO &options,
class MachOWriter &writer);
- StringRef _segmentName;
- StringRef _sectionName;
- DarwinPlatform &_platform;
- class MachOWriter &_writer;
- uint32_t _flags;
- uint32_t _permissions;
- std::vector<AtomInfo> _atoms;
+ void applyFixup(Reference::Kind kind, uint64_t addend,
+ uint8_t* location, uint64_t fixupAddress,
+ uint64_t targetAddress);
+
+ StringRef _segmentName;
+ StringRef _sectionName;
+ const WriterOptionsMachO &_options;
+ class MachOWriter &_writer;
+ uint32_t _flags;
+ uint32_t _permissions;
+ std::vector<AtomInfo> _atoms;
};
@@ -137,14 +149,17 @@ private:
//
class MachHeaderChunk : public Chunk {
public:
- MachHeaderChunk(DarwinPlatform &plat, const File &file);
+ MachHeaderChunk(const WriterOptionsMachO &options,
+ const File &file);
virtual StringRef segmentName() const;
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual const char* info();
void recordLoadCommand(load_command*);
uint64_t loadCommandsSize();
private:
+ uint32_t filetype(WriterOptionsMachO::OutputKind kind);
+
mach_header _mh;
};
@@ -158,10 +173,10 @@ private:
class LoadCommandsChunk : public Chunk {
public:
LoadCommandsChunk(MachHeaderChunk&,
- DarwinPlatform&,
+ const WriterOptionsMachO &options,
class MachOWriter&);
virtual StringRef segmentName() const;
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual const char* info();
void computeSize(const lld::File &file);
void addSection(SectionChunk*);
@@ -183,7 +198,7 @@ private:
};
MachHeaderChunk &_mh;
- DarwinPlatform &_platform;
+ const WriterOptionsMachO &_options;
class MachOWriter &_writer;
segment_command_64 *_linkEditSegment;
symtab_command *_symbolTableLoadCommand;
@@ -204,7 +219,7 @@ class LoadCommandPaddingChunk : public Chunk {
public:
LoadCommandPaddingChunk(LoadCommandsChunk&);
virtual StringRef segmentName() const;
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual const char* info();
void computeSize();
private:
@@ -234,7 +249,7 @@ public:
class DyldInfoChunk : public LinkEditChunk {
public:
DyldInfoChunk(class MachOWriter &);
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
protected:
void append_byte(uint8_t);
@@ -283,7 +298,7 @@ private:
class SymbolTableChunk : public LinkEditChunk {
public:
SymbolTableChunk(class SymbolStringsChunk&);
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual void computeSize(const lld::File &file,
const std::vector<SectionChunk*>&);
virtual const char* info();
@@ -307,7 +322,7 @@ private:
class SymbolStringsChunk : public LinkEditChunk {
public:
SymbolStringsChunk();
- virtual void write(raw_ostream &out);
+ virtual void write(uint8_t *fileBuffer);
virtual void computeSize(const lld::File &file,
const std::vector<SectionChunk*>&);
virtual const char* info();
@@ -321,14 +336,16 @@ private:
//
// A MachOWriter manages all the Chunks that comprise a mach-o executable.
//
-class MachOWriter {
+class MachOWriter : public Writer {
public:
- MachOWriter(DarwinPlatform &platform);
- void build(const lld::File &file);
- void write(raw_ostream &out);
+ MachOWriter(const WriterOptionsMachO &options);
+
+ virtual error_code writeFile(const lld::File &file, StringRef path);
+ virtual StubsPass *stubPass();
+ virtual GOTPass *gotPass();
+ virtual void addFiles(InputFiles&);
uint64_t addressOfAtom(const Atom *atom);
- void zeroFill(int64_t amount, raw_ostream &out);
void findSegment(StringRef segmentName, uint32_t *segIndex,
uint64_t *segStartAddr, uint64_t *segEndAddr);
@@ -338,6 +355,7 @@ private:
friend class LoadCommandsChunk;
friend class LazyBindingInfoChunk;
+ void build(const lld::File &file);
void createChunks(const lld::File &file);
void buildAtomToAddressMap();
void assignFileOffsets();
@@ -349,7 +367,10 @@ private:
typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
- DarwinPlatform &_platform;
+ const WriterOptionsMachO &_options;
+ StubsPass _stubsPass;
+ GOTPass _gotPass;
+ CRuntimeFile _cRuntimeFile;
LoadCommandsChunk *_loadCommandsChunk;
LoadCommandPaddingChunk *_paddingChunk;
AtomToAddress _atomToAddress;
@@ -360,6 +381,7 @@ private:
LazyBindingInfoChunk *_lazyBindingInfo;
SymbolTableChunk *_symbolTableChunk;
SymbolStringsChunk *_stringsChunk;
+ const DefinedAtom *_mainAtom;
uint64_t _linkEditStartOffset;
uint64_t _linkEditStartAddress;
};
@@ -394,12 +416,6 @@ uint64_t Chunk::fileOffset() const {
return _fileOffset;
}
-
-void Chunk::writeZeros(uint64_t amount, raw_ostream &out) {
- for( int i=amount; i > 0; --i)
- out.write('\0');
-}
-
uint64_t Chunk::alignTo(uint64_t value, uint8_t align2) {
uint64_t align = 1 << align2;
return ( (value + (align-1)) & (-align) );
@@ -420,11 +436,13 @@ void Chunk::assignFileOffset(uint64_t &curOffset, uint64_t &curAddress) {
curOffset = _fileOffset + _size;
curAddress = _address + _size;
}
- DEBUG(llvm::dbgs() << " fileOffset=0x";
- llvm::dbgs().write_hex(_fileOffset);
- llvm::dbgs() << " address=0x";
- llvm::dbgs().write_hex(_address);
- llvm::dbgs() << " info=" << this->info() << "\n");
+
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << " fileOffset="
+ << llvm::format("0x%08X", _fileOffset)
+ << " address="
+ << llvm::format("0x%016X", _address)
+ << " info=" << this->info() << "\n");
}
@@ -434,46 +452,46 @@ void Chunk::assignFileOffset(uint64_t &curOffset, uint64_t &curAddress) {
//===----------------------------------------------------------------------===//
SectionChunk::SectionChunk(StringRef seg, StringRef sect,
- uint32_t flags, DarwinPlatform &platform,
+ uint32_t flags, const WriterOptionsMachO &options,
MachOWriter &writer)
- : _segmentName(seg), _sectionName(sect), _platform(platform),
+ : _segmentName(seg), _sectionName(sect), _options(options),
_writer(writer), _flags(flags), _permissions(0) {
}
SectionChunk* SectionChunk::make(DefinedAtom::ContentType type,
- DarwinPlatform &platform,
+ const WriterOptionsMachO &options,
MachOWriter &writer) {
switch ( type ) {
case DefinedAtom::typeCode:
return new SectionChunk("__TEXT", "__text",
S_REGULAR | S_ATTR_PURE_INSTRUCTIONS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeCString:
return new SectionChunk("__TEXT", "__cstring",
S_CSTRING_LITERALS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeStub:
return new SectionChunk("__TEXT", "__stubs",
S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeStubHelper:
return new SectionChunk("__TEXT", "__stub_helper",
S_REGULAR | S_ATTR_PURE_INSTRUCTIONS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeLazyPointer:
return new SectionChunk("__DATA", "__la_symbol_ptr",
S_LAZY_SYMBOL_POINTERS,
- platform, writer);
+ options, writer);
break;
case DefinedAtom::typeGOT:
return new SectionChunk("__DATA", "__got",
S_NON_LAZY_SYMBOL_POINTERS,
- platform, writer);
+ options, writer);
break;
default:
assert(0 && "TO DO: add support for more sections");
@@ -542,46 +560,67 @@ void SectionChunk::appendAtom(const DefinedAtom *atom) {
}
-void SectionChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
- SmallVector<uint8_t, 1024> buffer;
+void SectionChunk::write(uint8_t *chunkBuffer) {
// Each section's content is just its atoms' content.
for (const AtomInfo &atomInfo : _atoms ) {
- uint64_t atomFileOffset = _fileOffset + atomInfo.offsetInSection;
- if ( atomFileOffset != out.tell() ) {
- // Need to add alignment padding before this atom starts.
- assert(atomFileOffset > out.tell());
- this->writeZeros(atomFileOffset - out.tell(), out);
- }
- // Copy raw content of atom.
+ // Copy raw content of atom to file buffer.
ArrayRef<uint8_t> content = atomInfo.atom->rawContent();
uint64_t contentSize = content.size();
- buffer.resize(contentSize);
if ( contentSize == 0 )
continue;
- ::memcpy(buffer.data(), content.data(), content.size());
+ uint8_t* atomContent = chunkBuffer + atomInfo.offsetInSection;
+ ::memcpy(atomContent, content.data(), contentSize);
+ // Apply fixups to file buffer
for (const Reference *ref : *atomInfo.atom) {
uint32_t offset = ref->offsetInAtom();
uint64_t targetAddress = 0;
if ( ref->target() != nullptr )
targetAddress = _writer.addressOfAtom(ref->target());
uint64_t fixupAddress = _writer.addressOfAtom(atomInfo.atom) + offset;
- _platform.applyFixup(ref->kind(), ref->addend(), &buffer[offset],
+ this->applyFixup(ref->kind(), ref->addend(), &atomContent[offset],
fixupAddress, targetAddress);
}
- for( uint8_t byte : buffer) {
- out.write(byte);
- }
}
}
+
+
+void SectionChunk::applyFixup(Reference::Kind kind, uint64_t addend,
+ uint8_t* location, uint64_t fixupAddress,
+ uint64_t targetAddress) {
+ //fprintf(stderr, "applyFixup(kind=%s, addend=0x%0llX, "
+ // "fixupAddress=0x%0llX, targetAddress=0x%0llX\n",
+ // kindToString(kind).data(), addend,
+ // fixupAddress, targetAddress);
+ if ( ReferenceKind::isRipRel32(kind) ) {
+ // compute rip relative value and update.
+ int32_t* loc32 = reinterpret_cast<int32_t*>(location);
+ *loc32 = (targetAddress - (fixupAddress+4)) + addend;
+ }
+ else if ( kind == ReferenceKind::x86_64_pointer64 ) {
+ uint64_t* loc64 = reinterpret_cast<uint64_t*>(location);
+ *loc64 = targetAddress + addend;
+ }
+}
+
+
+
//===----------------------------------------------------------------------===//
// MachHeaderChunk
//===----------------------------------------------------------------------===//
-MachHeaderChunk::MachHeaderChunk(DarwinPlatform &platform, const File &file) {
- // Let platform convert file info to mach-o cpu type and subtype.
- platform.initializeMachHeader(file, _mh);
+MachHeaderChunk::MachHeaderChunk(const WriterOptionsMachO &options,
+ const File &file) {
+ // Set up mach_header based on options
+ _mh.magic = MAGIC_64;
+ _mh.cputype = options.cpuType();
+ _mh.cpusubtype = options.cpuSubtype();
+ _mh.filetype = this->filetype(options.outputKind());
+ _mh.ncmds = 0;
+ _mh.sizeofcmds = 0;
+ _mh.flags = 0;
+ _mh.reserved = 0;
+
_size = _mh.size();
}
@@ -590,9 +629,8 @@ StringRef MachHeaderChunk::segmentName() const {
return StringRef("__TEXT");
}
-void MachHeaderChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
- _mh.write(out);
+void MachHeaderChunk::write(uint8_t *chunkBuffer) {
+ _mh.copyTo(chunkBuffer);
}
const char* MachHeaderChunk::info() {
@@ -607,6 +645,20 @@ uint64_t MachHeaderChunk::loadCommandsSize() {
return _mh.sizeofcmds;
}
+uint32_t MachHeaderChunk::filetype(WriterOptionsMachO::OutputKind kind) {
+ switch ( kind ) {
+ case WriterOptionsMachO::outputDynamicExecutable:
+ return MH_EXECUTE;
+ case WriterOptionsMachO::outputDylib:
+ return MH_DYLIB;
+ case WriterOptionsMachO::outputBundle:
+ return MH_BUNDLE;
+ case WriterOptionsMachO::outputObjectFile:
+ return MH_OBJECT;
+ }
+ assert(0 && "file outputkind not supported");
+}
+
//===----------------------------------------------------------------------===//
@@ -614,9 +666,9 @@ uint64_t MachHeaderChunk::loadCommandsSize() {
//===----------------------------------------------------------------------===//
LoadCommandsChunk::LoadCommandsChunk(MachHeaderChunk &mh,
- DarwinPlatform& platform,
+ const WriterOptionsMachO &options,
MachOWriter& writer)
- : _mh(mh), _platform(platform), _writer(writer),
+ : _mh(mh), _options(options), _writer(writer),
_linkEditSegment(nullptr), _symbolTableLoadCommand(nullptr),
_entryPointLoadCommand(nullptr), _dyldInfoLoadCommand(nullptr) {
}
@@ -626,10 +678,12 @@ StringRef LoadCommandsChunk::segmentName() const {
return StringRef("__TEXT");
}
-void LoadCommandsChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
+void LoadCommandsChunk::write(uint8_t *chunkBuffer) {
+ uint8_t* p = chunkBuffer;
for ( load_command* lc : _loadCmds ) {
- lc->write(out);
+ assert( ((uintptr_t)p & 0x3) == 0);
+ lc->copyTo(p);
+ p += lc->cmdsize;
}
}
@@ -660,7 +714,7 @@ uint32_t LoadCommandsChunk::permissionsFromSections(
void LoadCommandsChunk::computeSize(const lld::File &file) {
// Main executables have a __PAGEZERO segment.
- uint64_t pageZeroSize = _platform.pageZeroSize();
+ uint64_t pageZeroSize = _options.pageZeroSize();
if ( pageZeroSize != 0 ) {
segment_command_64* pzSegCmd = segment_command_64::make(0);
strcpy(pzSegCmd->segname, "__PAGEZERO");
@@ -741,10 +795,12 @@ void LoadCommandsChunk::computeSize(const lld::File &file) {
_dyldInfoLoadCommand = dyld_info_command::make();
this->addLoadCommand(_dyldInfoLoadCommand);
- // Add entry point load command
- _entryPointLoadCommand = entry_point_command::make();
- this->addLoadCommand(_entryPointLoadCommand);
-
+ // Add entry point load command to main executables
+ if (_options.outputKind() == WriterOptionsMachO::outputDynamicExecutable) {
+ _entryPointLoadCommand = entry_point_command::make();
+ this->addLoadCommand(_entryPointLoadCommand);
+ }
+
// Compute total size.
_size = _mh.loadCommandsSize();
}
@@ -812,7 +868,7 @@ void LoadCommandsChunk::updateLoadCommandContent(const lld::File &file) {
// Update entry point
if ( _entryPointLoadCommand != nullptr ) {
- const Atom *mainAtom = _platform.mainAtom();
+ const Atom *mainAtom = _writer._mainAtom;
assert(mainAtom != nullptr);
uint32_t entryOffset = _writer.addressOfAtom(mainAtom) - _mh.address();
_entryPointLoadCommand->entryoff = entryOffset;
@@ -844,10 +900,8 @@ StringRef LoadCommandPaddingChunk::segmentName() const {
return StringRef("__TEXT");
}
-void LoadCommandPaddingChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
+void LoadCommandPaddingChunk::write(uint8_t *chunkBuffer) {
// Zero fill padding.
- this->writeZeros(_size, out);
}
const char* LoadCommandPaddingChunk::info() {
@@ -899,11 +953,8 @@ DyldInfoChunk::DyldInfoChunk(MachOWriter &writer)
: _writer(writer) {
}
-void DyldInfoChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
- for ( uint8_t byte : _bytes ) {
- out.write(byte);
- }
+void DyldInfoChunk::write(uint8_t *chunkBuffer) {
+ ::memcpy(chunkBuffer, &_bytes[0], _bytes.size());
}
void DyldInfoChunk::append_byte(uint8_t b) {
@@ -967,7 +1018,7 @@ void BindingInfoChunk::computeSize(const lld::File &file,
const SharedLibraryAtom *shlTarget
= dyn_cast<SharedLibraryAtom>(target);
if ( shlTarget != nullptr ) {
- assert(ref->kind() == ReferenceKind::pointer64);
+ assert(ref->kind() == ReferenceKind::x86_64_pointer64);
targetName = shlTarget->name();
ordinal = 1;
}
@@ -1029,12 +1080,12 @@ const char* LazyBindingInfoChunk::info() {
void LazyBindingInfoChunk::updateHelper(const DefinedAtom *lazyPointerAtom,
uint32_t offset) {
for (const Reference *ref : *lazyPointerAtom ) {
- if ( ref->kind() != ReferenceKind::pointer64 )
+ if ( ref->kind() != ReferenceKind::x86_64_pointer64 )
continue;
const DefinedAtom *helperAtom = dyn_cast<DefinedAtom>(ref->target());
assert(helperAtom != nullptr);
for (const Reference *href : *helperAtom ) {
- if ( href->kind() == ReferenceKind::lazyImm ) {
+ if ( href->kind() == ReferenceKind::x86_64_lazyImm ) {
(const_cast<Reference*>(href))->setAddend(offset);
return;
}
@@ -1084,7 +1135,7 @@ void LazyBindingInfoChunk::computeSize(const lld::File &file,
int flags = 0;
StringRef name;
for (const Reference *ref : *lazyPointerAtom ) {
- if ( ref->kind() == ReferenceKind::lazyTarget ) {
+ if ( ref->kind() == ReferenceKind::x86_64_lazyTarget ) {
const Atom *shlib = ref->target();
assert(shlib != nullptr);
name = shlib->name();
@@ -1111,16 +1162,19 @@ SymbolTableChunk::SymbolTableChunk(SymbolStringsChunk& str)
: _stringsChunk(str) {
}
-void SymbolTableChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
+void SymbolTableChunk::write(uint8_t *chunkBuffer) {
+ uint8_t *p = chunkBuffer;
for ( nlist_64 &sym : _globalDefinedsymbols ) {
- sym.write(out);
+ sym.copyTo(p);
+ p += sizeof(nlist_64);
}
for ( nlist_64 &sym : _localDefinedsymbols ) {
- sym.write(out);
+ sym.copyTo(p);
+ p += sizeof(nlist_64);
}
for ( nlist_64 &sym : _undefinedsymbols ) {
- sym.write(out);
+ sym.copyTo(p);
+ p += sizeof(nlist_64);
}
}
@@ -1196,11 +1250,8 @@ SymbolStringsChunk::SymbolStringsChunk() {
}
-void SymbolStringsChunk::write(raw_ostream &out) {
- assert( out.tell() == _fileOffset);
- for ( char c : _strings ) {
- out.write(c);
- }
+void SymbolStringsChunk::write(uint8_t *chunkBuffer) {
+ ::memcpy(chunkBuffer, &_strings[0], _strings.size());
}
const char* SymbolStringsChunk::info() {
@@ -1225,9 +1276,10 @@ uint32_t SymbolStringsChunk::stringIndex(StringRef str) {
// MachOWriter
//===----------------------------------------------------------------------===//
-MachOWriter::MachOWriter(DarwinPlatform &platform)
- : _platform(platform), _bindingInfo(nullptr), _lazyBindingInfo(nullptr),
- _symbolTableChunk(nullptr), _stringsChunk(nullptr),
+MachOWriter::MachOWriter(const WriterOptionsMachO &options)
+ : _options(options), _stubsPass(options), _cRuntimeFile(options),
+ _bindingInfo(nullptr), _lazyBindingInfo(nullptr),
+ _symbolTableChunk(nullptr), _stringsChunk(nullptr), _mainAtom(nullptr),
_linkEditStartOffset(0), _linkEditStartAddress(0) {
}
@@ -1266,7 +1318,7 @@ void MachOWriter::createChunks(const lld::File &file) {
DefinedAtom::ContentType type = atom->contentType();
auto pos = map.find(type);
if ( pos == map.end() ) {
- SectionChunk *chunk = SectionChunk::make(type, _platform, *this);
+ SectionChunk *chunk = SectionChunk::make(type, _options, *this);
map[type] = chunk;
chunk->appendAtom(atom);
}
@@ -1279,10 +1331,10 @@ void MachOWriter::createChunks(const lld::File &file) {
// Make chunks in __TEXT for mach_header and load commands at start.
- MachHeaderChunk *mhc = new MachHeaderChunk(_platform, file);
+ MachHeaderChunk *mhc = new MachHeaderChunk(_options, file);
_chunks.push_back(mhc);
- _loadCommandsChunk = new LoadCommandsChunk(*mhc, _platform, *this);
+ _loadCommandsChunk = new LoadCommandsChunk(*mhc, _options, *this);
_chunks.push_back(_loadCommandsChunk);
_paddingChunk = new LoadCommandPaddingChunk(*_loadCommandsChunk);
@@ -1313,19 +1365,28 @@ void MachOWriter::addLinkEditChunk(LinkEditChunk *chunk) {
void MachOWriter::buildAtomToAddressMap() {
- DEBUG(llvm::dbgs() << "assign atom addresses:\n");
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << "assign atom addresses:\n");
+ const bool lookForMain =
+ (_options.outputKind() == WriterOptionsMachO::outputDynamicExecutable);
for (SectionChunk *chunk : _sectionChunks ) {
for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
_atomToAddress[info.atom] = chunk->address() + info.offsetInSection;
- DEBUG(llvm::dbgs() << " address=0x";
- llvm::dbgs().write_hex(_atomToAddress[info.atom]);
- llvm::dbgs() << " atom=" << info.atom;
- llvm::dbgs() << " name=" << info.atom->name() << "\n");
+ if ( lookForMain
+ && (info.atom->contentType() == DefinedAtom::typeCode)
+ && (info.atom->size() != 0)
+ && info.atom->name().equals("_main") ) {
+ _mainAtom = info.atom;
+ }
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << " address="
+ << llvm::format("0x%016X", _atomToAddress[info.atom])
+ << " atom=" << info.atom
+ << " name=" << info.atom->name() << "\n");
}
}
}
-
//void MachOWriter::dump() {
// for ( Chunk *chunk : _chunks ) {
// fprintf(stderr, "size=0x%08llX, fileOffset=0x%08llX, address=0x%08llX %s\n",
@@ -1334,9 +1395,10 @@ void MachOWriter::buildAtomToAddressMap() {
//}
void MachOWriter::assignFileOffsets() {
- DEBUG(llvm::dbgs() << "assign file offsets:\n");
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << "assign file offsets:\n");
uint64_t offset = 0;
- uint64_t address = _platform.pageZeroSize();
+ uint64_t address = _options.pageZeroSize();
for ( Chunk *chunk : _chunks ) {
if ( chunk->segmentName().equals("__LINKEDIT") ) {
_linkEditStartOffset = Chunk::alignTo(offset, 12);
@@ -1348,7 +1410,8 @@ void MachOWriter::assignFileOffsets() {
}
void MachOWriter::assignLinkEditFileOffsets() {
- DEBUG(llvm::dbgs() << "assign LINKEDIT file offsets:\n");
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << "assign LINKEDIT file offsets:\n");
uint64_t offset = _linkEditStartOffset;
uint64_t address = _linkEditStartAddress;
for ( Chunk *chunk : _linkEditChunks ) {
@@ -1373,7 +1436,7 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
const uint64_t kInvalidAddress = (uint64_t)(-1);
StringRef lastSegName("__TEXT");
*segIndex = 0;
- if ( _platform.pageZeroSize() != 0 ) {
+ if ( _options.pageZeroSize() != 0 ) {
*segIndex = 1;
}
*segStartAddr = kInvalidAddress;
@@ -1393,43 +1456,78 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
*segEndAddr = chunkEndAddr;
}
}
-
}
}
-void MachOWriter::zeroFill(int64_t amount, raw_ostream &out) {
- for( int i=amount; i > 0; --i)
- out.write('\0');
+//
+// Creates a mach-o final linked image from the given atom graph and writes
+// it to the supplied output stream.
+//
+error_code MachOWriter::writeFile(const lld::File &file, StringRef path) {
+ this->build(file);
+
+// FIXME: re-enable when FileOutputBuffer is in LLVMSupport.a
+#if 0
+ uint64_t totalSize = _chunks.back()->fileOffset() + _chunks.back()->size();
+
+ OwningPtr<llvm::FileOutputBuffer> buffer;
+ error_code ec = llvm::FileOutputBuffer::create(path,
+ totalSize, buffer,
+ llvm::FileOutputBuffer::F_executable);
+ if ( ec )
+ return ec;
+
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs() << "writeFile:\n");
+ for ( Chunk *chunk : _chunks ) {
+ DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
+ << " fileOffset="
+ << llvm::format("0x%08X", chunk->fileOffset())
+ << " chunk="
+ << chunk->info()
+ << "\n");
+ chunk->write(buffer->getBufferStart()+chunk->fileOffset());
+ }
+
+ return buffer->commit();
+#else
+ return error_code::success();
+#endif
}
-void MachOWriter::write(raw_ostream &out) {
- for ( Chunk *chunk : _chunks ) {
- if ( out.tell() != chunk->fileOffset() ) {
- // Assume just alignment padding to start of next section.
- assert( out.tell() < chunk->fileOffset() );
- uint64_t padding = chunk->fileOffset() - out.tell();
- chunk->writeZeros(padding, out);
- }
- chunk->write(out);
- }
+StubsPass *MachOWriter::stubPass() {
+ return &_stubsPass;
+}
+
+GOTPass *MachOWriter::gotPass() {
+ return &_gotPass;
}
+void MachOWriter::addFiles(InputFiles &inputFiles) {
+ inputFiles.prependFile(_cRuntimeFile);
+}
-//
-// Creates a mach-o final linked image from the given atom graph and writes
-// it to the supplied output stream.
-//
-void writeExecutable(const lld::File &file, DarwinPlatform &platform,
- raw_ostream &out) {
- MachOWriter writer(platform);
- writer.build(file);
- writer.write(out);
+
+} // namespace mach_o
+
+Writer* createWriterMachO(const WriterOptionsMachO &options) {
+ return new lld::mach_o::MachOWriter(options);
+}
+
+WriterOptionsMachO::WriterOptionsMachO()
+ : _outputkind(outputDynamicExecutable),
+ _archName("x86_64"),
+ _architecture(arch_x86_64),
+ _pageZeroSize(0x10000000),
+ _cpuType(mach_o::CPU_TYPE_X86_64),
+ _cpuSubtype(mach_o::CPU_SUBTYPE_X86_64_ALL),
+ _noTextRelocations(true) {
}
+WriterOptionsMachO::~WriterOptionsMachO() {
+}
-} // namespace darwin
} // namespace lld
diff --git a/lld/lib/ReaderWriter/Native/CMakeLists.txt b/lld/lib/ReaderWriter/Native/CMakeLists.txt
new file mode 100644
index 00000000000..8862750aea0
--- /dev/null
+++ b/lld/lib/ReaderWriter/Native/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_lld_library(lldNative
+ ReaderNative.cpp
+ WriterNative.cpp
+ )
diff --git a/lld/lib/Core/NativeFileFormat.h b/lld/lib/ReaderWriter/Native/NativeFileFormat.h
index f4e495246a5..43731f18a60 100644
--- a/lld/lib/Core/NativeFileFormat.h
+++ b/lld/lib/ReaderWriter/Native/NativeFileFormat.h
@@ -1,4 +1,4 @@
-//===- Core/NativeFileFormat.h - Describes native object file -------------===//
+//===- lib/ReaderWriter/Native/NativeFileFormat.h -------------------------===//
//
// The LLVM Linker
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_CORE_NATIVE_FILE_FORMAT_H_
-#define LLD_CORE_NATIVE_FILE_FORMAT_H_
+#ifndef LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_
+#define LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_
#include "llvm/Support/DataTypes.h"
@@ -240,4 +240,4 @@ struct NativeReferenceIvarsV2 {
} // namespace lld
-#endif // LLD_CORE_NATIVE_FILE_FORMAT_H_
+#endif // LLD_READER_WRITER_NATIVE_FILE_FORMAT_H_
diff --git a/lld/lib/Core/NativeReader.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
index 29086148ebc..b617a4fb9ae 100644
--- a/lld/lib/Core/NativeReader.cpp
+++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
@@ -1,4 +1,4 @@
-//===- Core/NativeReader.cpp - reads native object file ------------------===//
+//===- lib/ReaderWriter/Native/ReaderNative.cpp ---------------------------===//
//
// The LLVM Linker
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "NativeFileFormat.h"
+#include "lld/ReaderWriter/ReaderNative.h"
#include "lld/Core/Atom.h"
#include "lld/Core/Error.h"
@@ -16,16 +16,22 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "NativeFileFormat.h"
#include <vector>
#include <memory>
namespace lld {
+namespace native {
// forward reference
-class NativeFile;
+class File;
//
// An object of this class is instantied for each NativeDefinedAtomIvarsV1
@@ -33,11 +39,11 @@ class NativeFile;
//
class NativeDefinedAtomV1 : public DefinedAtom {
public:
- NativeDefinedAtomV1(const NativeFile& f,
+ NativeDefinedAtomV1(const File& f,
const NativeDefinedAtomIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
- virtual const class File& file() const;
+ virtual const class lld::File& file() const;
virtual uint64_t ordinal() const;
@@ -103,8 +109,8 @@ public:
private:
const NativeAtomAttributesV1& attributes() const;
- const NativeFile* _file;
- const NativeDefinedAtomIvarsV1* _ivarData;
+ const File *_file;
+ const NativeDefinedAtomIvarsV1 *_ivarData;
};
@@ -115,11 +121,11 @@ private:
//
class NativeUndefinedAtomV1 : public UndefinedAtom {
public:
- NativeUndefinedAtomV1(const NativeFile& f,
+ NativeUndefinedAtomV1(const File& f,
const NativeUndefinedAtomIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
- virtual const File& file() const;
+ virtual const lld::File& file() const;
virtual StringRef name() const;
virtual CanBeNull canBeNull() const {
@@ -128,8 +134,8 @@ public:
private:
- const NativeFile* _file;
- const NativeUndefinedAtomIvarsV1* _ivarData;
+ const File *_file;
+ const NativeUndefinedAtomIvarsV1 *_ivarData;
};
@@ -139,11 +145,11 @@ private:
//
class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
public:
- NativeSharedLibraryAtomV1(const NativeFile& f,
+ NativeSharedLibraryAtomV1(const File& f,
const NativeSharedLibraryAtomIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
- virtual const File& file() const;
+ virtual const lld::File& file() const;
virtual StringRef name() const;
virtual StringRef loadName() const;
@@ -152,8 +158,8 @@ public:
}
private:
- const NativeFile* _file;
- const NativeSharedLibraryAtomIvarsV1* _ivarData;
+ const File *_file;
+ const NativeSharedLibraryAtomIvarsV1 *_ivarData;
};
@@ -163,11 +169,11 @@ private:
//
class NativeAbsoluteAtomV1 : public AbsoluteAtom {
public:
- NativeAbsoluteAtomV1(const NativeFile& f,
+ NativeAbsoluteAtomV1(const File& f,
const NativeAbsoluteAtomIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
- virtual const File& file() const;
+ virtual const lld::File& file() const;
virtual StringRef name() const;
virtual uint64_t value() const {
@@ -175,8 +181,8 @@ public:
}
private:
- const NativeFile* _file;
- const NativeAbsoluteAtomIvarsV1* _ivarData;
+ const File *_file;
+ const NativeAbsoluteAtomIvarsV1 *_ivarData;
};
@@ -187,7 +193,7 @@ private:
//
class NativeReferenceV1 : public Reference {
public:
- NativeReferenceV1(const NativeFile& f,
+ NativeReferenceV1(const File& f,
const NativeReferenceIvarsV1* ivarData)
: _file(&f), _ivarData(ivarData) { }
@@ -216,8 +222,8 @@ private:
memcpy(niv, _ivarData, sizeof(NativeReferenceIvarsV1));
}
- const NativeFile* _file;
- const NativeReferenceIvarsV1* _ivarData;
+ const File *_file;
+ const NativeReferenceIvarsV1 *_ivarData;
};
@@ -225,14 +231,14 @@ private:
//
// lld::File object for native llvm object file
//
-class NativeFile : public File {
+class File : public lld::File {
public:
/// Instantiates a File object from a native object file. Ownership
/// of the MemoryBuffer is transfered to the resulting File object.
- static error_code make(std::unique_ptr<llvm::MemoryBuffer> mb,
+ static error_code make(std::unique_ptr<llvm::MemoryBuffer> &mb,
StringRef path,
- std::unique_ptr<File> &result) {
+ std::vector<std::unique_ptr<lld::File>> &result) {
const uint8_t* const base =
reinterpret_cast<const uint8_t*>(mb->getBufferStart());
const NativeFileHeader* const header =
@@ -248,8 +254,14 @@ public:
if ( header->fileSize > fileSize )
return make_error_code(native_reader_error::file_too_short);
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " Native File Header:"
+ << " fileSize=" << header->fileSize
+ << " chunkCount=" << header->chunkCount
+ << "\n");
+
// instantiate NativeFile object and add values to it as found
- std::unique_ptr<NativeFile> file(new NativeFile(std::move(mb), path));
+ std::unique_ptr<File> file(new File(std::move(mb), path));
// process each chunk
for(uint32_t i=0; i < header->chunkCount; ++i) {
@@ -298,14 +310,32 @@ public:
if ( ec ) {
return ec;
}
- // TO DO: validate enough chunks were used
+ }
+ // TO DO: validate enough chunks were used
+
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " ReaderNative DefinedAtoms:\n");
+ for (const DefinedAtom *a : file->defined() ) {
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << llvm::format(" 0x%09lX", a)
+ << ", name=" << a->name()
+ << ", size=" << a->size()
+ << "\n");
+ for (const Reference *r : *a ) {
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " offset="
+ << llvm::format("0x%03X", r->offsetInAtom())
+ << ", kind=" << r->kind()
+ << ", target=" << r->target()
+ << "\n");
+ }
}
- result.reset(file.release());
+ result.push_back(std::move(file));
return make_error_code(native_reader_error::success);
}
- virtual ~NativeFile() {
+ virtual ~File() {
// _buffer is automatically deleted because of OwningPtr<>
// All other ivar pointers are pointers into the MemoryBuffer, except
@@ -371,14 +401,26 @@ private:
this->_definedAtoms._arrayEnd = atomsEnd;
this->_definedAtoms._elementSize = atomSize;
this->_definedAtoms._elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk DefinedAtomsV1: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
+
+
// set up pointers to attributes array
error_code processAttributesV1(const uint8_t *base,
const NativeChunk *chunk) {
this->_attributes = base + chunk->fileOffset;
this->_attributesMaxOffset = chunk->fileSize;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk AttributesV1: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -409,6 +451,11 @@ private:
this->_undefinedAtoms._arrayEnd = atomsEnd;
this->_undefinedAtoms._elementSize = atomSize;
this->_undefinedAtoms._elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk UndefinedAtomsV1:"
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -440,6 +487,11 @@ private:
this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
this->_sharedLibraryAtoms._elementSize = atomSize;
this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk SharedLibraryAtomsV1:"
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -471,6 +523,11 @@ private:
this->_absoluteAtoms._arrayEnd = atomsEnd;
this->_absoluteAtoms._elementSize = atomSize;
this->_absoluteAtoms._elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk AbsoluteAtomsV1: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -506,6 +563,11 @@ private:
this->_references.arrayEnd = refsEnd;
this->_references.elementSize = refSize;
this->_references.elementCount = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk ReferencesV1: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -550,6 +612,11 @@ private:
}
return make_error_code(native_reader_error::file_malformed);
}
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk Targets Table: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -560,6 +627,11 @@ private:
this->_addends = reinterpret_cast<const Reference::Addend*>
(base + chunk->fileOffset);
this->_addendsMaxIndex = chunk->elementCount;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk Addends: "
+ << " count=" << chunk->elementCount
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -568,6 +640,10 @@ private:
const NativeChunk *chunk) {
this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
this->_stringsMaxOffset = chunk->fileSize;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk Strings: "
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -576,6 +652,10 @@ private:
const NativeChunk *chunk) {
this->_contentStart = base + chunk->fileOffset;
this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
+ DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
+ << " chunk content: "
+ << " chunkSize=" << chunk->fileSize
+ << "\n");
return make_error_code(native_reader_error::success);
}
@@ -624,9 +704,9 @@ private:
// private constructor, only called by make()
- NativeFile(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
- File(path),
- _buffer(std::move(mb)), // NativeFile now takes ownership of buffer
+ File(std::unique_ptr<llvm::MemoryBuffer> mb, StringRef path) :
+ lld::File(path),
+ _buffer(std::move(mb)), // Reader now takes ownership of buffer
_header(nullptr),
_targetsTable(nullptr),
_targetsTableCount(0),
@@ -701,7 +781,7 @@ private:
};
-inline const class File& NativeDefinedAtomV1::file() const {
+inline const class lld::File& NativeDefinedAtomV1::file() const {
return *_file;
}
@@ -754,7 +834,7 @@ void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
it = reinterpret_cast<const void*>(index);
}
-inline const class File& NativeUndefinedAtomV1::file() const {
+inline const class lld::File& NativeUndefinedAtomV1::file() const {
return *_file;
}
@@ -765,7 +845,7 @@ inline StringRef NativeUndefinedAtomV1::name() const {
-inline const class File& NativeSharedLibraryAtomV1::file() const {
+inline const class lld::File& NativeSharedLibraryAtomV1::file() const {
return *_file;
}
@@ -779,7 +859,7 @@ inline StringRef NativeSharedLibraryAtomV1::loadName() const {
-inline const class File& NativeAbsoluteAtomV1::file() const {
+inline const class lld::File& NativeAbsoluteAtomV1::file() const {
return *_file;
}
@@ -806,34 +886,44 @@ inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
}
inline void NativeReferenceV1::setAddend(Addend a) {
+ // Do nothing if addend value is not being changed.
+ if ( this->addend() == a )
+ return;
assert(0 && "setAddend() not supported");
}
-//
-// Instantiate an lld::File from the given native object file buffer
-//
-error_code parseNativeObjectFile(std::unique_ptr<llvm::MemoryBuffer> mb,
- StringRef path,
- std::unique_ptr<File> &result) {
- return NativeFile::make(std::move(mb), path, result);
-}
+class Reader : public lld::Reader {
+public:
+ Reader(const ReaderOptionsNative &options) : _options(options) {
+ }
+
+ virtual error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+ std::vector<std::unique_ptr<lld::File>> &result) {
+ return File::make(mb, mb->getBufferIdentifier(), result);
+ }
+private:
+ const ReaderOptionsNative &_options;
+};
-//
-// Instantiate an lld::File from the given native object file path
-//
-error_code parseNativeObjectFileOrSTDIN(StringRef path,
- std::unique_ptr<File>& result) {
- OwningPtr<llvm::MemoryBuffer> mb;
- error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb);
- if ( ec )
- return ec;
-
- return parseNativeObjectFile( std::unique_ptr<llvm::MemoryBuffer>(mb.take())
- , path
- , result);
+
+} // namespace native
+
+Reader* createReaderNative(const ReaderOptionsNative &options) {
+ return new lld::native::Reader(options);
+}
+
+ReaderOptionsNative::ReaderOptionsNative() {
}
+ReaderOptionsNative::~ReaderOptionsNative() {
+}
+
+
} // namespace lld
+
+
+
+
diff --git a/lld/lib/Core/NativeWriter.cpp b/lld/lib/ReaderWriter/Native/WriterNative.cpp
index 5c7fc05d03e..e3dc04351de 100644
--- a/lld/lib/Core/NativeWriter.cpp
+++ b/lld/lib/ReaderWriter/Native/WriterNative.cpp
@@ -1,4 +1,4 @@
-//===- Core/NativeWriter.cpp - Creates a native object file ---------------===//
+//===- lib/ReaderWriter/Native/WriterNative.cpp ---------------------------===//
//
// The LLVM Linker
//
@@ -7,26 +7,31 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/NativeWriter.h"
-#include "NativeFileFormat.h"
+#include "lld/ReaderWriter/WriterNative.h"
#include "lld/Core/File.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+#include "NativeFileFormat.h"
#include <vector>
namespace lld {
-
+namespace native {
///
/// Class for writing native object files.
///
-class NativeWriter {
+class Writer : public lld::Writer {
public:
- /// construct writer for an lld::File object
- NativeWriter(const lld::File& file) : _file(file) {
+ Writer(const WriterOptionsNative &options) : _options(options) {
+ }
+
+ virtual error_code writeFile(const lld::File &file, StringRef outPath) {
// reserve first byte for unnamed atoms
_stringPool.push_back('\0');
// visit all atoms
@@ -43,12 +48,25 @@ public:
this->addIVarsForAbsoluteAtom(*absAtom);
}
-
-
// construct file header based on atom information accumulated
- makeHeader();
+ this->makeHeader();
+
+ std::string errorInfo;
+ llvm::raw_fd_ostream out(outPath.data(), errorInfo,
+ llvm::raw_fd_ostream::F_Binary);
+ if (!errorInfo.empty())
+ return error_code::success(); // FIXME
+
+ this->write(out);
+
+ return error_code::success();
+ }
+
+ virtual ~Writer() {
}
+private:
+
// write the lld::File in native format to the specified stream
void write(raw_ostream &out) {
assert( out.tell() == 0 );
@@ -113,8 +131,6 @@ public:
}
}
-private:
-
void addIVarsForDefinedAtom(const DefinedAtom& atom) {
_definedAtomIndex[&atom] = _definedAtomIvars.size();
NativeDefinedAtomIvarsV1 ivar;
@@ -426,7 +442,7 @@ private:
if ( pos != _targetsTableIndex.end() ) {
return pos->second;
}
- uint32_t result = _targetsTableIndex.size();
+ uint32_t result = _targetsTableIndex.size();
_targetsTableIndex[target] = result;
return result;
}
@@ -507,7 +523,7 @@ private:
typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;
typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;
- const lld::File& _file;
+ const WriterOptionsNative &_options;
NativeFileHeader* _headerBuffer;
size_t _headerBufferSize;
std::vector<char> _stringPool;
@@ -529,27 +545,19 @@ private:
};
+} // namespace native
+Writer* createWriterNative(const WriterOptionsNative &options) {
+ return new lld::native::Writer(options);
+}
-
-/// writeNativeObjectFile - writes the lld::File object in native object
-/// file format to the specified stream.
-int writeNativeObjectFile(const File &file, raw_ostream &out) {
- NativeWriter writer(file);
- writer.write(out);
- return 0;
+WriterOptionsNative::WriterOptionsNative() {
}
-/// writeNativeObjectFile - writes the lld::File object in native object
-/// file format to the specified file path.
-int writeNativeObjectFile(const File &file, StringRef path) {
- std::string errorInfo;
- llvm::raw_fd_ostream out( path.data()
- , errorInfo
- , llvm::raw_fd_ostream::F_Binary);
- if (!errorInfo.empty())
- return -1;
- return writeNativeObjectFile(file, out);
+WriterOptionsNative::~WriterOptionsNative() {
}
+
} // namespace lld
+
+
diff --git a/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt b/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt
new file mode 100644
index 00000000000..a08b5ec4bfb
--- /dev/null
+++ b/lld/lib/ReaderWriter/PECOFF/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_lld_library(lldPECOFF
+ ReaderCOFF.cpp
+ WriterPECOFF.cpp
+ )
diff --git a/lld/lib/Reader/COFFReader.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index 3df6f73f2a9..a43c8380c28 100644
--- a/lld/lib/Reader/COFFReader.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -1,4 +1,4 @@
-//===- COFFReader.h - PECOFF Object File Reader ---------------------------===//
+//===- lib/ReaderWriter/PECOFF/ReaderCOFF.cpp -----------------------------===//
//
// The LLVM Linker
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Reader/Reader.h"
+#include "lld/ReaderWriter/ReaderPECOFF.h"
#include "lld/Core/File.h"
#include "llvm/ADT/ArrayRef.h"
@@ -199,9 +199,9 @@ private:
llvm::ArrayRef<uint8_t> Data;
};
-class COFFReader : public File {
+class FileCOFF : public File {
public:
- COFFReader(std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
+ FileCOFF(std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
: File(MB->getBufferIdentifier()) {
llvm::OwningPtr<llvm::object::Binary> Bin;
EC = llvm::object::createBinary(MB.release(), Bin);
@@ -331,15 +331,15 @@ public:
virtual const atom_collection<DefinedAtom> &defined() const {
return DefinedAtoms;
}
-
+
virtual const atom_collection<UndefinedAtom> &undefined() const {
return UndefinedAtoms;
}
-
+
virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
return SharedLibraryAtoms;
}
-
+
virtual const atom_collection<AbsoluteAtom> &absolute() const {
return AbsoluteAtoms;
}
@@ -353,12 +353,32 @@ private:
llvm::BumpPtrAllocator AtomStorage;
};
-llvm::error_code
-lld::parseCOFFObjectFile(std::unique_ptr<llvm::MemoryBuffer> MB,
- std::unique_ptr<File> &Result) {
- llvm::error_code EC;
- Result.reset(new COFFReader(std::move(MB), EC));
- if (EC)
- Result.release();
- return EC;
+
+
+class ReaderCOFF : public Reader {
+public:
+ ReaderCOFF(const ReaderOptionsPECOFF &options) : _options(options) {
+ }
+
+ error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+ std::vector<std::unique_ptr<File>> &result) {
+ llvm::error_code ec;
+ std::unique_ptr<File> f(new FileCOFF(std::move(mb), ec));
+ if (ec) {
+ return ec;
+ }
+
+ result.push_back(std::move(f));
+ return error_code::success();
+ }
+private:
+ const ReaderOptionsPECOFF &_options;
+};
+
+
+
+Reader* createReaderPECOFF(const ReaderOptionsPECOFF &options) {
+ return new ReaderCOFF(options);
}
+
+
diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
new file mode 100644
index 00000000000..8fec44e777b
--- /dev/null
+++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
@@ -0,0 +1,35 @@
+//===- lib/ReaderWriter/PECOFF/WriterPECOFF.cpp ---------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/WriterPECOFF.h"
+
+#include "llvm/Support/Debug.h"
+
+
+namespace lld {
+namespace pe_coff {
+
+// define PE/COFF writer class here
+
+
+} // namespace pe_coff
+
+Writer* createWriterPECOFF(const WriterOptionsPECOFF &options) {
+ assert(0 && "PE/COFF support not implemented yet");
+ return nullptr;
+}
+
+WriterOptionsPECOFF::WriterOptionsPECOFF() {
+}
+
+WriterOptionsPECOFF::~WriterOptionsPECOFF() {
+}
+
+} // namespace lld
+
diff --git a/lld/lib/ReaderWriter/Reader.cpp b/lld/lib/ReaderWriter/Reader.cpp
new file mode 100644
index 00000000000..f4395e8ff38
--- /dev/null
+++ b/lld/lib/ReaderWriter/Reader.cpp
@@ -0,0 +1,42 @@
+//===- lib/ReaderWriter/Reader.cpp ----------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/Reader.h"
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/system_error.h"
+
+
+namespace lld {
+
+Reader::Reader() {
+}
+
+Reader::~Reader() {
+}
+
+error_code Reader::readFile(StringRef path,
+ std::vector<std::unique_ptr<File>> &result) {
+ OwningPtr<llvm::MemoryBuffer> opmb;
+ if ( error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, opmb) )
+ return ec;
+
+ std::unique_ptr<MemoryBuffer> mb(opmb.take());
+ return this->parseFile(std::move(mb), result);
+}
+
+
+
+ReaderOptions::ReaderOptions() {
+}
+
+} // namespace lld
+
diff --git a/lld/lib/Core/Platform.cpp b/lld/lib/ReaderWriter/Writer.cpp
index 430668d1200..93dbcf5f967 100644
--- a/lld/lib/Core/Platform.cpp
+++ b/lld/lib/ReaderWriter/Writer.cpp
@@ -1,4 +1,4 @@
-//===- Core/Platform.cpp - Base class ------------------------------------===//
+//===- lib/ReaderWriter/Writer.cpp ----------------------------------------===//
//
// The LLVM Linker
//
@@ -7,13 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/Platform.h"
+#include "lld/ReaderWriter/Writer.h"
-namespace lld {
-Platform::Platform() {}
+namespace lld {
-Platform::~Platform() {}
+Writer::Writer() {
+}
+Writer::~Writer() {
+}
+WriterOptions::WriterOptions() {
}
+
+} // namespace lld
+
diff --git a/lld/lib/ReaderWriter/YAML/CMakeLists.txt b/lld/lib/ReaderWriter/YAML/CMakeLists.txt
new file mode 100644
index 00000000000..ecd07030cb4
--- /dev/null
+++ b/lld/lib/ReaderWriter/YAML/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_lld_library(lldYAML
+ YamlKeyValues.cpp
+ ReaderYAML.cpp
+ WriterYAML.cpp
+ )
diff --git a/lld/lib/Core/YamlReader.cpp b/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp
index 87f1e142355..8da77713698 100644
--- a/lld/lib/Core/YamlReader.cpp
+++ b/lld/lib/ReaderWriter/YAML/ReaderYAML.cpp
@@ -1,4 +1,4 @@
-//===- Core/YamlReader.cpp - Reads YAML encode object files ---------------===//
+//===- lib/ReaderWriter/YAML/ReaderYAML.cpp - Reads YAML object files -----===//
//
// The LLVM Linker
//
@@ -7,15 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/YamlReader.h"
-#include "YamlKeyValues.h"
-#include "lld/Core/Atom.h"
+#include "lld/ReaderWriter/ReaderYAML.h"
+
#include "lld/Core/AbsoluteAtom.h"
+#include "lld/Core/ArchiveLibraryFile.h"
+#include "lld/Core/Atom.h"
#include "lld/Core/Error.h"
#include "lld/Core/File.h"
-#include "lld/Core/ArchiveLibraryFile.h"
#include "lld/Core/LLVM.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/Reference.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/UndefinedAtom.h"
@@ -26,17 +25,19 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/system_error.h"
#include "llvm/Support/YAMLParser.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Debug.h"
#include <cstring>
#include <vector>
+#include "YamlKeyValues.h"
+
namespace lld {
namespace yaml {
@@ -536,7 +537,7 @@ const File *YAMLFile::find(StringRef name, bool dataSymbolOnly) const {
///
class YAMLState {
public:
- YAMLState(Platform &platform, llvm::yaml::Stream *s, YAMLFile *f);
+ YAMLState(const ReaderOptionsYAML &opts, llvm::yaml::Stream *s, YAMLFile *f);
void parse(llvm::yaml::Node *node, StringRef keyword,
llvm::yaml::Node *keywordNode=nullptr);
@@ -605,7 +606,7 @@ private:
static const Transistion _s_transistions[];
- Platform &_platform;
+ const ReaderOptionsYAML &_options;
error_code _error;
llvm::yaml::Stream *_stream;
YAMLFile *_file;
@@ -685,8 +686,9 @@ const YAMLState::Transistion YAMLState::_s_transistions[] = {
-YAMLState::YAMLState(Platform &platform, Stream *stream, YAMLFile *file)
- : _platform(platform)
+YAMLState::YAMLState(const ReaderOptionsYAML &opts, Stream *stream,
+ YAMLFile *file)
+ : _options(opts)
, _error(make_error_code(yaml_reader_error::success))
, _stream(stream)
, _file(file)
@@ -870,7 +872,7 @@ const char* YAMLState::stateName(State s) {
void YAMLState::moveToState(State newState) {
if ( newState == _state )
return;
- DEBUG(llvm::dbgs() << "moveToState(" << stateName(newState)
+ DEBUG_WITH_TYPE("objtxt", llvm::dbgs() << "moveToState(" << stateName(newState)
<< "), _state=" << stateName(_state) << "\n");
if ( newState == inArch ) {
@@ -896,7 +898,8 @@ void YAMLState::moveToState(State newState) {
void YAMLState::returnToState(State prevState, Node *node) {
if ( prevState == _state )
return;
- DEBUG(llvm::dbgs() << "returnToState(" << stateName(prevState)
+ DEBUG_WITH_TYPE("objtxt", llvm::dbgs()
+ << "returnToState(" << stateName(prevState)
<< "), _state=" << stateName(_state) << "\n");
// If done with an atom, instantiate an object for it.
if ( (_state == inAtom) && (prevState == inAtoms) )
@@ -913,9 +916,9 @@ void YAMLState::returnToState(State prevState, Node *node) {
StringRef YAMLState::extractString(ScalarNode *node) {
llvm::SmallString<32> storage;
StringRef str = node->getValue(storage);
- if ( str.data() == storage.begin() ) {
+ //if ( str.data() == storage.begin() ) {
str = _file->copyString(str);
- }
+ //}
return str;
}
@@ -1056,7 +1059,7 @@ void YAMLState::parseFixUpOffset(ScalarNode *node) {
void YAMLState::parseFixUpKind(ScalarNode *node) {
llvm::SmallString<32> storage;
- _ref._kind = _platform.kindFromString(node->getValue(storage));
+ _ref._kind = _options.kindFromString(node->getValue(storage));
_hasDefinedAtomAttributes = true;
}
@@ -1116,7 +1119,7 @@ void YAMLState::parseAtomValue(ScalarNode *node) {
//
void YAMLState::parse(Node *node, StringRef keyword, Node *keywordNode) {
using namespace llvm::yaml;
- DEBUG(llvm::dbgs() << "parse(" << keyword << "), _state="
+ DEBUG_WITH_TYPE("objtxt", llvm::dbgs() << "parse(" << keyword << "), _state="
<< stateName(_state) << "\n");
if ( _error )
return;
@@ -1196,17 +1199,17 @@ void YAMLState::parse(Node *node, StringRef keyword, Node *keywordNode) {
/// parseObjectText - Parse the specified YAML formatted MemoryBuffer
/// into lld::File object(s) and append each to the specified vector<File*>.
-error_code parseObjectText( llvm::MemoryBuffer *mb
- , Platform& platform
- , std::vector<std::unique_ptr<const File>> &result) {
+error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ const ReaderOptionsYAML &options,
+ std::vector<std::unique_ptr<File>> &result) {
llvm::SourceMgr srcMgr;
llvm::yaml::Stream stream(mb->getBuffer(), srcMgr);
for (llvm::yaml::Document &d : stream) {
- std::unique_ptr<YAMLFile> curFile(new YAMLFile);
+ std::unique_ptr<yaml::YAMLFile> curFile(new yaml::YAMLFile);
if (llvm::isa<llvm::yaml::NullNode>(d.getRoot()))
continue; // Empty files are allowed.
- YAMLState yamlState(platform, &stream, curFile.get());
+ yaml::YAMLState yamlState(options, &stream, curFile.get());
yamlState.parse(d.getRoot(), StringRef("<root>"));
if ( stream.failed() )
@@ -1225,19 +1228,37 @@ error_code parseObjectText( llvm::MemoryBuffer *mb
-//
-// Fill in vector<File*> from path to input text file.
-//
-error_code
-parseObjectTextFileOrSTDIN( StringRef path
- , Platform& platform
- , std::vector<std::unique_ptr<const File>>& result) {
- OwningPtr<llvm::MemoryBuffer> mb;
- if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, mb))
- return ec;
-
- return parseObjectText(mb.take(), platform, result);
+} // namespace yaml
+
+
+
+class ReaderYAML: public Reader {
+public:
+ ReaderYAML(const ReaderOptionsYAML &options) : _options(options) {
+ }
+
+ error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
+ std::vector<std::unique_ptr<File>> &result) {
+ return lld::yaml::parseFile(mb, _options, result);
+ }
+
+private:
+ const ReaderOptionsYAML &_options;
+};
+
+
+
+Reader* createReaderYAML(const ReaderOptionsYAML &options) {
+ return new ReaderYAML(options);
}
-} // namespace yaml
+ReaderOptionsYAML::ReaderOptionsYAML() {
+}
+
+ReaderOptionsYAML::~ReaderOptionsYAML() {
+}
+
+
+
+
} // namespace lld
diff --git a/lld/lib/Core/YamlWriter.cpp b/lld/lib/ReaderWriter/YAML/WriterYAML.cpp
index f3b348282b8..7b69f7822f4 100644
--- a/lld/lib/Core/YamlWriter.cpp
+++ b/lld/lib/ReaderWriter/YAML/WriterYAML.cpp
@@ -1,4 +1,4 @@
-//===- Core/YamlWriter.cpp - Writes YAML ----------------------------------===//
+//===- lib/ReaderWriter/YAML/WriterYAML.cpp - Writes YAML object files ----===//
//
// The LLVM Linker
//
@@ -7,11 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#include "lld/Core/YamlWriter.h"
-#include "YamlKeyValues.h"
+#include "lld/ReaderWriter/WriterYAML.h"
+
#include "lld/Core/Atom.h"
#include "lld/Core/File.h"
-#include "lld/Core/Platform.h"
#include "lld/Core/Reference.h"
#include "llvm/ADT/ArrayRef.h"
@@ -25,12 +24,13 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
+#include "YamlKeyValues.h"
+
#include <vector>
namespace lld {
namespace yaml {
-namespace {
///
/// In most cases, atoms names are unambiguous, so references can just
/// use the atom name as the target (e.g. target: foo). But in a few
@@ -125,8 +125,9 @@ private:
///
class AtomWriter {
public:
- AtomWriter(const File& file, Platform& platform, RefNameBuilder& rnb)
- : _file(file), _platform(platform), _rnb(rnb), _firstAtom(true) { }
+ AtomWriter(const File& file, const WriterOptionsYAML &options,
+ RefNameBuilder& rnb)
+ : _file(file), _options(options), _rnb(rnb), _firstAtom(true) { }
void write(raw_ostream &out) {
@@ -295,7 +296,7 @@ public:
out << " "
<< "kind:"
<< spacePadding(strlen("kind"))
- << _platform.kindToString(ref->kind())
+ << _options.kindToString(ref->kind())
<< "\n";
const Atom* target = ref->target();
if (target != nullptr) {
@@ -436,28 +437,62 @@ private:
return 'A' + nibble - 0x0A;
}
- const File& _file;
- Platform& _platform;
- RefNameBuilder& _rnb;
- bool _firstAtom;
+ const File &_file;
+ const WriterOptionsYAML &_options;
+ RefNameBuilder &_rnb;
+ bool _firstAtom;
};
-} // anonymous namespace
-///
-/// writeObjectText - writes the lld::File object as in YAML
-/// format to the specified stream.
-///
-void writeObjectText(const File &file, Platform &platform, raw_ostream &out) {
- // Figure what ref-name labels are needed
- RefNameBuilder rnb(file);
+class Writer : public lld::Writer {
+public:
+ Writer(const WriterOptionsYAML &options) : _options(options) {
+ }
+
+ virtual error_code writeFile(const lld::File &file, StringRef path) {
+ // Create stream to path.
+ std::string errorInfo;
+ llvm::raw_fd_ostream out(path.data(), errorInfo);
+ if (!errorInfo.empty())
+ return llvm::make_error_code(llvm::errc::no_such_file_or_directory);
+
+ // Figure what ref-name labels are needed.
+ RefNameBuilder rnb(file);
+
+ // Write out all atoms.
+ AtomWriter writer(file, _options, rnb);
+ writer.write(out);
+ return error_code::success();
+ }
+
+ virtual StubsPass *stubPass() {
+ return _options.stubPass();
+ }
+
+ virtual GOTPass *gotPass() {
+ return _options.gotPass();
+ }
+
+
+private:
+ const WriterOptionsYAML &_options;
+};
- // Write out all atoms
- AtomWriter writer(file, platform, rnb);
- writer.write(out);
-}
} // namespace yaml
+
+
+Writer* createWriterYAML(const WriterOptionsYAML &options) {
+ return new lld::yaml::Writer(options);
+}
+
+WriterOptionsYAML::WriterOptionsYAML() {
+}
+
+WriterOptionsYAML::~WriterOptionsYAML() {
+}
+
+
} // namespace lld
diff --git a/lld/lib/Core/YamlKeyValues.cpp b/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp
index 3eab4e6d9c5..46120ad6716 100644
--- a/lld/lib/Core/YamlKeyValues.cpp
+++ b/lld/lib/ReaderWriter/YAML/YamlKeyValues.cpp
@@ -1,4 +1,4 @@
-//===- Core/YamlKeyValues.cpp - Reads YAML --------------------------------===//
+//===- lib/ReaderWriter/YAML/YamlKeyValues.cpp ----------------------------===//
//
// The LLVM Linker
//
diff --git a/lld/lib/Core/YamlKeyValues.h b/lld/lib/ReaderWriter/YAML/YamlKeyValues.h
index ecb3d2e239a..9f0e964cba5 100644
--- a/lld/lib/Core/YamlKeyValues.h
+++ b/lld/lib/ReaderWriter/YAML/YamlKeyValues.h
@@ -1,4 +1,4 @@
-//===- Core/YamlKeyValues.h - Reads YAML ----------------------------------===//
+//===- lib/ReaderWriter/YAML/YamlKeyValues.h ------------------------------===//
//
// The LLVM Linker
//
diff --git a/lld/tools/lld-core/CMakeLists.txt b/lld/tools/lld-core/CMakeLists.txt
index bd645094d59..4f4a43bbbc6 100644
--- a/lld/tools/lld-core/CMakeLists.txt
+++ b/lld/tools/lld-core/CMakeLists.txt
@@ -1,9 +1,13 @@
set(LLVM_USED_LIBS
lldCore
- lldReader
lldPasses
- lldDarwinPlatform
- )
+ lldMachO
+ lldPECOFF
+ lldELF
+ lldNative
+ lldYAML
+ lldReaderWriter
+ )
set(LLVM_LINK_COMPONENTS
support
diff --git a/lld/tools/lld-core/TestingHelpers.hpp b/lld/tools/lld-core/TestingHelpers.hpp
new file mode 100644
index 00000000000..20f4d570aeb
--- /dev/null
+++ b/lld/tools/lld-core/TestingHelpers.hpp
@@ -0,0 +1,403 @@
+//===- tools/lld/TestingWriter.hpp - Linker Core Test Support -------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_TOOLS_TESTING_HELPERS_H_
+#define LLD_TOOLS_TESTING_HELPERS_H_
+
+#include "lld/Core/Atom.h"
+#include "lld/Core/LLVM.h"
+#include "lld/Core/Pass.h"
+#include "lld/Core/Resolver.h"
+#include "lld/ReaderWriter/WriterYAML.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
+
+#include <vector>
+
+using namespace lld;
+
+//
+// Simple atom created by the stubs pass.
+//
+class TestingStubAtom : public DefinedAtom {
+public:
+ TestingStubAtom(const File& f, const Atom& shlib) :
+ _file(f), _shlib(shlib) {
+ static uint32_t lastOrdinal = 0;
+ _ordinal = lastOrdinal++;
+ }
+
+ virtual const File& file() const {
+ return _file;
+ }
+
+ virtual StringRef name() const {
+ return StringRef();
+ }
+
+ virtual uint64_t ordinal() const {
+ return _ordinal;
+ }
+
+ virtual uint64_t size() const {
+ return 0;
+ }
+
+ virtual Scope scope() const {
+ return DefinedAtom::scopeLinkageUnit;
+ }
+
+ virtual Interposable interposable() const {
+ return DefinedAtom::interposeNo;
+ }
+
+ virtual Merge merge() const {
+ return DefinedAtom::mergeNo;
+ }
+
+ virtual ContentType contentType() const {
+ return DefinedAtom::typeStub;
+ }
+
+ virtual Alignment alignment() const {
+ return Alignment(0,0);
+ }
+
+ virtual SectionChoice sectionChoice() const {
+ return DefinedAtom::sectionBasedOnContent;
+ }
+
+ virtual StringRef customSectionName() const {
+ return StringRef();
+ }
+ virtual DeadStripKind deadStrip() const {
+ return DefinedAtom::deadStripNormal;
+ }
+
+ virtual ContentPermissions permissions() const {
+ return DefinedAtom::permR_X;
+ }
+
+ virtual bool isThumb() const {
+ return false;
+ }
+
+ virtual bool isAlias() const {
+ return false;
+ }
+
+ virtual ArrayRef<uint8_t> rawContent() const {
+ return ArrayRef<uint8_t>();
+ }
+
+ virtual reference_iterator begin() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+ virtual reference_iterator end() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+ virtual const Reference* derefIterator(const void* iter) const {
+ return nullptr;
+ }
+
+ virtual void incrementIterator(const void*& iter) const {
+
+ }
+
+private:
+ const File& _file;
+ const Atom& _shlib;
+ uint32_t _ordinal;
+};
+
+
+
+
+//
+// Simple atom created by the GOT pass.
+//
+class TestingGOTAtom : public DefinedAtom {
+public:
+ TestingGOTAtom(const File& f, const Atom& shlib) :
+ _file(f), _shlib(shlib) {
+ static uint32_t lastOrdinal = 0;
+ _ordinal = lastOrdinal++;
+ }
+
+ virtual const File& file() const {
+ return _file;
+ }
+
+ virtual StringRef name() const {
+ return StringRef();
+ }
+
+ virtual uint64_t ordinal() const {
+ return _ordinal;
+ }
+
+ virtual uint64_t size() const {
+ return 0;
+ }
+
+ virtual Scope scope() const {
+ return DefinedAtom::scopeLinkageUnit;
+ }
+
+ virtual Interposable interposable() const {
+ return DefinedAtom::interposeNo;
+ }
+
+ virtual Merge merge() const {
+ return DefinedAtom::mergeNo;
+ }
+
+ virtual ContentType contentType() const {
+ return DefinedAtom::typeGOT;
+ }
+
+ virtual Alignment alignment() const {
+ return Alignment(3,0);
+ }
+
+ virtual SectionChoice sectionChoice() const {
+ return DefinedAtom::sectionBasedOnContent;
+ }
+
+ virtual StringRef customSectionName() const {
+ return StringRef();
+ }
+ virtual DeadStripKind deadStrip() const {
+ return DefinedAtom::deadStripNormal;
+ }
+
+ virtual ContentPermissions permissions() const {
+ return DefinedAtom::permRW_;
+ }
+
+ virtual bool isThumb() const {
+ return false;
+ }
+
+ virtual bool isAlias() const {
+ return false;
+ }
+
+ virtual ArrayRef<uint8_t> rawContent() const {
+ return ArrayRef<uint8_t>();
+ }
+
+ virtual reference_iterator begin() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+ virtual reference_iterator end() const {
+ return reference_iterator(*this, nullptr);
+ }
+
+ virtual const Reference* derefIterator(const void* iter) const {
+ return nullptr;
+ }
+
+ virtual void incrementIterator(const void*& iter) const {
+
+ }
+
+private:
+ const File& _file;
+ const Atom& _shlib;
+ uint32_t _ordinal;
+};
+
+
+
+class TestingPassFile : public File {
+public:
+ TestingPassFile() : File("Testing pass") {
+ }
+
+ virtual void addAtom(const Atom &atom) {
+ if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
+ _definedAtoms._atoms.push_back(defAtom);
+ }
+ else {
+ assert(0 && "atom has unknown definition kind");
+ }
+ }
+
+ virtual const atom_collection<DefinedAtom>& defined() const {
+ return _definedAtoms;
+ }
+ virtual const atom_collection<UndefinedAtom>& undefined() const {
+ return _undefinedAtoms;
+ }
+ virtual const atom_collection<SharedLibraryAtom>& sharedLibrary() const {
+ return _sharedLibraryAtoms;
+ }
+ virtual const atom_collection<AbsoluteAtom>& absolute() const {
+ return _absoluteAtoms;
+ }
+
+private:
+ atom_collection_vector<DefinedAtom> _definedAtoms;
+ atom_collection_vector<UndefinedAtom> _undefinedAtoms;
+ atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+ atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+};
+
+
+
+struct TestingKindMapping {
+ const char* string;
+ Reference::Kind value;
+ bool isBranch;
+ bool isGotLoad;
+ bool isGotUse;
+};
+
+//
+// Table of fixup kinds in YAML documents used for testing
+//
+const TestingKindMapping sKinds[] = {
+ { "call32", 1, true, false, false},
+ { "pcrel32", 2, false, false, false },
+ { "gotLoad32", 3, false, true, true },
+ { "gotUse32", 4, false, false, true },
+ { "lea32wasGot", 5, false, false, false },
+ { nullptr, 0, false, false, false }
+ };
+
+
+
+class TestingStubsPass : public StubsPass {
+public:
+ virtual bool noTextRelocs() {
+ return true;
+ }
+
+ virtual bool isCallSite(Reference::Kind kind) {
+ for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) {
+ if ( kind == p->value )
+ return p->isBranch;
+ }
+ return false;
+ }
+
+ virtual const DefinedAtom* getStub(const Atom& target) {
+ const DefinedAtom *result = new TestingStubAtom(_file, target);
+ _file.addAtom(*result);
+ return result;
+ }
+
+
+ virtual void addStubAtoms(File &mergedFile) {
+ for (const DefinedAtom *stub : _file.defined() ) {
+ mergedFile.addAtom(*stub);
+ }
+ }
+
+private:
+ TestingPassFile _file;
+};
+
+
+
+class TestingGOTPass : public GOTPass {
+public:
+ virtual bool noTextRelocs() {
+ return true;
+ }
+
+ virtual bool isGOTAccess(Reference::Kind kind, bool &canBypassGOT) {
+ for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) {
+ if ( kind == p->value ) {
+ canBypassGOT = p->isGotLoad;
+ return (p->isGotUse || p->isGotLoad);
+ }
+ }
+ return false;
+ }
+
+ virtual void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) {
+ if ( targetIsNowGOT )
+ (const_cast<Reference*>(ref))->setKind(2); // pcrel32
+ else
+ (const_cast<Reference*>(ref))->setKind(5); // lea32wasGot
+ }
+
+ virtual const DefinedAtom* makeGOTEntry(const Atom &target) {
+ return new TestingGOTAtom(_file, target);
+ }
+
+private:
+ TestingPassFile _file;
+};
+
+
+class TestingWriterOptionsYAML : public lld::WriterOptionsYAML {
+public:
+ TestingWriterOptionsYAML(bool stubs, bool got)
+ : _doStubs(stubs), _doGOT(got) {
+ }
+
+ virtual StubsPass *stubPass() const {
+ if ( _doStubs )
+ return const_cast<TestingStubsPass*>(&_stubsPass);
+ else
+ return nullptr;
+ }
+
+ virtual GOTPass *gotPass() const {
+ if ( _doGOT )
+ return const_cast<TestingGOTPass*>(&_gotPass);
+ else
+ return nullptr;
+ }
+
+ virtual StringRef kindToString(Reference::Kind value) const {
+ for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) {
+ if ( value == p->value)
+ return p->string;
+ }
+ return StringRef("???");
+ }
+private:
+ bool _doStubs;
+ bool _doGOT;
+ TestingStubsPass _stubsPass;
+ TestingGOTPass _gotPass;
+};
+
+
+class TestingReaderOptionsYAML : public lld::ReaderOptionsYAML {
+ virtual Reference::Kind kindFromString(StringRef kindName) const {
+ for (const TestingKindMapping* p = sKinds; p->string != nullptr; ++p) {
+ if ( kindName.equals(p->string) )
+ return p->value;
+ }
+ int k;
+ if (kindName.getAsInteger(0, k))
+ k = 0;
+ return k;
+ }
+};
+
+
+
+#endif // LLD_TOOLS_TESTING_HELPERS_H_
diff --git a/lld/tools/lld-core/lld-core.cpp b/lld/tools/lld-core/lld-core.cpp
index 229ed868614..37e69cdca47 100644
--- a/lld/tools/lld-core/lld-core.cpp
+++ b/lld/tools/lld-core/lld-core.cpp
@@ -9,13 +9,17 @@
#include "lld/Core/Atom.h"
#include "lld/Core/LLVM.h"
-#include "lld/Core/NativeReader.h"
-#include "lld/Core/NativeWriter.h"
#include "lld/Core/Pass.h"
#include "lld/Core/Resolver.h"
-#include "lld/Core/YamlReader.h"
-#include "lld/Core/YamlWriter.h"
-#include "lld/Reader/Reader.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/ReaderNative.h"
+#include "lld/ReaderWriter/ReaderYAML.h"
+#include "lld/ReaderWriter/Writer.h"
+#include "lld/ReaderWriter/WriterELF.h"
+#include "lld/ReaderWriter/WriterMachO.h"
+#include "lld/ReaderWriter/WriterNative.h"
+#include "lld/ReaderWriter/WriterPECOFF.h"
+#include "lld/ReaderWriter/WriterYAML.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/CommandLine.h"
@@ -29,6 +33,8 @@
#include <vector>
+#include "TestingHelpers.hpp"
+
using namespace lld;
static void error(Twine message) {
@@ -43,311 +49,6 @@ static bool error(error_code ec) {
return false;
}
-namespace {
-
-
-//
-// Simple atom created by the stubs pass.
-//
-class TestingStubAtom : public DefinedAtom {
-public:
- TestingStubAtom(const File& f, const Atom& shlib) :
- _file(f), _shlib(shlib) {
- static uint32_t lastOrdinal = 0;
- _ordinal = lastOrdinal++;
- }
-
- virtual const File& file() const {
- return _file;
- }
-
- virtual StringRef name() const {
- return StringRef();
- }
-
- virtual uint64_t ordinal() const {
- return _ordinal;
- }
-
- virtual uint64_t size() const {
- return 0;
- }
-
- virtual Scope scope() const {
- return DefinedAtom::scopeLinkageUnit;
- }
-
- virtual Interposable interposable() const {
- return DefinedAtom::interposeNo;
- }
-
- virtual Merge merge() const {
- return DefinedAtom::mergeNo;
- }
-
- virtual ContentType contentType() const {
- return DefinedAtom::typeStub;
- }
-
- virtual Alignment alignment() const {
- return Alignment(0,0);
- }
-
- virtual SectionChoice sectionChoice() const {
- return DefinedAtom::sectionBasedOnContent;
- }
-
- virtual StringRef customSectionName() const {
- return StringRef();
- }
- virtual DeadStripKind deadStrip() const {
- return DefinedAtom::deadStripNormal;
- }
-
- virtual ContentPermissions permissions() const {
- return DefinedAtom::permR_X;
- }
-
- virtual bool isThumb() const {
- return false;
- }
-
- virtual bool isAlias() const {
- return false;
- }
-
- virtual ArrayRef<uint8_t> rawContent() const {
- return ArrayRef<uint8_t>();
- }
-
- virtual reference_iterator begin() const {
- return reference_iterator(*this, nullptr);
- }
-
- virtual reference_iterator end() const {
- return reference_iterator(*this, nullptr);
- }
-
- virtual const Reference* derefIterator(const void* iter) const {
- return nullptr;
- }
-
- virtual void incrementIterator(const void*& iter) const {
-
- }
-
-private:
- const File& _file;
- const Atom& _shlib;
- uint32_t _ordinal;
-};
-
-
-
-
-//
-// Simple atom created by the GOT pass.
-//
-class TestingGOTAtom : public DefinedAtom {
-public:
- TestingGOTAtom(const File& f, const Atom& shlib) :
- _file(f), _shlib(shlib) {
- static uint32_t lastOrdinal = 0;
- _ordinal = lastOrdinal++;
- }
-
- virtual const File& file() const {
- return _file;
- }
-
- virtual StringRef name() const {
- return StringRef();
- }
-
- virtual uint64_t ordinal() const {
- return _ordinal;
- }
-
- virtual uint64_t size() const {
- return 0;
- }
-
- virtual Scope scope() const {
- return DefinedAtom::scopeLinkageUnit;
- }
-
- virtual Interposable interposable() const {
- return DefinedAtom::interposeNo;
- }
-
- virtual Merge merge() const {
- return DefinedAtom::mergeNo;
- }
-
- virtual ContentType contentType() const {
- return DefinedAtom::typeGOT;
- }
-
- virtual Alignment alignment() const {
- return Alignment(3,0);
- }
-
- virtual SectionChoice sectionChoice() const {
- return DefinedAtom::sectionBasedOnContent;
- }
-
- virtual StringRef customSectionName() const {
- return StringRef();
- }
- virtual DeadStripKind deadStrip() const {
- return DefinedAtom::deadStripNormal;
- }
-
- virtual ContentPermissions permissions() const {
- return DefinedAtom::permRW_;
- }
-
- virtual bool isThumb() const {
- return false;
- }
-
- virtual bool isAlias() const {
- return false;
- }
-
- virtual ArrayRef<uint8_t> rawContent() const {
- return ArrayRef<uint8_t>();
- }
-
- virtual reference_iterator begin() const {
- return reference_iterator(*this, nullptr);
- }
-
- virtual reference_iterator end() const {
- return reference_iterator(*this, nullptr);
- }
-
- virtual const Reference* derefIterator(const void* iter) const {
- return nullptr;
- }
-
- virtual void incrementIterator(const void*& iter) const {
-
- }
-
-private:
- const File& _file;
- const Atom& _shlib;
- uint32_t _ordinal;
-};
-
-//
-// A simple platform for testing.
-//
-class TestingPlatform : public Platform {
-public:
-
- virtual void addFiles(InputFiles&) {
- }
-
- struct KindMapping {
- const char* string;
- Reference::Kind value;
- bool isBranch;
- bool isGotLoad;
- bool isGotUse;
- };
-
- static const KindMapping _s_kindMappings[];
-
- virtual Reference::Kind kindFromString(StringRef kindName) {
- for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) {
- if ( kindName.equals(p->string) )
- return p->value;
- }
- int k;
- if (kindName.getAsInteger(0, k))
- k = 0;
- return k;
- }
-
- virtual StringRef kindToString(Reference::Kind value) {
- for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) {
- if ( value == p->value)
- return p->string;
- }
- return StringRef("???");
- }
-
- virtual bool noTextRelocs() {
- return true;
- }
-
- virtual bool isCallSite(Reference::Kind kind) {
- for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) {
- if ( kind == p->value )
- return p->isBranch;
- }
- return false;
- }
-
- virtual bool isGOTAccess(Reference::Kind kind, bool& canBypassGOT) {
- for (const KindMapping* p = _s_kindMappings; p->string != nullptr; ++p) {
- if ( kind == p->value ) {
- canBypassGOT = p->isGotLoad;
- return p->isGotUse;
- }
- }
- return false;
- }
-
- virtual void updateReferenceToGOT(const Reference* ref, bool targetIsNowGOT) {
- if ( targetIsNowGOT )
- (const_cast<Reference*>(ref))->setKind(kindFromString("pcrel32"));
- else
- (const_cast<Reference*>(ref))->setKind(kindFromString("lea32wasGot"));
- }
-
-
-
- virtual const DefinedAtom *getStub(const Atom& shlibAtom, File& file) {
- const DefinedAtom *result = new TestingStubAtom(file, shlibAtom);
- _stubs.push_back(result);
- return result;
- }
-
- virtual const DefinedAtom* makeGOTEntry(const Atom& shlibAtom, File& file) {
- return new TestingGOTAtom(file, shlibAtom);
- }
-
- virtual void addStubAtoms(File &file) {
- for (const DefinedAtom *stub : _stubs) {
- file.addAtom(*stub);
- }
- }
-
- virtual void writeExecutable(const lld::File &, raw_ostream &out) {
- }
-private:
- std::vector<const DefinedAtom*> _stubs;
-};
-
-
-//
-// Table of fixup kinds in YAML documents used for testing
-//
-const TestingPlatform::KindMapping TestingPlatform::_s_kindMappings[] = {
- { "call32", 1, true, false, false},
- { "pcrel32", 2, false, false, false },
- { "gotLoad32", 3, false, true, true },
- { "gotUse32", 4, false, false, true },
- { "lea32wasGot", 5, false, false, false },
- { nullptr, 0, false, false, false }
- };
-
-
-} // anon namespace
-
llvm::cl::list<std::string>
cmdLineInputFilePaths(llvm::cl::Positional,
@@ -383,16 +84,18 @@ cmdLineGlobalsNotDeadStrip("keep-globals",
llvm::cl::desc("All global symbols are roots for dead-strip"));
-enum PlatformChoice {
- platformTesting, platformDarwin
+enum WriteChoice {
+ writeYAML, writeMachO, writePECOFF, writeELF
};
-llvm::cl::opt<PlatformChoice>
-platformSelected("platform",
- llvm::cl::desc("Select platform"),
+llvm::cl::opt<WriteChoice>
+writeSelected("writer",
+ llvm::cl::desc("Select writer"),
llvm::cl::values(
- clEnumValN(platformTesting, "none", "link for testing"),
- clEnumValN(platformDarwin, "darwin", "link as darwin would"),
+ clEnumValN(writeYAML, "YAML", "link assuming YAML format"),
+ clEnumValN(writeMachO, "mach-o", "link as darwin would"),
+ clEnumValN(writePECOFF, "PECOFF", "link as windows would"),
+ clEnumValN(writeELF, "ELF", "link as linux would"),
clEnumValEnd));
@@ -410,8 +113,6 @@ public:
-
-
int main(int argc, char *argv[]) {
// Print a stack trace if we signal out.
llvm::sys::PrintStackTraceOnErrorSignal();
@@ -421,108 +122,97 @@ int main(int argc, char *argv[]) {
// parse options
llvm::cl::ParseCommandLineOptions(argc, argv);
+ // if no input file specified, read from stdin
if (cmdLineInputFilePaths.empty())
cmdLineInputFilePaths.emplace_back("-");
- // create platform for testing
- Platform* platform = nullptr;
- switch ( platformSelected ) {
- case platformTesting:
- platform = new TestingPlatform();
+ // if no output path specified, write to stdout
+ if (cmdLineOutputFilePath.empty())
+ cmdLineOutputFilePath.assign("-");
+
+ // create writer for final output
+ TestingWriterOptionsYAML writerOptionsYAML(cmdLineDoStubsPass,
+ cmdLineDoGotPass);
+ WriterOptionsMachO writerOptionsMachO;
+ WriterOptionsPECOFF writerOptionsPECOFF;
+ WriterOptionsELF writerOptionsELF;
+ Writer* writer = nullptr;
+ switch ( writeSelected ) {
+ case writeYAML:
+ writer = createWriterYAML(writerOptionsYAML);
+ break;
+ case writeMachO:
+ writer = createWriterMachO(writerOptionsMachO);
+ break;
+ case writePECOFF:
+ writer = createWriterPECOFF(writerOptionsPECOFF);
break;
- case platformDarwin:
- platform = createDarwinPlatform();
+ case writeELF:
+ writer = createWriterELF(writerOptionsELF);
break;
}
- // read input YAML doc into object file(s)
- std::vector<std::unique_ptr<const File>> files;
+ // create object to mange input files
+ InputFiles inputFiles;
+
+ // read input files into in-memory File objects
+ TestingReaderOptionsYAML readerOptionsYAML;
+ Reader *reader = createReaderYAML(readerOptionsYAML);
for (auto path : cmdLineInputFilePaths) {
- OwningPtr<llvm::MemoryBuffer> ofile;
- if (error(llvm::MemoryBuffer::getFileOrSTDIN(path, ofile)))
+ std::vector<std::unique_ptr<File>> files;
+ if ( error(reader->readFile(path, files)) )
return 1;
- std::unique_ptr<llvm::MemoryBuffer> file(ofile.take());
- if (llvm::sys::fs::identify_magic(file->getBuffer())
- == llvm::sys::fs::file_magic::coff_object) {
- std::unique_ptr<File> f;
- if (error(parseCOFFObjectFile(std::move(file), f)))
- return 1;
- files.push_back(std::move(f));
- } else {
- if (error(yaml::parseObjectText( file.release()
- , *platform
- , files)))
- return 1;
- }
+ inputFiles.appendFiles(files);
}
+
+ // given writer a chance to add files
+ writer->addFiles(inputFiles);
// create options for resolving
TestingResolverOptions options;
- // create object to mange input files
- InputFiles inputFiles;
- for (const auto &file : files) {
- inputFiles.appendFile(*file);
- }
-
- platform->addFiles(inputFiles);
-
// merge all atom graphs
Resolver resolver(options, inputFiles);
resolver.resolve();
+ File &mergedMasterFile = resolver.resultFile();
// run passes
- if ( cmdLineDoGotPass ) {
- GOTPass addGot(resolver.resultFile(), *platform);
- addGot.perform();
+ if ( GOTPass *pass = writer->gotPass() ) {
+ pass->perform(mergedMasterFile);
}
- if ( cmdLineDoStubsPass ) {
- StubsPass addStubs(resolver.resultFile(), *platform);
- addStubs.perform();
+ if ( StubsPass *pass = writer->stubPass() ) {
+ pass->perform(mergedMasterFile);
}
-
-// yaml::writeObjectText(resolver.resultFile(), *platform, llvm::errs());
+ // showing yaml at this stage can help when debugging
+ const bool dumpIntermediateYAML = false;
+ if ( dumpIntermediateYAML )
+ writer->writeFile(mergedMasterFile, "-");
- // make unique temp .o file to put generated object file
- int fd;
- SmallString<128> tempPath;
- llvm::sys::fs::unique_file("temp%%%%%.o", fd, tempPath);
- llvm::raw_fd_ostream binaryOut(fd, /*shouldClose=*/true);
+ // make unique temp file to put generated native object file
+ llvm::sys::Path tmpNativePath = llvm::sys::Path::GetTemporaryDirectory();
+ if (tmpNativePath.createTemporaryFileOnDisk()) {
+ error("createTemporaryFileOnDisk() failed");
+ return 1;
+ }
- // write native file
- writeNativeObjectFile(resolver.resultFile(), binaryOut);
- binaryOut.close(); // manually close so that file can be read next
-
-// out << "native file: " << tempPath.str() << "\n";
+ // write as native file
+ WriterOptionsNative optionsNativeWriter;
+ Writer *natWriter = createWriterNative(optionsNativeWriter);
+ if (error(natWriter->writeFile(mergedMasterFile, tmpNativePath.c_str())))
+ return 1;
- // read native file
- std::unique_ptr<lld::File> natFile;
- if ( error(parseNativeObjectFileOrSTDIN(tempPath, natFile)) )
+ // read as native file
+ ReaderOptionsNative optionsNativeReader;
+ Reader *natReader = createReaderNative(optionsNativeReader);
+ std::vector<std::unique_ptr<File>> readNativeFiles;
+ if (error(natReader->readFile(tmpNativePath.c_str(), readNativeFiles)))
return 1;
-
- // write new atom graph
- std::string errorInfo;
- const char* outPath = (cmdLineOutputFilePath.empty() ? "-"
- : cmdLineOutputFilePath.c_str());
- llvm::raw_fd_ostream out(outPath, errorInfo);
- if ( platformSelected == platformTesting) {
- // write atom graph out as YAML doc
- yaml::writeObjectText(resolver.resultFile() /* *natFile */, *platform, out);
- }
- else {
- // write atom graph as an executable
- platform->writeExecutable(resolver.resultFile() /* *natFile */, out);
- // HACK. I don't see any way to set the 'executable' bit on files
- // in raw_fd_ostream or in llvm/Support.
-#if HAVE_SYS_STAT_H
- ::chmod(outPath, 0777);
-#endif
- }
-
- // delete temp .o file
- bool existed;
- llvm::sys::fs::remove(tempPath.str(), existed);
+ // write new atom graph
+ const File *parsedNativeFile = readNativeFiles[0].get();
+ if (error(writer->writeFile(*parsedNativeFile, cmdLineOutputFilePath)))
+ return 1;
+
return 0;
}
OpenPOWER on IntegriCloud