endif()
add_subdirectory(Common)
-add_subdirectory(lib)
add_subdirectory(tools/lld)
if (LLVM_INCLUDE_TESTS)
add_subdirectory(test)
- add_subdirectory(unittests)
endif()
add_subdirectory(docs)
llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
}
-namespace mach_o {
-bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
- llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
-}
-
namespace macho {
bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
public:
/// Which universe defines the kindValue().
enum class KindNamespace {
- all = 0,
+ all = 0,
testing = 1,
- mach_o = 2,
};
KindNamespace kindNamespace() const { return (KindNamespace)_kindNamespace; }
+++ /dev/null
-//===- lld/ReaderWriter/MachOLinkingContext.h -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <set>
-
-using llvm::MachO::HeaderFileType;
-
-namespace lld {
-
-namespace mach_o {
-class ArchHandler;
-class MachODylibFile;
-class MachOFile;
-class SectCreateFile;
-}
-
-class MachOLinkingContext : public LinkingContext {
-public:
- MachOLinkingContext();
- ~MachOLinkingContext() override;
-
- enum Arch {
- arch_unknown,
- arch_ppc,
- arch_x86,
- arch_x86_64,
- arch_armv6,
- arch_armv7,
- arch_armv7s,
- arch_arm64,
- };
-
- enum class OS {
- unknown,
- macOSX,
- iOS,
- iOS_simulator
- };
-
- enum class ExportMode {
- globals, // Default, all global symbols exported.
- exported, // -exported_symbol[s_list], only listed symbols exported.
- unexported // -unexported_symbol[s_list], no listed symbol exported.
- };
-
- enum class DebugInfoMode {
- addDebugMap, // Default
- noDebugMap // -S option
- };
-
- enum class UndefinedMode {
- error,
- warning,
- suppress,
- dynamicLookup
- };
-
- enum ObjCConstraint {
- objc_unknown = 0,
- objc_supports_gc = 2,
- objc_gc_only = 4,
- // Image optimized by dyld = 8
- // GC compaction = 16
- objc_retainReleaseForSimulator = 32,
- objc_retainRelease
- };
-
- /// Initializes the context to sane default values given the specified output
- /// file type, arch, os, and minimum os version. This should be called before
- /// other setXXX() methods.
- void configure(HeaderFileType type, Arch arch, OS os, uint32_t minOSVersion,
- bool exportDynamicSymbols);
-
- void addPasses(PassManager &pm) override;
- bool validateImpl() override;
- std::string demangle(StringRef symbolName) const override;
-
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- /// Creates a new file which is owned by the context. Returns a pointer to
- /// the new file.
- template <class T, class... Args>
- typename std::enable_if<!std::is_array<T>::value, T *>::type
- make_file(Args &&... args) const {
- auto file = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
- auto *filePtr = file.get();
- auto *ctx = const_cast<MachOLinkingContext *>(this);
- ctx->getNodes().push_back(std::make_unique<FileNode>(std::move(file)));
- return filePtr;
- }
-
- uint32_t getCPUType() const;
- uint32_t getCPUSubType() const;
-
- bool addEntryPointLoadCommand() const;
- bool addUnixThreadLoadCommand() const;
- bool outputTypeHasEntry() const;
- bool is64Bit() const;
-
- virtual uint64_t pageZeroSize() const { return _pageZeroSize; }
- virtual uint64_t pageSize() const { return _pageSize; }
-
- mach_o::ArchHandler &archHandler() const;
-
- HeaderFileType outputMachOType() const { return _outputMachOType; }
-
- Arch arch() const { return _arch; }
- StringRef archName() const { return nameFromArch(_arch); }
- OS os() const { return _os; }
-
- ExportMode exportMode() const { return _exportMode; }
- void setExportMode(ExportMode mode) { _exportMode = mode; }
- void addExportSymbol(StringRef sym);
- bool exportRestrictMode() const { return _exportMode != ExportMode::globals; }
- bool exportSymbolNamed(StringRef sym) const;
-
- DebugInfoMode debugInfoMode() const { return _debugInfoMode; }
- void setDebugInfoMode(DebugInfoMode mode) {
- _debugInfoMode = mode;
- }
-
- void appendOrderedSymbol(StringRef symbol, StringRef filename);
-
- bool keepPrivateExterns() const { return _keepPrivateExterns; }
- void setKeepPrivateExterns(bool v) { _keepPrivateExterns = v; }
- bool demangleSymbols() const { return _demangle; }
- void setDemangleSymbols(bool d) { _demangle = d; }
- bool mergeObjCCategories() const { return _mergeObjCCategories; }
- void setMergeObjCCategories(bool v) { _mergeObjCCategories = v; }
- /// Create file at specified path which will contain a binary encoding
- /// of all input and output file paths.
- std::error_code createDependencyFile(StringRef path);
- void addInputFileDependency(StringRef path) const;
- void addInputFileNotFound(StringRef path) const;
- void addOutputFileDependency(StringRef path) const;
-
- bool minOS(StringRef mac, StringRef iOS) const;
- void setDoNothing(bool value) { _doNothing = value; }
- bool doNothing() const { return _doNothing; }
- bool printAtoms() const { return _printAtoms; }
- bool testingFileUsage() const { return _testingFileUsage; }
- const StringRefVector &searchDirs() const { return _searchDirs; }
- const StringRefVector &frameworkDirs() const { return _frameworkDirs; }
- void setSysLibRoots(const StringRefVector &paths);
- const StringRefVector &sysLibRoots() const { return _syslibRoots; }
- bool PIE() const { return _pie; }
- void setPIE(bool pie) { _pie = pie; }
- bool generateVersionLoadCommand() const {
- return _generateVersionLoadCommand;
- }
- void setGenerateVersionLoadCommand(bool v) {
- _generateVersionLoadCommand = v;
- }
-
- bool generateFunctionStartsLoadCommand() const {
- return _generateFunctionStartsLoadCommand;
- }
- void setGenerateFunctionStartsLoadCommand(bool v) {
- _generateFunctionStartsLoadCommand = v;
- }
-
- bool generateDataInCodeLoadCommand() const {
- return _generateDataInCodeLoadCommand;
- }
- void setGenerateDataInCodeLoadCommand(bool v) {
- _generateDataInCodeLoadCommand = v;
- }
-
- uint64_t stackSize() const { return _stackSize; }
- void setStackSize(uint64_t stackSize) { _stackSize = stackSize; }
-
- uint64_t baseAddress() const { return _baseAddress; }
- void setBaseAddress(uint64_t baseAddress) { _baseAddress = baseAddress; }
-
- ObjCConstraint objcConstraint() const { return _objcConstraint; }
-
- uint32_t osMinVersion() const { return _osMinVersion; }
-
- uint32_t sdkVersion() const { return _sdkVersion; }
- void setSdkVersion(uint64_t v) { _sdkVersion = v; }
-
- uint64_t sourceVersion() const { return _sourceVersion; }
- void setSourceVersion(uint64_t v) { _sourceVersion = v; }
-
- uint32_t swiftVersion() const { return _swiftVersion; }
-
- /// Checks whether a given path on the filesystem exists.
- ///
- /// When running in -test_file_usage mode, this method consults an
- /// internally maintained list of files that exist (provided by -path_exists)
- /// instead of the actual filesystem.
- bool pathExists(StringRef path) const;
-
- /// Like pathExists() but only used on files - not directories.
- bool fileExists(StringRef path) const;
-
- /// Adds any library search paths derived from the given base, possibly
- /// modified by -syslibroots.
- ///
- /// The set of paths added consists of approximately all syslibroot-prepended
- /// versions of libPath that exist, or the original libPath if there are none
- /// for whatever reason. With various edge-cases for compatibility.
- void addModifiedSearchDir(StringRef libPath, bool isSystemPath = false);
-
- /// Determine whether -lFoo can be resolve within the given path, and
- /// return the filename if so.
- ///
- /// The -lFoo option is documented to search for libFoo.dylib and libFoo.a in
- /// that order, unless Foo ends in ".o", in which case only the exact file
- /// matches (e.g. -lfoo.o would only find foo.o).
- llvm::Optional<StringRef> searchDirForLibrary(StringRef path,
- StringRef libName) const;
-
- /// Iterates through all search path entries looking for libName (as
- /// specified by -lFoo).
- llvm::Optional<StringRef> searchLibrary(StringRef libName) const;
-
- /// Add a framework search path. Internally, this method may be prepended
- /// the path with syslibroot.
- void addFrameworkSearchDir(StringRef fwPath, bool isSystemPath = false);
-
- /// Iterates through all framework directories looking for
- /// Foo.framework/Foo (when fwName = "Foo").
- llvm::Optional<StringRef> findPathForFramework(StringRef fwName) const;
-
- /// The dylib's binary compatibility version, in the raw uint32 format.
- ///
- /// When building a dynamic library, this is the compatibility version that
- /// gets embedded into the result. Other Mach-O binaries that link against
- /// this library will store the compatibility version in its load command. At
- /// runtime, the loader will verify that the binary is compatible with the
- /// installed dynamic library.
- uint32_t compatibilityVersion() const { return _compatibilityVersion; }
-
- /// The dylib's current version, in the raw uint32 format.
- ///
- /// When building a dynamic library, this is the current version that gets
- /// embedded into the result. Other Mach-O binaries that link against
- /// this library will store the compatibility version in its load command.
- uint32_t currentVersion() const { return _currentVersion; }
-
- /// The dylib's install name.
- ///
- /// Binaries that link against the dylib will embed this path into the dylib
- /// load command. When loading the binaries at runtime, this is the location
- /// on disk that the loader will look for the dylib.
- StringRef installName() const { return _installName; }
-
- /// Whether or not the dylib has side effects during initialization.
- ///
- /// Dylibs marked as being dead strippable provide the guarantee that loading
- /// the dylib has no side effects, allowing the linker to strip out the dylib
- /// when linking a binary that does not use any of its symbols.
- bool deadStrippableDylib() const { return _deadStrippableDylib; }
-
- /// Whether or not to use flat namespace.
- ///
- /// MachO usually uses a two-level namespace, where each external symbol
- /// referenced by the target is associated with the dylib that will provide
- /// the symbol's definition at runtime. Using flat namespace overrides this
- /// behavior: the linker searches all dylibs on the command line and all
- /// dylibs those original dylibs depend on, but does not record which dylib
- /// an external symbol came from. At runtime dyld again searches all images
- /// and uses the first definition it finds. In addition, any undefines in
- /// loaded flat_namespace dylibs must be resolvable at build time.
- bool useFlatNamespace() const { return _flatNamespace; }
-
- /// How to handle undefined symbols.
- ///
- /// Options are:
- /// * error: Report an error and terminate linking.
- /// * warning: Report a warning, but continue linking.
- /// * suppress: Ignore and continue linking.
- /// * dynamic_lookup: For use with -twolevel namespace: Records source dylibs
- /// for symbols that are defined in a linked dylib at static link time.
- /// Undefined symbols are handled by searching all loaded images at
- /// runtime.
- UndefinedMode undefinedMode() const { return _undefinedMode; }
-
- /// The path to the executable that will load the bundle at runtime.
- ///
- /// When building a Mach-O bundle, this executable will be examined if there
- /// are undefined symbols after the main link phase. It is expected that this
- /// binary will be loading the bundle at runtime and will provide the symbols
- /// at that point.
- StringRef bundleLoader() const { return _bundleLoader; }
-
- void setCompatibilityVersion(uint32_t vers) { _compatibilityVersion = vers; }
- void setCurrentVersion(uint32_t vers) { _currentVersion = vers; }
- void setInstallName(StringRef name) { _installName = name; }
- void setDeadStrippableDylib(bool deadStrippable) {
- _deadStrippableDylib = deadStrippable;
- }
- void setUseFlatNamespace(bool flatNamespace) {
- _flatNamespace = flatNamespace;
- }
-
- void setUndefinedMode(UndefinedMode undefinedMode) {
- _undefinedMode = undefinedMode;
- }
-
- void setBundleLoader(StringRef loader) { _bundleLoader = loader; }
- void setPrintAtoms(bool value=true) { _printAtoms = value; }
- void setTestingFileUsage(bool value = true) {
- _testingFileUsage = value;
- }
- void addExistingPathForDebug(StringRef path) {
- _existingPaths.insert(path);
- }
-
- void addRpath(StringRef rpath);
- const StringRefVector &rpaths() const { return _rpaths; }
-
- /// Add section alignment constraint on final layout.
- void addSectionAlignment(StringRef seg, StringRef sect, uint16_t align);
-
- /// Add a section based on a command-line sectcreate option.
- void addSectCreateSection(StringRef seg, StringRef sect,
- std::unique_ptr<MemoryBuffer> content);
-
- /// Returns true if specified section had alignment constraints.
- bool sectionAligned(StringRef seg, StringRef sect, uint16_t &align) const;
-
- StringRef dyldPath() const { return "/usr/lib/dyld"; }
-
- /// Stub creation Pass should be run.
- bool needsStubsPass() const;
-
- // GOT creation Pass should be run.
- bool needsGOTPass() const;
-
- /// Pass to add TLV sections.
- bool needsTLVPass() const;
-
- /// Pass to transform __compact_unwind into __unwind_info should be run.
- bool needsCompactUnwindPass() const;
-
- /// Pass to add shims switching between thumb and arm mode.
- bool needsShimPass() const;
-
- /// Pass to add objc image info and optimized objc data.
- bool needsObjCPass() const;
-
- /// Magic symbol name stubs will need to help lazy bind.
- StringRef binderSymbolName() const;
-
- /// Used to keep track of direct and indirect dylibs.
- void registerDylib(mach_o::MachODylibFile *dylib, bool upward) const;
-
- // Reads a file from disk to memory. Returns only a needed chunk
- // if a fat binary.
- ErrorOr<std::unique_ptr<MemoryBuffer>> getMemoryBuffer(StringRef path);
-
- /// Used to find indirect dylibs. Instantiates a MachODylibFile if one
- /// has not already been made for the requested dylib. Uses -L and -F
- /// search paths to allow indirect dylibs to be overridden.
- mach_o::MachODylibFile* findIndirectDylib(StringRef path);
-
- uint32_t dylibCurrentVersion(StringRef installName) const;
-
- uint32_t dylibCompatVersion(StringRef installName) const;
-
- ArrayRef<mach_o::MachODylibFile*> allDylibs() const {
- return _allDylibs;
- }
-
- /// Creates a copy (owned by this MachOLinkingContext) of a string.
- StringRef copy(StringRef str) { return str.copy(_allocator); }
-
- /// If the memoryBuffer is a fat file with a slice for the current arch,
- /// this method will return the offset and size of that slice.
- bool sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset, uint32_t &size);
-
- /// Returns if a command line option specified dylib is an upward link.
- bool isUpwardDylib(StringRef installName) const;
-
- static bool isThinObjectFile(StringRef path, Arch &arch);
- static Arch archFromCpuType(uint32_t cputype, uint32_t cpusubtype);
- static Arch archFromName(StringRef archName);
- static StringRef nameFromArch(Arch arch);
- static uint32_t cpuTypeFromArch(Arch arch);
- static uint32_t cpuSubtypeFromArch(Arch arch);
- static bool is64Bit(Arch arch);
- static bool isHostEndian(Arch arch);
- static bool isBigEndian(Arch arch);
-
- /// Construct 32-bit value from string "X.Y.Z" where
- /// bits are xxxx.yy.zz. Largest number is 65535.255.255
- static bool parsePackedVersion(StringRef str, uint32_t &result);
-
- /// Construct 64-bit value from string "A.B.C.D.E" where
- /// bits are aaaa.bb.cc.dd.ee. Largest number is 16777215.1023.1023.1023.1023
- static bool parsePackedVersion(StringRef str, uint64_t &result);
-
- void finalizeInputFiles() override;
-
- llvm::Error handleLoadedFile(File &file) override;
-
- bool customAtomOrderer(const DefinedAtom *left, const DefinedAtom *right,
- bool &leftBeforeRight) const;
-
- /// Return the 'flat namespace' file. This is the file that supplies
- /// atoms for otherwise undefined symbols when the -flat_namespace or
- /// -undefined dynamic_lookup options are used.
- File* flatNamespaceFile() const { return _flatNamespaceFile; }
-
-private:
- Writer &writer() const override;
- mach_o::MachODylibFile* loadIndirectDylib(StringRef path);
- struct ArchInfo {
- StringRef archName;
- MachOLinkingContext::Arch arch;
- bool littleEndian;
- uint32_t cputype;
- uint32_t cpusubtype;
- };
-
- struct SectionAlign {
- StringRef segmentName;
- StringRef sectionName;
- uint16_t align;
- };
-
- struct OrderFileNode {
- StringRef fileFilter;
- unsigned order;
- };
-
- static bool findOrderOrdinal(const std::vector<OrderFileNode> &nodes,
- const DefinedAtom *atom, unsigned &ordinal);
-
- static ArchInfo _s_archInfos[];
-
- std::set<StringRef> _existingPaths; // For testing only.
- StringRefVector _searchDirs;
- StringRefVector _syslibRoots;
- StringRefVector _frameworkDirs;
- HeaderFileType _outputMachOType = llvm::MachO::MH_EXECUTE;
- bool _outputMachOTypeStatic = false; // Disambiguate static vs dynamic prog
- bool _doNothing = false; // for -help and -v which just print info
- bool _pie = false;
- Arch _arch = arch_unknown;
- OS _os = OS::macOSX;
- uint32_t _osMinVersion = 0;
- uint32_t _sdkVersion = 0;
- uint64_t _sourceVersion = 0;
- uint64_t _pageZeroSize = 0;
- uint64_t _pageSize = 4096;
- uint64_t _baseAddress = 0;
- uint64_t _stackSize = 0;
- uint32_t _compatibilityVersion = 0;
- uint32_t _currentVersion = 0;
- ObjCConstraint _objcConstraint = objc_unknown;
- uint32_t _swiftVersion = 0;
- StringRef _installName;
- StringRefVector _rpaths;
- bool _flatNamespace = false;
- UndefinedMode _undefinedMode = UndefinedMode::error;
- bool _deadStrippableDylib = false;
- bool _printAtoms = false;
- bool _testingFileUsage = false;
- bool _keepPrivateExterns = false;
- bool _demangle = false;
- bool _mergeObjCCategories = true;
- bool _generateVersionLoadCommand = false;
- bool _generateFunctionStartsLoadCommand = false;
- bool _generateDataInCodeLoadCommand = false;
- StringRef _bundleLoader;
- mutable std::unique_ptr<mach_o::ArchHandler> _archHandler;
- mutable std::unique_ptr<Writer> _writer;
- std::vector<SectionAlign> _sectAligns;
- mutable llvm::StringMap<mach_o::MachODylibFile*> _pathToDylibMap;
- mutable std::vector<mach_o::MachODylibFile*> _allDylibs;
- mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
- mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
- mutable std::mutex _dylibsMutex;
- ExportMode _exportMode = ExportMode::globals;
- llvm::StringSet<> _exportedSymbols;
- DebugInfoMode _debugInfoMode = DebugInfoMode::addDebugMap;
- std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
- llvm::StringMap<std::vector<OrderFileNode>> _orderFiles;
- unsigned _orderFileEntries = 0;
- File *_flatNamespaceFile = nullptr;
- mach_o::SectCreateFile *_sectCreateFile = nullptr;
-};
-
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
+++ /dev/null
-//===- lld/ReaderWriter/YamlContext.h - object used in YAML I/O context ---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_YAML_CONTEXT_H
-#define LLD_READER_WRITER_YAML_CONTEXT_H
-
-#include "lld/Common/LLVM.h"
-#include <functional>
-#include <memory>
-#include <vector>
-
-namespace lld {
-class File;
-class LinkingContext;
-class Registry;
-namespace mach_o {
-namespace normalized {
-struct NormalizedFile;
-}
-}
-
-using lld::mach_o::normalized::NormalizedFile;
-
-/// When YAML I/O is used in lld, the yaml context always holds a YamlContext
-/// object. We need to support hetergenous yaml documents which each require
-/// different context info. This struct supports all clients.
-struct YamlContext {
- const LinkingContext *_ctx = nullptr;
- const Registry *_registry = nullptr;
- File *_file = nullptr;
- NormalizedFile *_normalizeMachOFile = nullptr;
- StringRef _path;
-};
-
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_YAML_CONTEXT_H
+++ /dev/null
-add_subdirectory(Core)
-add_subdirectory(Driver)
-add_subdirectory(ReaderWriter)
+++ /dev/null
-add_lld_library(lldCore
- DefinedAtom.cpp
- Error.cpp
- File.cpp
- LinkingContext.cpp
- Reader.cpp
- Resolver.cpp
- SymbolTable.cpp
- Writer.cpp
-
- ADDITIONAL_HEADER_DIRS
- ${LLD_INCLUDE_DIR}/lld/Core
-
- LINK_COMPONENTS
- BinaryFormat
- MC
- Support
-
- LINK_LIBS
- ${LLVM_PTHREAD_LIB}
-
- DEPENDS
- intrinsics_gen
- )
+++ /dev/null
-//===- DefinedAtom.cpp ------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/ErrorHandling.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-
-namespace lld {
-
-DefinedAtom::ContentPermissions DefinedAtom::permissions() const {
- // By default base permissions on content type.
- return permissions(this->contentType());
-}
-
-// Utility function for deriving permissions from content type
-DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) {
- switch (type) {
- case typeCode:
- case typeResolver:
- case typeBranchIsland:
- case typeBranchShim:
- case typeStub:
- case typeStubHelper:
- case typeMachHeader:
- return permR_X;
-
- case typeConstant:
- case typeCString:
- case typeUTF16String:
- case typeCFI:
- case typeLSDA:
- case typeLiteral4:
- case typeLiteral8:
- case typeLiteral16:
- case typeDTraceDOF:
- case typeCompactUnwindInfo:
- case typeProcessedUnwindInfo:
- case typeObjCImageInfo:
- case typeObjCMethodList:
- return permR__;
-
- case typeData:
- case typeDataFast:
- case typeZeroFill:
- case typeZeroFillFast:
- case typeObjC1Class:
- case typeLazyPointer:
- case typeLazyDylibPointer:
- case typeNonLazyPointer:
- case typeThunkTLV:
- return permRW_;
-
- case typeGOT:
- case typeConstData:
- case typeCFString:
- case typeInitializerPtr:
- case typeTerminatorPtr:
- case typeCStringPtr:
- case typeObjCClassPtr:
- case typeObjC2CategoryList:
- case typeInterposingTuples:
- case typeTLVInitialData:
- case typeTLVInitialZeroFill:
- case typeTLVInitializerPtr:
- return permRW_L;
-
- case typeUnknown:
- case typeTempLTO:
- case typeSectCreate:
- case typeDSOHandle:
- return permUnknown;
- }
- llvm_unreachable("unknown content type");
-}
-
-} // namespace
+++ /dev/null
-//===- Error.cpp - system_error extensions for lld --------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Error.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <mutex>
-#include <string>
-#include <vector>
-
-using namespace lld;
-
-namespace {
-class _YamlReaderErrorCategory : public std::error_category {
-public:
- const char* name() const noexcept override {
- return "lld.yaml.reader";
- }
-
- std::string message(int ev) const override {
- switch (static_cast<YamlReaderError>(ev)) {
- case YamlReaderError::unknown_keyword:
- return "Unknown keyword found in yaml file";
- case YamlReaderError::illegal_value:
- return "Bad value found in yaml file";
- }
- llvm_unreachable("An enumerator of YamlReaderError does not have a "
- "message defined.");
- }
-};
-} // end anonymous namespace
-
-const std::error_category &lld::YamlReaderCategory() {
- static _YamlReaderErrorCategory o;
- return o;
-}
-
-namespace lld {
-
-/// Temporary class to enable make_dynamic_error_code() until
-/// llvm::ErrorOr<> is updated to work with error encapsulations
-/// other than error_code.
-class dynamic_error_category : public std::error_category {
-public:
- ~dynamic_error_category() override = default;
-
- const char *name() const noexcept override {
- return "lld.dynamic_error";
- }
-
- std::string message(int ev) const override {
- assert(ev >= 0);
- assert(ev < (int)_messages.size());
- // The value is an index into the string vector.
- return _messages[ev];
- }
-
- int add(std::string msg) {
- std::lock_guard<std::recursive_mutex> lock(_mutex);
- // Value zero is always the success value.
- if (_messages.empty())
- _messages.push_back("Success");
- _messages.push_back(msg);
- // Return the index of the string just appended.
- return _messages.size() - 1;
- }
-
-private:
- std::vector<std::string> _messages;
- std::recursive_mutex _mutex;
-};
-
-static dynamic_error_category categorySingleton;
-
-std::error_code make_dynamic_error_code(StringRef msg) {
- return std::error_code(categorySingleton.add(std::string(msg)),
- categorySingleton);
-}
-
-char GenericError::ID = 0;
-
-GenericError::GenericError(Twine Msg) : Msg(Msg.str()) { }
-
-void GenericError::log(raw_ostream &OS) const {
- OS << Msg;
-}
-
-} // namespace lld
+++ /dev/null
-//===- Core/File.cpp - A Container of Atoms -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/File.h"
-#include <mutex>
-
-namespace lld {
-
-File::~File() = default;
-
-File::AtomVector<DefinedAtom> File::_noDefinedAtoms;
-File::AtomVector<UndefinedAtom> File::_noUndefinedAtoms;
-File::AtomVector<SharedLibraryAtom> File::_noSharedLibraryAtoms;
-File::AtomVector<AbsoluteAtom> File::_noAbsoluteAtoms;
-
-std::error_code File::parse() {
- std::lock_guard<std::mutex> lock(_parseMutex);
- if (!_lastError.hasValue())
- _lastError = doParse();
- return _lastError.getValue();
-}
-
-} // end namespace lld
+++ /dev/null
-//===- lib/Core/LinkingContext.cpp - Linker Context Object Interface ------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Node.h"
-#include "lld/Core/Simple.h"
-#include "lld/Core/Writer.h"
-#include <algorithm>
-
-namespace lld {
-
-LinkingContext::LinkingContext() = default;
-
-LinkingContext::~LinkingContext() = default;
-
-bool LinkingContext::validate() {
- return validateImpl();
-}
-
-llvm::Error LinkingContext::writeFile(const File &linkedFile) const {
- return this->writer().writeFile(linkedFile, _outputPath);
-}
-
-std::unique_ptr<File> LinkingContext::createEntrySymbolFile() const {
- return createEntrySymbolFile("<command line option -e>");
-}
-
-std::unique_ptr<File>
-LinkingContext::createEntrySymbolFile(StringRef filename) const {
- if (entrySymbolName().empty())
- return nullptr;
- std::unique_ptr<SimpleFile> entryFile(new SimpleFile(filename,
- File::kindEntryObject));
- entryFile->addAtom(
- *(new (_allocator) SimpleUndefinedAtom(*entryFile, entrySymbolName())));
- return std::move(entryFile);
-}
-
-std::unique_ptr<File> LinkingContext::createUndefinedSymbolFile() const {
- return createUndefinedSymbolFile("<command line option -u or --defsym>");
-}
-
-std::unique_ptr<File>
-LinkingContext::createUndefinedSymbolFile(StringRef filename) const {
- if (_initialUndefinedSymbols.empty())
- return nullptr;
- std::unique_ptr<SimpleFile> undefinedSymFile(
- new SimpleFile(filename, File::kindUndefinedSymsObject));
- for (StringRef undefSym : _initialUndefinedSymbols)
- undefinedSymFile->addAtom(*(new (_allocator) SimpleUndefinedAtom(
- *undefinedSymFile, undefSym)));
- return std::move(undefinedSymFile);
-}
-
-void LinkingContext::createInternalFiles(
- std::vector<std::unique_ptr<File>> &result) const {
- if (std::unique_ptr<File> file = createEntrySymbolFile())
- result.push_back(std::move(file));
- if (std::unique_ptr<File> file = createUndefinedSymbolFile())
- result.push_back(std::move(file));
-}
-
-} // end namespace lld
+++ /dev/null
-//===- lib/Core/Reader.cpp ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Reader.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <algorithm>
-#include <memory>
-
-using llvm::file_magic;
-using llvm::identify_magic;
-
-namespace lld {
-
-YamlIOTaggedDocumentHandler::~YamlIOTaggedDocumentHandler() = default;
-
-void Registry::add(std::unique_ptr<Reader> reader) {
- _readers.push_back(std::move(reader));
-}
-
-void Registry::add(std::unique_ptr<YamlIOTaggedDocumentHandler> handler) {
- _yamlHandlers.push_back(std::move(handler));
-}
-
-ErrorOr<std::unique_ptr<File>>
-Registry::loadFile(std::unique_ptr<MemoryBuffer> mb) const {
- // Get file magic.
- StringRef content(mb->getBufferStart(), mb->getBufferSize());
- file_magic fileType = identify_magic(content);
-
- // Ask each registered reader if it can handle this file type or extension.
- for (const std::unique_ptr<Reader> &reader : _readers) {
- if (!reader->canParse(fileType, mb->getMemBufferRef()))
- continue;
- return reader->loadFile(std::move(mb), *this);
- }
-
- // No Reader could parse this file.
- return make_error_code(llvm::errc::executable_format_error);
-}
-
-static const Registry::KindStrings kindStrings[] = {
- {Reference::kindLayoutAfter, "layout-after"},
- {Reference::kindAssociate, "associate"},
- LLD_KIND_STRING_END};
-
-Registry::Registry() {
- addKindTable(Reference::KindNamespace::all, Reference::KindArch::all,
- kindStrings);
-}
-
-bool Registry::handleTaggedDoc(llvm::yaml::IO &io,
- const lld::File *&file) const {
- for (const std::unique_ptr<YamlIOTaggedDocumentHandler> &h : _yamlHandlers)
- if (h->handledDocTag(io, file))
- return true;
- return false;
-}
-
-void Registry::addKindTable(Reference::KindNamespace ns,
- Reference::KindArch arch,
- const KindStrings array[]) {
- KindEntry entry = { ns, arch, array };
- _kindEntries.push_back(entry);
-}
-
-bool Registry::referenceKindFromString(StringRef inputStr,
- Reference::KindNamespace &ns,
- Reference::KindArch &arch,
- Reference::KindValue &value) const {
- for (const KindEntry &entry : _kindEntries) {
- for (const KindStrings *pair = entry.array; !pair->name.empty(); ++pair) {
- if (!inputStr.equals(pair->name))
- continue;
- ns = entry.ns;
- arch = entry.arch;
- value = pair->value;
- return true;
- }
- }
- return false;
-}
-
-bool Registry::referenceKindToString(Reference::KindNamespace ns,
- Reference::KindArch arch,
- Reference::KindValue value,
- StringRef &str) const {
- for (const KindEntry &entry : _kindEntries) {
- if (entry.ns != ns)
- continue;
- if (entry.arch != arch)
- continue;
- for (const KindStrings *pair = entry.array; !pair->name.empty(); ++pair) {
- if (pair->value != value)
- continue;
- str = pair->name;
- return true;
- }
- }
- return false;
-}
-
-} // end namespace lld
+++ /dev/null
-//===- Core/Resolver.cpp - Resolves Atom References -----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Resolver.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/Core/SymbolTable.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <utility>
-#include <vector>
-
-namespace lld {
-
-llvm::Expected<bool> Resolver::handleFile(File &file) {
- if (auto ec = _ctx.handleLoadedFile(file))
- return std::move(ec);
- bool undefAdded = false;
- for (auto &atom : file.defined().owning_ptrs())
- doDefinedAtom(std::move(atom));
- for (auto &atom : file.undefined().owning_ptrs()) {
- if (doUndefinedAtom(std::move(atom)))
- undefAdded = true;
- }
- for (auto &atom : file.sharedLibrary().owning_ptrs())
- doSharedLibraryAtom(std::move(atom));
- for (auto &atom : file.absolute().owning_ptrs())
- doAbsoluteAtom(std::move(atom));
- return undefAdded;
-}
-
-llvm::Expected<bool> Resolver::forEachUndefines(File &file,
- UndefCallback callback) {
- size_t i = _undefineIndex[&file];
- bool undefAdded = false;
- do {
- for (; i < _undefines.size(); ++i) {
- StringRef undefName = _undefines[i];
- if (undefName.empty())
- continue;
- const Atom *atom = _symbolTable.findByName(undefName);
- if (!isa<UndefinedAtom>(atom) || _symbolTable.isCoalescedAway(atom)) {
- // The symbol was resolved by some other file. Cache the result.
- _undefines[i] = "";
- continue;
- }
- auto undefAddedOrError = callback(undefName);
- if (auto ec = undefAddedOrError.takeError())
- return std::move(ec);
- undefAdded |= undefAddedOrError.get();
- }
- } while (i < _undefines.size());
- _undefineIndex[&file] = i;
- return undefAdded;
-}
-
-llvm::Expected<bool> Resolver::handleArchiveFile(File &file) {
- ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&file);
- return forEachUndefines(file,
- [&](StringRef undefName) -> llvm::Expected<bool> {
- if (File *member = archiveFile->find(undefName)) {
- member->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- return handleFile(*member);
- }
- return false;
- });
-}
-
-llvm::Error Resolver::handleSharedLibrary(File &file) {
- // Add all the atoms from the shared library
- SharedLibraryFile *sharedLibrary = cast<SharedLibraryFile>(&file);
- auto undefAddedOrError = handleFile(*sharedLibrary);
- if (auto ec = undefAddedOrError.takeError())
- return ec;
- undefAddedOrError =
- forEachUndefines(file, [&](StringRef undefName) -> llvm::Expected<bool> {
- auto atom = sharedLibrary->exports(undefName);
- if (atom.get())
- doSharedLibraryAtom(std::move(atom));
- return false;
- });
-
- if (auto ec = undefAddedOrError.takeError())
- return ec;
- return llvm::Error::success();
-}
-
-bool Resolver::doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << " UndefinedAtom: "
- << llvm::format("0x%09lX", atom.get())
- << ", name=" << atom.get()->name() << "\n");
-
- // tell symbol table
- bool newUndefAdded = _symbolTable.add(*atom.get());
- if (newUndefAdded)
- _undefines.push_back(atom.get()->name());
-
- // add to list of known atoms
- _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-
- return newUndefAdded;
-}
-
-// Called on each atom when a file is added. Returns true if a given
-// atom is added to the symbol table.
-void Resolver::doDefinedAtom(OwningAtomPtr<DefinedAtom> atom) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << " DefinedAtom: "
- << llvm::format("0x%09lX", atom.get())
- << ", file=#"
- << atom.get()->file().ordinal()
- << ", atom=#"
- << atom.get()->ordinal()
- << ", name="
- << atom.get()->name()
- << ", type="
- << atom.get()->contentType()
- << "\n");
-
- // An atom that should never be dead-stripped is a dead-strip root.
- if (_ctx.deadStrip() &&
- atom.get()->deadStrip() == DefinedAtom::deadStripNever) {
- _deadStripRoots.insert(atom.get());
- }
-
- // add to list of known atoms
- _symbolTable.add(*atom.get());
- _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-}
-
-void Resolver::doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << " SharedLibraryAtom: "
- << llvm::format("0x%09lX", atom.get())
- << ", name="
- << atom.get()->name()
- << "\n");
-
- // tell symbol table
- _symbolTable.add(*atom.get());
-
- // add to list of known atoms
- _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-}
-
-void Resolver::doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << " AbsoluteAtom: "
- << llvm::format("0x%09lX", atom.get())
- << ", name="
- << atom.get()->name()
- << "\n");
-
- // tell symbol table
- if (atom.get()->scope() != Atom::scopeTranslationUnit)
- _symbolTable.add(*atom.get());
-
- // add to list of known atoms
- _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
-}
-
-// Returns true if at least one of N previous files has created an
-// undefined symbol.
-bool Resolver::undefinesAdded(int begin, int end) {
- std::vector<std::unique_ptr<Node>> &inputs = _ctx.getNodes();
- for (int i = begin; i < end; ++i)
- if (FileNode *node = dyn_cast<FileNode>(inputs[i].get()))
- if (_newUndefinesAdded[node->getFile()])
- return true;
- return false;
-}
-
-File *Resolver::getFile(int &index) {
- std::vector<std::unique_ptr<Node>> &inputs = _ctx.getNodes();
- if ((size_t)index >= inputs.size())
- return nullptr;
- if (GroupEnd *group = dyn_cast<GroupEnd>(inputs[index].get())) {
- // We are at the end of the current group. If one or more new
- // undefined atom has been added in the last groupSize files, we
- // reiterate over the files.
- int size = group->getSize();
- if (undefinesAdded(index - size, index)) {
- index -= size;
- return getFile(index);
- }
- ++index;
- return getFile(index);
- }
- return cast<FileNode>(inputs[index++].get())->getFile();
-}
-
-// Keep adding atoms until _ctx.getNextFile() returns an error. This
-// function is where undefined atoms are resolved.
-bool Resolver::resolveUndefines() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Resolving undefines:\n");
- ScopedTask task(getDefaultDomain(), "resolveUndefines");
- int index = 0;
- std::set<File *> seen;
- for (;;) {
- bool undefAdded = false;
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "Loading file #" << index << "\n");
- File *file = getFile(index);
- if (!file)
- return true;
- if (std::error_code ec = file->parse()) {
- llvm::errs() << "Cannot open " + file->path() << ": " << ec.message()
- << "\n";
- return false;
- }
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "Loaded file: " << file->path() << "\n");
- switch (file->kind()) {
- case File::kindErrorObject:
- case File::kindNormalizedObject:
- case File::kindMachObject:
- case File::kindCEntryObject:
- case File::kindHeaderObject:
- case File::kindEntryObject:
- case File::kindUndefinedSymsObject:
- case File::kindStubHelperObject:
- case File::kindResolverMergedObject:
- case File::kindSectCreateObject: {
- // The same file may be visited more than once if the file is
- // in --start-group and --end-group. Only library files should
- // be processed more than once.
- if (seen.count(file))
- break;
- seen.insert(file);
- assert(!file->hasOrdinal());
- file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- auto undefAddedOrError = handleFile(*file);
- if (auto EC = undefAddedOrError.takeError()) {
- // FIXME: This should be passed to logAllUnhandledErrors but it needs
- // to be passed a Twine instead of a string.
- llvm::errs() << "Error in " + file->path() << ": ";
- logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
- return false;
- }
- undefAdded = undefAddedOrError.get();
- break;
- }
- case File::kindArchiveLibrary: {
- if (!file->hasOrdinal())
- file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- auto undefAddedOrError = handleArchiveFile(*file);
- if (auto EC = undefAddedOrError.takeError()) {
- // FIXME: This should be passed to logAllUnhandledErrors but it needs
- // to be passed a Twine instead of a string.
- llvm::errs() << "Error in " + file->path() << ": ";
- logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
- return false;
- }
- undefAdded = undefAddedOrError.get();
- break;
- }
- case File::kindSharedLibrary:
- if (!file->hasOrdinal())
- file->setOrdinal(_ctx.getNextOrdinalAndIncrement());
- if (auto EC = handleSharedLibrary(*file)) {
- // FIXME: This should be passed to logAllUnhandledErrors but it needs
- // to be passed a Twine instead of a string.
- llvm::errs() << "Error in " + file->path() << ": ";
- logAllUnhandledErrors(std::move(EC), llvm::errs(), std::string());
- return false;
- }
- break;
- }
- _newUndefinesAdded[file] = undefAdded;
- }
-}
-
-// switch all references to undefined or coalesced away atoms
-// to the new defined atom
-void Resolver::updateReferences() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Updating references:\n");
- ScopedTask task(getDefaultDomain(), "updateReferences");
- for (const OwningAtomPtr<Atom> &atom : _atoms) {
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get())) {
- for (const Reference *ref : *defAtom) {
- // A reference of type kindAssociate shouldn't be updated.
- // Instead, an atom having such reference will be removed
- // if the target atom is coalesced away, so that they will
- // go away as a group.
- if (ref->kindNamespace() == lld::Reference::KindNamespace::all &&
- ref->kindValue() == lld::Reference::kindAssociate) {
- if (_symbolTable.isCoalescedAway(atom.get()))
- _deadAtoms.insert(ref->target());
- continue;
- }
- const Atom *newTarget = _symbolTable.replacement(ref->target());
- const_cast<Reference *>(ref)->setTarget(newTarget);
- }
- }
- }
-}
-
-// For dead code stripping, recursively mark atoms "live"
-void Resolver::markLive(const Atom *atom) {
- // Mark the atom is live. If it's already marked live, then stop recursion.
- auto exists = _liveAtoms.insert(atom);
- if (!exists.second)
- return;
-
- // Mark all atoms it references as live
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
- for (const Reference *ref : *defAtom)
- markLive(ref->target());
- for (auto &p : llvm::make_range(_reverseRef.equal_range(defAtom))) {
- const Atom *target = p.second;
- markLive(target);
- }
- }
-}
-
-static bool isBackref(const Reference *ref) {
- if (ref->kindNamespace() != lld::Reference::KindNamespace::all)
- return false;
- return (ref->kindValue() == lld::Reference::kindLayoutAfter);
-}
-
-// remove all atoms not actually used
-void Resolver::deadStripOptimize() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Dead stripping unused atoms:\n");
- ScopedTask task(getDefaultDomain(), "deadStripOptimize");
- // only do this optimization with -dead_strip
- if (!_ctx.deadStrip())
- return;
-
- // Some type of references prevent referring atoms to be dead-striped.
- // Make a reverse map of such references before traversing the graph.
- // While traversing the list of atoms, mark AbsoluteAtoms as live
- // in order to avoid reclaim.
- for (const OwningAtomPtr<Atom> &atom : _atoms) {
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
- for (const Reference *ref : *defAtom)
- if (isBackref(ref))
- _reverseRef.insert(std::make_pair(ref->target(), atom.get()));
- if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom.get()))
- markLive(absAtom);
- }
-
- // By default, shared libraries are built with all globals as dead strip roots
- if (_ctx.globalsAreDeadStripRoots())
- for (const OwningAtomPtr<Atom> &atom : _atoms)
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
- if (defAtom->scope() == DefinedAtom::scopeGlobal)
- _deadStripRoots.insert(defAtom);
-
- // Or, use list of names that are dead strip roots.
- for (const StringRef &name : _ctx.deadStripRoots()) {
- const Atom *symAtom = _symbolTable.findByName(name);
- assert(symAtom);
- _deadStripRoots.insert(symAtom);
- }
-
- // mark all roots as live, and recursively all atoms they reference
- for (const Atom *dsrAtom : _deadStripRoots)
- markLive(dsrAtom);
-
- // now remove all non-live atoms from _atoms
- llvm::erase_if(_atoms, [&](OwningAtomPtr<Atom> &a) {
- return _liveAtoms.count(a.get()) == 0;
- });
-}
-
-// error out if some undefines remain
-bool Resolver::checkUndefines() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Checking for undefines:\n");
-
- // build vector of remaining undefined symbols
- std::vector<const UndefinedAtom *> undefinedAtoms = _symbolTable.undefines();
- if (_ctx.deadStrip()) {
- // When dead code stripping, we don't care if dead atoms are undefined.
- llvm::erase_if(undefinedAtoms,
- [&](const Atom *a) { return _liveAtoms.count(a) == 0; });
- }
-
- if (undefinedAtoms.empty())
- return false;
-
- // Warn about unresolved symbols.
- bool foundUndefines = false;
- for (const UndefinedAtom *undef : undefinedAtoms) {
- // Skip over a weak symbol.
- if (undef->canBeNull() != UndefinedAtom::canBeNullNever)
- continue;
-
- // If this is a library and undefined symbols are allowed on the
- // target platform, skip over it.
- if (isa<SharedLibraryFile>(undef->file()) && _ctx.allowShlibUndefines())
- continue;
-
- // If the undefine is coalesced away, skip over it.
- if (_symbolTable.isCoalescedAway(undef))
- continue;
-
- // Seems like this symbol is undefined. Warn that.
- foundUndefines = true;
- if (_ctx.printRemainingUndefines()) {
- llvm::errs() << "Undefined symbol: " << undef->file().path() << ": "
- << _ctx.demangle(undef->name()) << "\n";
- }
- }
- if (!foundUndefines)
- return false;
- if (_ctx.printRemainingUndefines())
- llvm::errs() << "symbol(s) not found\n";
- return true;
-}
-
-// Remove from _atoms all coalesced away atoms.
-void Resolver::removeCoalescedAwayAtoms() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Removing coalesced away atoms:\n");
- ScopedTask task(getDefaultDomain(), "removeCoalescedAwayAtoms");
- llvm::erase_if(_atoms, [&](OwningAtomPtr<Atom> &a) {
- return _symbolTable.isCoalescedAway(a.get()) || _deadAtoms.count(a.get());
- });
-}
-
-bool Resolver::resolve() {
- DEBUG_WITH_TYPE("resolver",
- llvm::dbgs() << "******** Resolving atom references:\n");
- if (!resolveUndefines())
- return false;
- updateReferences();
- deadStripOptimize();
- if (checkUndefines()) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Found undefines... ");
- if (!_ctx.allowRemainingUndefines()) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "which we don't allow\n");
- return false;
- }
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "which we are ok with\n");
- }
- removeCoalescedAwayAtoms();
- _result->addAtoms(_atoms);
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "******** Finished resolver\n");
- return true;
-}
-
-void Resolver::MergedFile::addAtoms(
- llvm::MutableArrayRef<OwningAtomPtr<Atom>> all) {
- ScopedTask task(getDefaultDomain(), "addAtoms");
- DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
-
- for (OwningAtomPtr<Atom> &atom : all) {
-#ifndef NDEBUG
- if (auto *definedAtom = dyn_cast<DefinedAtom>(atom.get())) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << llvm::format(" 0x%09lX", definedAtom)
- << ", file=#"
- << definedAtom->file().ordinal()
- << ", atom=#"
- << definedAtom->ordinal()
- << ", name="
- << definedAtom->name()
- << ", type="
- << definedAtom->contentType()
- << "\n");
- } else {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << llvm::format(" 0x%09lX", atom.get())
- << ", name="
- << atom.get()->name()
- << "\n");
- }
-#endif
- addAtom(*atom.release());
- }
-}
-
-} // namespace lld
+++ /dev/null
-//===- Core/SymbolTable.cpp - Main Symbol Table ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/SymbolTable.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/AbsoluteAtom.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Resolver.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdlib>
-#include <vector>
-
-namespace lld {
-bool SymbolTable::add(const UndefinedAtom &atom) { return addByName(atom); }
-
-bool SymbolTable::add(const SharedLibraryAtom &atom) { return addByName(atom); }
-
-bool SymbolTable::add(const AbsoluteAtom &atom) { return addByName(atom); }
-
-bool SymbolTable::add(const DefinedAtom &atom) {
- if (!atom.name().empty() &&
- atom.scope() != DefinedAtom::scopeTranslationUnit) {
- // Named atoms cannot be merged by content.
- assert(atom.merge() != DefinedAtom::mergeByContent);
- // Track named atoms that are not scoped to file (static).
- return addByName(atom);
- }
- if (atom.merge() == DefinedAtom::mergeByContent) {
- // Named atoms cannot be merged by content.
- assert(atom.name().empty());
- // Currently only read-only constants can be merged.
- if (atom.permissions() == DefinedAtom::permR__)
- return addByContent(atom);
- // TODO: support mergeByContent of data atoms by comparing content & fixups.
- }
- return false;
-}
-
-enum NameCollisionResolution {
- NCR_First,
- NCR_Second,
- NCR_DupDef,
- NCR_DupUndef,
- NCR_DupShLib,
- NCR_Error
-};
-
-static NameCollisionResolution cases[4][4] = {
- //regular absolute undef sharedLib
- {
- // first is regular
- NCR_DupDef, NCR_Error, NCR_First, NCR_First
- },
- {
- // first is absolute
- NCR_Error, NCR_Error, NCR_First, NCR_First
- },
- {
- // first is undef
- NCR_Second, NCR_Second, NCR_DupUndef, NCR_Second
- },
- {
- // first is sharedLib
- NCR_Second, NCR_Second, NCR_First, NCR_DupShLib
- }
-};
-
-static NameCollisionResolution collide(Atom::Definition first,
- Atom::Definition second) {
- return cases[first][second];
-}
-
-enum MergeResolution {
- MCR_First,
- MCR_Second,
- MCR_Largest,
- MCR_SameSize,
- MCR_Error
-};
-
-static MergeResolution mergeCases[][6] = {
- // no tentative weak weakAddress sameNameAndSize largest
- {MCR_Error, MCR_First, MCR_First, MCR_First, MCR_SameSize, MCR_Largest}, // no
- {MCR_Second, MCR_Largest, MCR_Second, MCR_Second, MCR_SameSize, MCR_Largest}, // tentative
- {MCR_Second, MCR_First, MCR_First, MCR_Second, MCR_SameSize, MCR_Largest}, // weak
- {MCR_Second, MCR_First, MCR_First, MCR_First, MCR_SameSize, MCR_Largest}, // weakAddress
- {MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize, MCR_SameSize}, // sameSize
- {MCR_Largest, MCR_Largest, MCR_Largest, MCR_Largest, MCR_SameSize, MCR_Largest}, // largest
-};
-
-static MergeResolution mergeSelect(DefinedAtom::Merge first,
- DefinedAtom::Merge second) {
- assert(first != DefinedAtom::mergeByContent);
- assert(second != DefinedAtom::mergeByContent);
- return mergeCases[first][second];
-}
-
-bool SymbolTable::addByName(const Atom &newAtom) {
- StringRef name = newAtom.name();
- assert(!name.empty());
- const Atom *existing = findByName(name);
- if (existing == nullptr) {
- // Name is not in symbol table yet, add it associate with this atom.
- _nameTable[name] = &newAtom;
- return true;
- }
-
- // Do nothing if the same object is added more than once.
- if (existing == &newAtom)
- return false;
-
- // Name is already in symbol table and associated with another atom.
- bool useNew = true;
- switch (collide(existing->definition(), newAtom.definition())) {
- case NCR_First:
- useNew = false;
- break;
- case NCR_Second:
- useNew = true;
- break;
- case NCR_DupDef: {
- const auto *existingDef = cast<DefinedAtom>(existing);
- const auto *newDef = cast<DefinedAtom>(&newAtom);
- switch (mergeSelect(existingDef->merge(), newDef->merge())) {
- case MCR_First:
- useNew = false;
- break;
- case MCR_Second:
- useNew = true;
- break;
- case MCR_Largest: {
- uint64_t existingSize = existingDef->sectionSize();
- uint64_t newSize = newDef->sectionSize();
- useNew = (newSize >= existingSize);
- break;
- }
- case MCR_SameSize: {
- uint64_t existingSize = existingDef->sectionSize();
- uint64_t newSize = newDef->sectionSize();
- if (existingSize == newSize) {
- useNew = true;
- break;
- }
- llvm::errs() << "Size mismatch: " << existing->name() << " ("
- << existingSize << ") " << newAtom.name() << " (" << newSize
- << ")\n";
- LLVM_FALLTHROUGH;
- }
- case MCR_Error:
- llvm::errs() << "Duplicate symbols: " << existing->name() << ":"
- << existing->file().path() << " and " << newAtom.name()
- << ":" << newAtom.file().path() << "\n";
- llvm::report_fatal_error("duplicate symbol error");
- break;
- }
- break;
- }
- case NCR_DupUndef: {
- const UndefinedAtom* existingUndef = cast<UndefinedAtom>(existing);
- const UndefinedAtom* newUndef = cast<UndefinedAtom>(&newAtom);
-
- bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
- if (sameCanBeNull)
- useNew = false;
- else
- useNew = (newUndef->canBeNull() < existingUndef->canBeNull());
- break;
- }
- case NCR_DupShLib: {
- useNew = false;
- break;
- }
- case NCR_Error:
- llvm::errs() << "SymbolTable: error while merging " << name << "\n";
- llvm::report_fatal_error("duplicate symbol error");
- break;
- }
-
- if (useNew) {
- // Update name table to use new atom.
- _nameTable[name] = &newAtom;
- // Add existing atom to replacement table.
- _replacedAtoms[existing] = &newAtom;
- } else {
- // New atom is not being used. Add it to replacement table.
- _replacedAtoms[&newAtom] = existing;
- }
- return false;
-}
-
-unsigned SymbolTable::AtomMappingInfo::getHashValue(const DefinedAtom *atom) {
- auto content = atom->rawContent();
- return llvm::hash_combine(atom->size(),
- atom->contentType(),
- llvm::hash_combine_range(content.begin(),
- content.end()));
-}
-
-bool SymbolTable::AtomMappingInfo::isEqual(const DefinedAtom * const l,
- const DefinedAtom * const r) {
- if (l == r)
- return true;
- if (l == getEmptyKey() || r == getEmptyKey())
- return false;
- if (l == getTombstoneKey() || r == getTombstoneKey())
- return false;
- if (l->contentType() != r->contentType())
- return false;
- if (l->size() != r->size())
- return false;
- if (l->sectionChoice() != r->sectionChoice())
- return false;
- if (l->sectionChoice() == DefinedAtom::sectionCustomRequired) {
- if (!l->customSectionName().equals(r->customSectionName()))
- return false;
- }
- ArrayRef<uint8_t> lc = l->rawContent();
- ArrayRef<uint8_t> rc = r->rawContent();
- return memcmp(lc.data(), rc.data(), lc.size()) == 0;
-}
-
-bool SymbolTable::addByContent(const DefinedAtom &newAtom) {
- AtomContentSet::iterator pos = _contentTable.find(&newAtom);
- if (pos == _contentTable.end()) {
- _contentTable.insert(&newAtom);
- return true;
- }
- const Atom* existing = *pos;
- // New atom is not being used. Add it to replacement table.
- _replacedAtoms[&newAtom] = existing;
- return false;
-}
-
-const Atom *SymbolTable::findByName(StringRef sym) {
- NameToAtom::iterator pos = _nameTable.find(sym);
- if (pos == _nameTable.end())
- return nullptr;
- return pos->second;
-}
-
-const Atom *SymbolTable::replacement(const Atom *atom) {
- // Find the replacement for a given atom. Atoms in _replacedAtoms
- // may be chained, so find the last one.
- for (;;) {
- AtomToAtom::iterator pos = _replacedAtoms.find(atom);
- if (pos == _replacedAtoms.end())
- return atom;
- atom = pos->second;
- }
-}
-
-bool SymbolTable::isCoalescedAway(const Atom *atom) {
- return _replacedAtoms.count(atom) > 0;
-}
-
-std::vector<const UndefinedAtom *> SymbolTable::undefines() {
- std::vector<const UndefinedAtom *> ret;
- for (auto it : _nameTable) {
- const Atom *atom = it.second;
- assert(atom != nullptr);
- if (const auto *undef = dyn_cast<const UndefinedAtom>(atom))
- if (_replacedAtoms.count(undef) == 0)
- ret.push_back(undef);
- }
- return ret;
-}
-
-} // namespace lld
+++ /dev/null
-//===- lib/Core/Writer.cpp ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/Writer.h"
-
-namespace lld {
-
-Writer::Writer() = default;
-
-Writer::~Writer() = default;
-
-} // end namespace lld
+++ /dev/null
-set(LLVM_TARGET_DEFINITIONS DarwinLdOptions.td)
-tablegen(LLVM DarwinLdOptions.inc -gen-opt-parser-defs)
-add_public_tablegen_target(DriverOptionsTableGen)
-
-add_lld_library(lldDriver
- DarwinLdDriver.cpp
-
- ADDITIONAL_HEADER_DIRS
- ${LLD_INCLUDE_DIR}/lld/Driver
-
- LINK_COMPONENTS
- Option
- Support
-
- LINK_LIBS
- lldCommon
- lldCore
- lldMachOOld
- lldReaderWriter
- lldYAML
- )
-
-add_dependencies(lldDriver DriverOptionsTableGen)
+++ /dev/null
-//===- lib/Driver/DarwinLdDriver.cpp --------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// Concrete instance of the Driver for darwin's ld.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Common/Args.h"
-#include "lld/Common/ErrorHandler.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Node.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/Resolver.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Option/OptTable.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <system_error>
-#include <utility>
-#include <vector>
-
-using namespace lld;
-
-namespace {
-
-// Create enum with OPT_xxx values for each option in DarwinLdOptions.td
-enum {
- OPT_INVALID = 0,
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELP, META, VALUES) \
- OPT_##ID,
-#include "DarwinLdOptions.inc"
-#undef OPTION
-};
-
-// Create prefix string literals used in DarwinLdOptions.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "DarwinLdOptions.inc"
-#undef PREFIX
-
-// Create table mapping all options defined in DarwinLdOptions.td
-static const llvm::opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR, VALUES) \
- {PREFIX, NAME, HELPTEXT, \
- METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
- PARAM, FLAGS, OPT_##GROUP, \
- OPT_##ALIAS, ALIASARGS, VALUES},
-#include "DarwinLdOptions.inc"
-#undef OPTION
-};
-
-// Create OptTable class for parsing actual command line arguments
-class DarwinLdOptTable : public llvm::opt::OptTable {
-public:
- DarwinLdOptTable() : OptTable(InfoTable) {}
-};
-
-static std::vector<std::unique_ptr<File>>
-makeErrorFile(StringRef path, std::error_code ec) {
- std::vector<std::unique_ptr<File>> result;
- result.push_back(std::make_unique<ErrorFile>(path, ec));
- return result;
-}
-
-static std::vector<std::unique_ptr<File>>
-parseMemberFiles(std::unique_ptr<File> file) {
- std::vector<std::unique_ptr<File>> members;
- if (auto *archive = dyn_cast<ArchiveLibraryFile>(file.get())) {
- if (std::error_code ec = archive->parseAllMembers(members))
- return makeErrorFile(file->path(), ec);
- } else {
- members.push_back(std::move(file));
- }
- return members;
-}
-
-std::vector<std::unique_ptr<File>> loadFile(MachOLinkingContext &ctx,
- StringRef path, bool wholeArchive,
- bool upwardDylib) {
- if (ctx.logInputFiles())
- message(path);
-
- ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = ctx.getMemoryBuffer(path);
- if (std::error_code ec = mbOrErr.getError())
- return makeErrorFile(path, ec);
- ErrorOr<std::unique_ptr<File>> fileOrErr =
- ctx.registry().loadFile(std::move(mbOrErr.get()));
- if (std::error_code ec = fileOrErr.getError())
- return makeErrorFile(path, ec);
- std::unique_ptr<File> &file = fileOrErr.get();
-
- // If file is a dylib, inform LinkingContext about it.
- if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(file.get())) {
- if (std::error_code ec = shl->parse())
- return makeErrorFile(path, ec);
- ctx.registerDylib(reinterpret_cast<mach_o::MachODylibFile *>(shl),
- upwardDylib);
- }
- if (wholeArchive)
- return parseMemberFiles(std::move(file));
- std::vector<std::unique_ptr<File>> files;
- files.push_back(std::move(file));
- return files;
-}
-
-} // end anonymous namespace
-
-// Test may be running on Windows. Canonicalize the path
-// separator to '/' to get consistent outputs for tests.
-static std::string canonicalizePath(StringRef path) {
- char sep = llvm::sys::path::get_separator().front();
- if (sep != '/') {
- std::string fixedPath = std::string(path);
- std::replace(fixedPath.begin(), fixedPath.end(), sep, '/');
- return fixedPath;
- } else {
- return std::string(path);
- }
-}
-
-static void addFile(StringRef path, MachOLinkingContext &ctx,
- bool loadWholeArchive, bool upwardDylib) {
- std::vector<std::unique_ptr<File>> files =
- loadFile(ctx, path, loadWholeArchive, upwardDylib);
- for (std::unique_ptr<File> &file : files)
- ctx.getNodes().push_back(std::make_unique<FileNode>(std::move(file)));
-}
-
-// Export lists are one symbol per line. Blank lines are ignored.
-// Trailing comments start with #.
-static std::error_code parseExportsList(StringRef exportFilePath,
- MachOLinkingContext &ctx) {
- // Map in export list file.
- ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
- MemoryBuffer::getFileOrSTDIN(exportFilePath);
- if (std::error_code ec = mb.getError())
- return ec;
- ctx.addInputFileDependency(exportFilePath);
- StringRef buffer = mb->get()->getBuffer();
- while (!buffer.empty()) {
- // Split off each line in the file.
- std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n');
- StringRef line = lineAndRest.first;
- // Ignore trailing # comments.
- std::pair<StringRef, StringRef> symAndComment = line.split('#');
- StringRef sym = symAndComment.first.trim();
- if (!sym.empty())
- ctx.addExportSymbol(sym);
- buffer = lineAndRest.second;
- }
- return std::error_code();
-}
-
-/// Order files are one symbol per line. Blank lines are ignored.
-/// Trailing comments start with #. Symbol names can be prefixed with an
-/// architecture name and/or .o leaf name. Examples:
-/// _foo
-/// bar.o:_bar
-/// libfrob.a(bar.o):_bar
-/// x86_64:_foo64
-static std::error_code parseOrderFile(StringRef orderFilePath,
- MachOLinkingContext &ctx) {
- // Map in order file.
- ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
- MemoryBuffer::getFileOrSTDIN(orderFilePath);
- if (std::error_code ec = mb.getError())
- return ec;
- ctx.addInputFileDependency(orderFilePath);
- StringRef buffer = mb->get()->getBuffer();
- while (!buffer.empty()) {
- // Split off each line in the file.
- std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n');
- StringRef line = lineAndRest.first;
- buffer = lineAndRest.second;
- // Ignore trailing # comments.
- std::pair<StringRef, StringRef> symAndComment = line.split('#');
- if (symAndComment.first.empty())
- continue;
- StringRef sym = symAndComment.first.trim();
- if (sym.empty())
- continue;
- // Check for prefix.
- StringRef prefix;
- std::pair<StringRef, StringRef> prefixAndSym = sym.split(':');
- if (!prefixAndSym.second.empty()) {
- sym = prefixAndSym.second;
- prefix = prefixAndSym.first;
- if (!prefix.endswith(".o") && !prefix.endswith(".o)")) {
- // If arch name prefix does not match arch being linked, ignore symbol.
- if (!ctx.archName().equals(prefix))
- continue;
- prefix = "";
- }
- } else
- sym = prefixAndSym.first;
- if (!sym.empty()) {
- ctx.appendOrderedSymbol(sym, prefix);
- // llvm::errs() << sym << ", prefix=" << prefix << "\n";
- }
- }
- return std::error_code();
-}
-
-//
-// There are two variants of the -filelist option:
-//
-// -filelist <path>
-// In this variant, the path is to a text file which contains one file path
-// per line. There are no comments or trimming of whitespace.
-//
-// -fileList <path>,<dir>
-// In this variant, the path is to a text file which contains a partial path
-// per line. The <dir> prefix is prepended to each partial path.
-//
-static llvm::Error loadFileList(StringRef fileListPath,
- MachOLinkingContext &ctx, bool forceLoad) {
- // If there is a comma, split off <dir>.
- std::pair<StringRef, StringRef> opt = fileListPath.split(',');
- StringRef filePath = opt.first;
- StringRef dirName = opt.second;
- ctx.addInputFileDependency(filePath);
- // Map in file list file.
- ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
- MemoryBuffer::getFileOrSTDIN(filePath);
- if (std::error_code ec = mb.getError())
- return llvm::errorCodeToError(ec);
- StringRef buffer = mb->get()->getBuffer();
- while (!buffer.empty()) {
- // Split off each line in the file.
- std::pair<StringRef, StringRef> lineAndRest = buffer.split('\n');
- StringRef line = lineAndRest.first;
- StringRef path;
- if (!dirName.empty()) {
- // If there is a <dir> then prepend dir to each line.
- SmallString<256> fullPath;
- fullPath.assign(dirName);
- llvm::sys::path::append(fullPath, Twine(line));
- path = ctx.copy(fullPath.str());
- } else {
- // No <dir> use whole line as input file path.
- path = ctx.copy(line);
- }
- if (!ctx.pathExists(path)) {
- return llvm::make_error<GenericError>(Twine("File not found '")
- + path
- + "'");
- }
- if (ctx.testingFileUsage()) {
- message("Found filelist entry " + canonicalizePath(path));
- }
- addFile(path, ctx, forceLoad, false);
- buffer = lineAndRest.second;
- }
- return llvm::Error::success();
-}
-
-/// Parse number assuming it is base 16, but allow 0x prefix.
-static bool parseNumberBase16(StringRef numStr, uint64_t &baseAddress) {
- if (numStr.startswith_insensitive("0x"))
- numStr = numStr.drop_front(2);
- return numStr.getAsInteger(16, baseAddress);
-}
-
-static void parseLLVMOptions(const LinkingContext &ctx) {
- // Honor -mllvm
- if (!ctx.llvmOptions().empty()) {
- unsigned numArgs = ctx.llvmOptions().size();
- auto **args = new const char *[numArgs + 2];
- args[0] = "lld (LLVM option parsing)";
- for (unsigned i = 0; i != numArgs; ++i)
- args[i + 1] = ctx.llvmOptions()[i];
- args[numArgs + 1] = nullptr;
- llvm::cl::ResetAllOptionOccurrences();
- llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
- }
-}
-
-namespace lld {
-namespace mach_o {
-
-bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) {
- // Parse command line options using DarwinLdOptions.td
- DarwinLdOptTable table;
- unsigned missingIndex;
- unsigned missingCount;
- llvm::opt::InputArgList parsedArgs =
- table.ParseArgs(args.slice(1), missingIndex, missingCount);
- if (missingCount) {
- error("missing arg value for '" +
- Twine(parsedArgs.getArgString(missingIndex)) + "' expected " +
- Twine(missingCount) + " argument(s).");
- return false;
- }
-
- for (auto unknownArg : parsedArgs.filtered(OPT_UNKNOWN)) {
- warn("ignoring unknown argument: " +
- Twine(unknownArg->getAsString(parsedArgs)));
- }
-
- errorHandler().verbose = parsedArgs.hasArg(OPT_v);
- errorHandler().errorLimit = args::getInteger(parsedArgs, OPT_error_limit, 20);
-
- // Figure out output kind ( -dylib, -r, -bundle, -preload, or -static )
- llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE;
- bool isStaticExecutable = false;
- if (llvm::opt::Arg *kind = parsedArgs.getLastArg(
- OPT_dylib, OPT_relocatable, OPT_bundle, OPT_static, OPT_preload)) {
- switch (kind->getOption().getID()) {
- case OPT_dylib:
- fileType = llvm::MachO::MH_DYLIB;
- break;
- case OPT_relocatable:
- fileType = llvm::MachO::MH_OBJECT;
- break;
- case OPT_bundle:
- fileType = llvm::MachO::MH_BUNDLE;
- break;
- case OPT_static:
- fileType = llvm::MachO::MH_EXECUTE;
- isStaticExecutable = true;
- break;
- case OPT_preload:
- fileType = llvm::MachO::MH_PRELOAD;
- break;
- }
- }
-
- // Handle -arch xxx
- MachOLinkingContext::Arch arch = MachOLinkingContext::arch_unknown;
- if (llvm::opt::Arg *archStr = parsedArgs.getLastArg(OPT_arch)) {
- arch = MachOLinkingContext::archFromName(archStr->getValue());
- if (arch == MachOLinkingContext::arch_unknown) {
- error("unknown arch named '" + Twine(archStr->getValue()) + "'");
- return false;
- }
- }
- // If no -arch specified, scan input files to find first non-fat .o file.
- if (arch == MachOLinkingContext::arch_unknown) {
- for (auto &inFile : parsedArgs.filtered(OPT_INPUT)) {
- // This is expensive because it opens and maps the file. But that is
- // ok because no -arch is rare.
- if (MachOLinkingContext::isThinObjectFile(inFile->getValue(), arch))
- break;
- }
- if (arch == MachOLinkingContext::arch_unknown &&
- !parsedArgs.getLastArg(OPT_test_file_usage)) {
- // If no -arch and no options at all, print usage message.
- if (parsedArgs.size() == 0) {
- table.printHelp(llvm::outs(),
- (std::string(args[0]) + " [options] file...").c_str(),
- "LLVM Linker", false);
- } else {
- error("-arch not specified and could not be inferred");
- }
- return false;
- }
- }
-
- // Handle -macosx_version_min or -ios_version_min
- MachOLinkingContext::OS os = MachOLinkingContext::OS::unknown;
- uint32_t minOSVersion = 0;
- if (llvm::opt::Arg *minOS =
- parsedArgs.getLastArg(OPT_macosx_version_min, OPT_ios_version_min,
- OPT_ios_simulator_version_min)) {
- switch (minOS->getOption().getID()) {
- case OPT_macosx_version_min:
- os = MachOLinkingContext::OS::macOSX;
- if (MachOLinkingContext::parsePackedVersion(minOS->getValue(),
- minOSVersion)) {
- error("malformed macosx_version_min value");
- return false;
- }
- break;
- case OPT_ios_version_min:
- os = MachOLinkingContext::OS::iOS;
- if (MachOLinkingContext::parsePackedVersion(minOS->getValue(),
- minOSVersion)) {
- error("malformed ios_version_min value");
- return false;
- }
- break;
- case OPT_ios_simulator_version_min:
- os = MachOLinkingContext::OS::iOS_simulator;
- if (MachOLinkingContext::parsePackedVersion(minOS->getValue(),
- minOSVersion)) {
- error("malformed ios_simulator_version_min value");
- return false;
- }
- break;
- }
- } else {
- // No min-os version on command line, check environment variables
- }
-
- // Handle export_dynamic
- // FIXME: Should we warn when this applies to something other than a static
- // executable or dylib? Those are the only cases where this has an effect.
- // Note, this has to come before ctx.configure() so that we get the correct
- // value for _globalsAreDeadStripRoots.
- bool exportDynamicSymbols = parsedArgs.hasArg(OPT_export_dynamic);
-
- // Now that there's enough information parsed in, let the linking context
- // set up default values.
- ctx.configure(fileType, arch, os, minOSVersion, exportDynamicSymbols);
-
- // Handle -e xxx
- if (llvm::opt::Arg *entry = parsedArgs.getLastArg(OPT_entry))
- ctx.setEntrySymbolName(entry->getValue());
-
- // Handle -o xxx
- if (llvm::opt::Arg *outpath = parsedArgs.getLastArg(OPT_output))
- ctx.setOutputPath(outpath->getValue());
- else
- ctx.setOutputPath("a.out");
-
- // Handle -image_base XXX and -seg1addr XXXX
- if (llvm::opt::Arg *imageBase = parsedArgs.getLastArg(OPT_image_base)) {
- uint64_t baseAddress;
- if (parseNumberBase16(imageBase->getValue(), baseAddress)) {
- error("image_base expects a hex number");
- return false;
- } else if (baseAddress < ctx.pageZeroSize()) {
- error("image_base overlaps with __PAGEZERO");
- return false;
- } else if (baseAddress % ctx.pageSize()) {
- error("image_base must be a multiple of page size (0x" +
- llvm::utohexstr(ctx.pageSize()) + ")");
- return false;
- }
-
- ctx.setBaseAddress(baseAddress);
- }
-
- // Handle -dead_strip
- if (parsedArgs.getLastArg(OPT_dead_strip))
- ctx.setDeadStripping(true);
-
- bool globalWholeArchive = false;
- // Handle -all_load
- if (parsedArgs.getLastArg(OPT_all_load))
- globalWholeArchive = true;
-
- // Handle -install_name
- if (llvm::opt::Arg *installName = parsedArgs.getLastArg(OPT_install_name))
- ctx.setInstallName(installName->getValue());
- else
- ctx.setInstallName(ctx.outputPath());
-
- // Handle -mark_dead_strippable_dylib
- if (parsedArgs.getLastArg(OPT_mark_dead_strippable_dylib))
- ctx.setDeadStrippableDylib(true);
-
- // Handle -compatibility_version and -current_version
- if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_compatibility_version)) {
- if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) {
- error("-compatibility_version can only be used with -dylib");
- return false;
- }
- uint32_t parsedVers;
- if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
- error("-compatibility_version value is malformed");
- return false;
- }
- ctx.setCompatibilityVersion(parsedVers);
- }
-
- if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_current_version)) {
- if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) {
- error("-current_version can only be used with -dylib");
- return false;
- }
- uint32_t parsedVers;
- if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
- error("-current_version value is malformed");
- return false;
- }
- ctx.setCurrentVersion(parsedVers);
- }
-
- // Handle -bundle_loader
- if (llvm::opt::Arg *loader = parsedArgs.getLastArg(OPT_bundle_loader))
- ctx.setBundleLoader(loader->getValue());
-
- // Handle -sectalign segname sectname align
- for (auto &alignArg : parsedArgs.filtered(OPT_sectalign)) {
- const char* segName = alignArg->getValue(0);
- const char* sectName = alignArg->getValue(1);
- const char* alignStr = alignArg->getValue(2);
- if ((alignStr[0] == '0') && (alignStr[1] == 'x'))
- alignStr += 2;
- unsigned long long alignValue;
- if (llvm::getAsUnsignedInteger(alignStr, 16, alignValue)) {
- error("-sectalign alignment value '" + Twine(alignStr) +
- "' not a valid number");
- return false;
- }
- uint16_t align = 1 << llvm::countTrailingZeros(alignValue);
- if (!llvm::isPowerOf2_64(alignValue)) {
- std::string Msg;
- llvm::raw_string_ostream OS(Msg);
- OS << "alignment for '-sectalign " << segName << " " << sectName
- << llvm::format(" 0x%llX", alignValue)
- << "' is not a power of two, using " << llvm::format("0x%08X", align);
- OS.flush();
- warn(Msg);
- }
- ctx.addSectionAlignment(segName, sectName, align);
- }
-
- // Handle -mllvm
- for (auto &llvmArg : parsedArgs.filtered(OPT_mllvm)) {
- ctx.appendLLVMOption(llvmArg->getValue());
- }
-
- // Handle -print_atoms
- if (parsedArgs.getLastArg(OPT_print_atoms))
- ctx.setPrintAtoms();
-
- // Handle -t (trace) option.
- if (parsedArgs.getLastArg(OPT_t))
- ctx.setLogInputFiles(true);
-
- // Handle -demangle option.
- if (parsedArgs.getLastArg(OPT_demangle))
- ctx.setDemangleSymbols(true);
-
- // Handle -keep_private_externs
- if (parsedArgs.getLastArg(OPT_keep_private_externs)) {
- ctx.setKeepPrivateExterns(true);
- if (ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
- warn("-keep_private_externs only used in -r mode");
- }
-
- // Handle -dependency_info <path> used by Xcode.
- if (llvm::opt::Arg *depInfo = parsedArgs.getLastArg(OPT_dependency_info))
- if (std::error_code ec = ctx.createDependencyFile(depInfo->getValue()))
- warn(ec.message() + ", processing '-dependency_info " +
- depInfo->getValue());
-
- // In -test_file_usage mode, we'll be given an explicit list of paths that
- // exist. We'll also be expected to print out information about how we located
- // libraries and so on that the user specified, but not to actually do any
- // linking.
- if (parsedArgs.getLastArg(OPT_test_file_usage)) {
- ctx.setTestingFileUsage();
-
- // With paths existing by fiat, linking is not going to end well.
- ctx.setDoNothing(true);
-
- // Only bother looking for an existence override if we're going to use it.
- for (auto existingPath : parsedArgs.filtered(OPT_path_exists)) {
- ctx.addExistingPathForDebug(existingPath->getValue());
- }
- }
-
- // Register possible input file parsers.
- if (!ctx.doNothing()) {
- ctx.registry().addSupportMachOObjects(ctx);
- ctx.registry().addSupportArchives(ctx.logInputFiles());
- ctx.registry().addSupportYamlFiles();
- }
-
- // Now construct the set of library search directories, following ld64's
- // baroque set of accumulated hacks. Mostly, the algorithm constructs
- // { syslibroots } x { libpaths }
- //
- // Unfortunately, there are numerous exceptions:
- // 1. Only absolute paths get modified by syslibroot options.
- // 2. If there is just 1 -syslibroot, system paths not found in it are
- // skipped.
- // 3. If the last -syslibroot is "/", all of them are ignored entirely.
- // 4. If { syslibroots } x path == {}, the original path is kept.
- std::vector<StringRef> sysLibRoots;
- for (auto syslibRoot : parsedArgs.filtered(OPT_syslibroot)) {
- sysLibRoots.push_back(syslibRoot->getValue());
- }
- if (!sysLibRoots.empty()) {
- // Ignore all if last -syslibroot is "/".
- if (sysLibRoots.back() != "/")
- ctx.setSysLibRoots(sysLibRoots);
- }
-
- // Paths specified with -L come first, and are not considered system paths for
- // the case where there is precisely 1 -syslibroot.
- for (auto libPath : parsedArgs.filtered(OPT_L)) {
- ctx.addModifiedSearchDir(libPath->getValue());
- }
-
- // Process -F directories (where to look for frameworks).
- for (auto fwPath : parsedArgs.filtered(OPT_F)) {
- ctx.addFrameworkSearchDir(fwPath->getValue());
- }
-
- // -Z suppresses the standard search paths.
- if (!parsedArgs.hasArg(OPT_Z)) {
- ctx.addModifiedSearchDir("/usr/lib", true);
- ctx.addModifiedSearchDir("/usr/local/lib", true);
- ctx.addFrameworkSearchDir("/Library/Frameworks", true);
- ctx.addFrameworkSearchDir("/System/Library/Frameworks", true);
- }
-
- // Now that we've constructed the final set of search paths, print out those
- // search paths in verbose mode.
- if (errorHandler().verbose) {
- message("Library search paths:");
- for (auto path : ctx.searchDirs()) {
- message(" " + path);
- }
- message("Framework search paths:");
- for (auto path : ctx.frameworkDirs()) {
- message(" " + path);
- }
- }
-
- // Handle -exported_symbols_list <file>
- for (auto expFile : parsedArgs.filtered(OPT_exported_symbols_list)) {
- if (ctx.exportMode() == MachOLinkingContext::ExportMode::unexported) {
- error("-exported_symbols_list cannot be combined with "
- "-unexported_symbol[s_list]");
- return false;
- }
- ctx.setExportMode(MachOLinkingContext::ExportMode::exported);
- if (std::error_code ec = parseExportsList(expFile->getValue(), ctx)) {
- error(ec.message() + ", processing '-exported_symbols_list " +
- expFile->getValue());
- return false;
- }
- }
-
- // Handle -exported_symbol <symbol>
- for (auto symbol : parsedArgs.filtered(OPT_exported_symbol)) {
- if (ctx.exportMode() == MachOLinkingContext::ExportMode::unexported) {
- error("-exported_symbol cannot be combined with "
- "-unexported_symbol[s_list]");
- return false;
- }
- ctx.setExportMode(MachOLinkingContext::ExportMode::exported);
- ctx.addExportSymbol(symbol->getValue());
- }
-
- // Handle -unexported_symbols_list <file>
- for (auto expFile : parsedArgs.filtered(OPT_unexported_symbols_list)) {
- if (ctx.exportMode() == MachOLinkingContext::ExportMode::exported) {
- error("-unexported_symbols_list cannot be combined with "
- "-exported_symbol[s_list]");
- return false;
- }
- ctx.setExportMode(MachOLinkingContext::ExportMode::unexported);
- if (std::error_code ec = parseExportsList(expFile->getValue(), ctx)) {
- error(ec.message() + ", processing '-unexported_symbols_list " +
- expFile->getValue());
- return false;
- }
- }
-
- // Handle -unexported_symbol <symbol>
- for (auto symbol : parsedArgs.filtered(OPT_unexported_symbol)) {
- if (ctx.exportMode() == MachOLinkingContext::ExportMode::exported) {
- error("-unexported_symbol cannot be combined with "
- "-exported_symbol[s_list]");
- return false;
- }
- ctx.setExportMode(MachOLinkingContext::ExportMode::unexported);
- ctx.addExportSymbol(symbol->getValue());
- }
-
- // Handle obosolete -multi_module and -single_module
- if (llvm::opt::Arg *mod =
- parsedArgs.getLastArg(OPT_multi_module, OPT_single_module)) {
- if (mod->getOption().getID() == OPT_multi_module)
- warn("-multi_module is obsolete and being ignored");
- else if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB)
- warn("-single_module being ignored. It is only for use when producing a "
- "dylib");
- }
-
- // Handle obsolete ObjC options: -objc_gc_compaction, -objc_gc, -objc_gc_only
- if (parsedArgs.getLastArg(OPT_objc_gc_compaction)) {
- error("-objc_gc_compaction is not supported");
- return false;
- }
-
- if (parsedArgs.getLastArg(OPT_objc_gc)) {
- error("-objc_gc is not supported");
- return false;
- }
-
- if (parsedArgs.getLastArg(OPT_objc_gc_only)) {
- error("-objc_gc_only is not supported");
- return false;
- }
-
- // Handle -pie or -no_pie
- if (llvm::opt::Arg *pie = parsedArgs.getLastArg(OPT_pie, OPT_no_pie)) {
- switch (ctx.outputMachOType()) {
- case llvm::MachO::MH_EXECUTE:
- switch (ctx.os()) {
- case MachOLinkingContext::OS::macOSX:
- if ((minOSVersion < 0x000A0500) &&
- (pie->getOption().getID() == OPT_pie)) {
- error("-pie can only be used when targeting Mac OS X 10.5 or later");
- return false;
- }
- break;
- case MachOLinkingContext::OS::iOS:
- if ((minOSVersion < 0x00040200) &&
- (pie->getOption().getID() == OPT_pie)) {
- error("-pie can only be used when targeting iOS 4.2 or later");
- return false;
- }
- break;
- case MachOLinkingContext::OS::iOS_simulator:
- if (pie->getOption().getID() == OPT_no_pie) {
- error("iOS simulator programs must be built PIE");
- return false;
- }
- break;
- case MachOLinkingContext::OS::unknown:
- break;
- }
- ctx.setPIE(pie->getOption().getID() == OPT_pie);
- break;
- case llvm::MachO::MH_PRELOAD:
- break;
- case llvm::MachO::MH_DYLIB:
- case llvm::MachO::MH_BUNDLE:
- warn(pie->getSpelling() +
- " being ignored. It is only used when linking main executables");
- break;
- default:
- error(pie->getSpelling() +
- " can only used when linking main executables");
- return false;
- }
- }
-
- // Handle -version_load_command or -no_version_load_command
- {
- bool flagOn = false;
- bool flagOff = false;
- if (auto *arg = parsedArgs.getLastArg(OPT_version_load_command,
- OPT_no_version_load_command)) {
- flagOn = arg->getOption().getID() == OPT_version_load_command;
- flagOff = arg->getOption().getID() == OPT_no_version_load_command;
- }
-
- // default to adding version load command for dynamic code,
- // static code must opt-in
- switch (ctx.outputMachOType()) {
- case llvm::MachO::MH_OBJECT:
- ctx.setGenerateVersionLoadCommand(false);
- break;
- case llvm::MachO::MH_EXECUTE:
- // dynamic executables default to generating a version load command,
- // while static executables only generate it if required.
- if (isStaticExecutable) {
- if (flagOn)
- ctx.setGenerateVersionLoadCommand(true);
- } else {
- if (!flagOff)
- ctx.setGenerateVersionLoadCommand(true);
- }
- break;
- case llvm::MachO::MH_PRELOAD:
- case llvm::MachO::MH_KEXT_BUNDLE:
- if (flagOn)
- ctx.setGenerateVersionLoadCommand(true);
- break;
- case llvm::MachO::MH_DYLINKER:
- case llvm::MachO::MH_DYLIB:
- case llvm::MachO::MH_BUNDLE:
- if (!flagOff)
- ctx.setGenerateVersionLoadCommand(true);
- break;
- case llvm::MachO::MH_FVMLIB:
- case llvm::MachO::MH_DYLDLINK:
- case llvm::MachO::MH_DYLIB_STUB:
- case llvm::MachO::MH_DSYM:
- // We don't generate load commands for these file types, even if
- // forced on.
- break;
- }
- }
-
- // Handle -function_starts or -no_function_starts
- {
- bool flagOn = false;
- bool flagOff = false;
- if (auto *arg = parsedArgs.getLastArg(OPT_function_starts,
- OPT_no_function_starts)) {
- flagOn = arg->getOption().getID() == OPT_function_starts;
- flagOff = arg->getOption().getID() == OPT_no_function_starts;
- }
-
- // default to adding functions start for dynamic code, static code must
- // opt-in
- switch (ctx.outputMachOType()) {
- case llvm::MachO::MH_OBJECT:
- ctx.setGenerateFunctionStartsLoadCommand(false);
- break;
- case llvm::MachO::MH_EXECUTE:
- // dynamic executables default to generating a version load command,
- // while static executables only generate it if required.
- if (isStaticExecutable) {
- if (flagOn)
- ctx.setGenerateFunctionStartsLoadCommand(true);
- } else {
- if (!flagOff)
- ctx.setGenerateFunctionStartsLoadCommand(true);
- }
- break;
- case llvm::MachO::MH_PRELOAD:
- case llvm::MachO::MH_KEXT_BUNDLE:
- if (flagOn)
- ctx.setGenerateFunctionStartsLoadCommand(true);
- break;
- case llvm::MachO::MH_DYLINKER:
- case llvm::MachO::MH_DYLIB:
- case llvm::MachO::MH_BUNDLE:
- if (!flagOff)
- ctx.setGenerateFunctionStartsLoadCommand(true);
- break;
- case llvm::MachO::MH_FVMLIB:
- case llvm::MachO::MH_DYLDLINK:
- case llvm::MachO::MH_DYLIB_STUB:
- case llvm::MachO::MH_DSYM:
- // We don't generate load commands for these file types, even if
- // forced on.
- break;
- }
- }
-
- // Handle -data_in_code_info or -no_data_in_code_info
- {
- bool flagOn = false;
- bool flagOff = false;
- if (auto *arg = parsedArgs.getLastArg(OPT_data_in_code_info,
- OPT_no_data_in_code_info)) {
- flagOn = arg->getOption().getID() == OPT_data_in_code_info;
- flagOff = arg->getOption().getID() == OPT_no_data_in_code_info;
- }
-
- // default to adding data in code for dynamic code, static code must
- // opt-in
- switch (ctx.outputMachOType()) {
- case llvm::MachO::MH_OBJECT:
- if (!flagOff)
- ctx.setGenerateDataInCodeLoadCommand(true);
- break;
- case llvm::MachO::MH_EXECUTE:
- // dynamic executables default to generating a version load command,
- // while static executables only generate it if required.
- if (isStaticExecutable) {
- if (flagOn)
- ctx.setGenerateDataInCodeLoadCommand(true);
- } else {
- if (!flagOff)
- ctx.setGenerateDataInCodeLoadCommand(true);
- }
- break;
- case llvm::MachO::MH_PRELOAD:
- case llvm::MachO::MH_KEXT_BUNDLE:
- if (flagOn)
- ctx.setGenerateDataInCodeLoadCommand(true);
- break;
- case llvm::MachO::MH_DYLINKER:
- case llvm::MachO::MH_DYLIB:
- case llvm::MachO::MH_BUNDLE:
- if (!flagOff)
- ctx.setGenerateDataInCodeLoadCommand(true);
- break;
- case llvm::MachO::MH_FVMLIB:
- case llvm::MachO::MH_DYLDLINK:
- case llvm::MachO::MH_DYLIB_STUB:
- case llvm::MachO::MH_DSYM:
- // We don't generate load commands for these file types, even if
- // forced on.
- break;
- }
- }
-
- // Handle sdk_version
- if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_sdk_version)) {
- uint32_t sdkVersion = 0;
- if (MachOLinkingContext::parsePackedVersion(arg->getValue(),
- sdkVersion)) {
- error("malformed sdkVersion value");
- return false;
- }
- ctx.setSdkVersion(sdkVersion);
- } else if (ctx.generateVersionLoadCommand()) {
- // If we don't have an sdk version, but were going to emit a load command
- // with min_version, then we need to give a warning as we have no sdk
- // version to put in that command.
- // FIXME: We need to decide whether to make this an error.
- warn("-sdk_version is required when emitting min version load command. "
- "Setting sdk version to match provided min version");
- ctx.setSdkVersion(ctx.osMinVersion());
- }
-
- // Handle source_version
- if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_source_version)) {
- uint64_t version = 0;
- if (MachOLinkingContext::parsePackedVersion(arg->getValue(),
- version)) {
- error("malformed source_version value");
- return false;
- }
- ctx.setSourceVersion(version);
- }
-
- // Handle stack_size
- if (llvm::opt::Arg *stackSize = parsedArgs.getLastArg(OPT_stack_size)) {
- uint64_t stackSizeVal;
- if (parseNumberBase16(stackSize->getValue(), stackSizeVal)) {
- error("stack_size expects a hex number");
- return false;
- }
- if ((stackSizeVal % ctx.pageSize()) != 0) {
- error("stack_size must be a multiple of page size (0x" +
- llvm::utohexstr(ctx.pageSize()) + ")");
- return false;
- }
-
- ctx.setStackSize(stackSizeVal);
- }
-
- // Handle debug info handling options: -S
- if (parsedArgs.hasArg(OPT_S))
- ctx.setDebugInfoMode(MachOLinkingContext::DebugInfoMode::noDebugMap);
-
- // Handle -order_file <file>
- for (auto orderFile : parsedArgs.filtered(OPT_order_file)) {
- if (std::error_code ec = parseOrderFile(orderFile->getValue(), ctx)) {
- error(ec.message() + ", processing '-order_file " + orderFile->getValue()
- + "'");
- return false;
- }
- }
-
- // Handle -flat_namespace.
- if (llvm::opt::Arg *ns =
- parsedArgs.getLastArg(OPT_flat_namespace, OPT_twolevel_namespace)) {
- if (ns->getOption().getID() == OPT_flat_namespace)
- ctx.setUseFlatNamespace(true);
- }
-
- // Handle -undefined
- if (llvm::opt::Arg *undef = parsedArgs.getLastArg(OPT_undefined)) {
- MachOLinkingContext::UndefinedMode UndefMode;
- if (StringRef(undef->getValue()).equals("error"))
- UndefMode = MachOLinkingContext::UndefinedMode::error;
- else if (StringRef(undef->getValue()).equals("warning"))
- UndefMode = MachOLinkingContext::UndefinedMode::warning;
- else if (StringRef(undef->getValue()).equals("suppress"))
- UndefMode = MachOLinkingContext::UndefinedMode::suppress;
- else if (StringRef(undef->getValue()).equals("dynamic_lookup"))
- UndefMode = MachOLinkingContext::UndefinedMode::dynamicLookup;
- else {
- error("invalid option to -undefined [ warning | error | suppress | "
- "dynamic_lookup ]");
- return false;
- }
-
- if (ctx.useFlatNamespace()) {
- // If we're using -flat_namespace then 'warning', 'suppress' and
- // 'dynamic_lookup' are all equivalent, so map them to 'suppress'.
- if (UndefMode != MachOLinkingContext::UndefinedMode::error)
- UndefMode = MachOLinkingContext::UndefinedMode::suppress;
- } else {
- // If we're using -twolevel_namespace then 'warning' and 'suppress' are
- // illegal. Emit a diagnostic if they've been (mis)used.
- if (UndefMode == MachOLinkingContext::UndefinedMode::warning ||
- UndefMode == MachOLinkingContext::UndefinedMode::suppress) {
- error("can't use -undefined warning or suppress with "
- "-twolevel_namespace");
- return false;
- }
- }
-
- ctx.setUndefinedMode(UndefMode);
- }
-
- // Handle -no_objc_category_merging.
- if (parsedArgs.getLastArg(OPT_no_objc_category_merging))
- ctx.setMergeObjCCategories(false);
-
- // Handle -rpath <path>
- if (parsedArgs.hasArg(OPT_rpath)) {
- switch (ctx.outputMachOType()) {
- case llvm::MachO::MH_EXECUTE:
- case llvm::MachO::MH_DYLIB:
- case llvm::MachO::MH_BUNDLE:
- if (!ctx.minOS("10.5", "2.0")) {
- if (ctx.os() == MachOLinkingContext::OS::macOSX)
- error("-rpath can only be used when targeting OS X 10.5 or later");
- else
- error("-rpath can only be used when targeting iOS 2.0 or later");
- return false;
- }
- break;
- default:
- error("-rpath can only be used when creating a dynamic final linked "
- "image");
- return false;
- }
-
- for (auto rPath : parsedArgs.filtered(OPT_rpath)) {
- ctx.addRpath(rPath->getValue());
- }
- }
-
- // Parse the LLVM options before we process files in case the file handling
- // makes use of things like LLVM_DEBUG().
- parseLLVMOptions(ctx);
-
- // Handle input files and sectcreate.
- for (auto &arg : parsedArgs) {
- bool upward;
- llvm::Optional<StringRef> resolvedPath;
- switch (arg->getOption().getID()) {
- default:
- continue;
- case OPT_INPUT:
- addFile(arg->getValue(), ctx, globalWholeArchive, false);
- break;
- case OPT_upward_library:
- addFile(arg->getValue(), ctx, false, true);
- break;
- case OPT_force_load:
- addFile(arg->getValue(), ctx, true, false);
- break;
- case OPT_l:
- case OPT_upward_l:
- upward = (arg->getOption().getID() == OPT_upward_l);
- resolvedPath = ctx.searchLibrary(arg->getValue());
- if (!resolvedPath) {
- error("Unable to find library for " + arg->getSpelling() +
- arg->getValue());
- return false;
- } else if (ctx.testingFileUsage()) {
- message(Twine("Found ") + (upward ? "upward " : " ") + "library " +
- canonicalizePath(resolvedPath.getValue()));
- }
- addFile(resolvedPath.getValue(), ctx, globalWholeArchive, upward);
- break;
- case OPT_framework:
- case OPT_upward_framework:
- upward = (arg->getOption().getID() == OPT_upward_framework);
- resolvedPath = ctx.findPathForFramework(arg->getValue());
- if (!resolvedPath) {
- error("Unable to find framework for " + arg->getSpelling() + " " +
- arg->getValue());
- return false;
- } else if (ctx.testingFileUsage()) {
- message(Twine("Found ") + (upward ? "upward " : " ") + "framework " +
- canonicalizePath(resolvedPath.getValue()));
- }
- addFile(resolvedPath.getValue(), ctx, globalWholeArchive, upward);
- break;
- case OPT_filelist:
- if (auto ec = loadFileList(arg->getValue(), ctx, globalWholeArchive)) {
- handleAllErrors(std::move(ec), [&](const llvm::ErrorInfoBase &EI) {
- error(EI.message() + ", processing '-filelist " + arg->getValue());
- });
- return false;
- }
- break;
- case OPT_sectcreate: {
- const char* seg = arg->getValue(0);
- const char* sect = arg->getValue(1);
- const char* fileName = arg->getValue(2);
-
- ErrorOr<std::unique_ptr<MemoryBuffer>> contentOrErr =
- MemoryBuffer::getFile(fileName);
-
- if (!contentOrErr) {
- error("can't open -sectcreate file " + Twine(fileName));
- return false;
- }
-
- ctx.addSectCreateSection(seg, sect, std::move(*contentOrErr));
- }
- break;
- }
- }
-
- if (ctx.getNodes().empty()) {
- error("No input files");
- return false;
- }
-
- // Validate the combination of options used.
- return ctx.validate();
-}
-
-static void createFiles(MachOLinkingContext &ctx, bool Implicit) {
- std::vector<std::unique_ptr<File>> Files;
- if (Implicit)
- ctx.createImplicitFiles(Files);
- else
- ctx.createInternalFiles(Files);
- for (auto i = Files.rbegin(), e = Files.rend(); i != e; ++i) {
- auto &members = ctx.getNodes();
- members.insert(members.begin(), std::make_unique<FileNode>(std::move(*i)));
- }
-}
-
-/// This is where the link is actually performed.
-bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,
- raw_ostream &StdoutOS, raw_ostream &StderrOS) {
- lld::stdoutOS = &StdoutOS;
- lld::stderrOS = &StderrOS;
-
- errorHandler().logName = args::getFilenameWithoutExe(args[0]);
- errorHandler().errorLimitExceededMsg =
- "too many errors emitted, stopping now (use "
- "'-error-limit 0' to see all errors)";
- errorHandler().exitEarly = CanExitEarly;
- StderrOS.enable_colors(StderrOS.has_colors());
-
- MachOLinkingContext ctx;
- if (!parse(args, ctx))
- return false;
- if (ctx.doNothing())
- return true;
- if (ctx.getNodes().empty())
- return false;
-
- for (std::unique_ptr<Node> &ie : ctx.getNodes())
- if (FileNode *node = dyn_cast<FileNode>(ie.get()))
- node->getFile()->parse();
-
- createFiles(ctx, false /* Implicit */);
-
- // Give target a chance to add files
- createFiles(ctx, true /* Implicit */);
-
- // Give target a chance to postprocess input files.
- // Mach-O uses this chance to move all object files before library files.
- ctx.finalizeInputFiles();
-
- // Do core linking.
- ScopedTask resolveTask(getDefaultDomain(), "Resolve");
- Resolver resolver(ctx);
- if (!resolver.resolve())
- return false;
- SimpleFile *merged = nullptr;
- {
- std::unique_ptr<SimpleFile> mergedFile = resolver.resultFile();
- merged = mergedFile.get();
- auto &members = ctx.getNodes();
- members.insert(members.begin(),
- std::make_unique<FileNode>(std::move(mergedFile)));
- }
- resolveTask.end();
-
- // Run passes on linked atoms.
- ScopedTask passTask(getDefaultDomain(), "Passes");
- PassManager pm;
- ctx.addPasses(pm);
- if (auto ec = pm.runOnFile(*merged)) {
- // FIXME: This should be passed to logAllUnhandledErrors but it needs
- // to be passed a Twine instead of a string.
- lld::errs() << "Failed to run passes on file '" << ctx.outputPath()
- << "': ";
- logAllUnhandledErrors(std::move(ec), lld::errs(), std::string());
- return false;
- }
-
- passTask.end();
-
- // Give linked atoms to Writer to generate output file.
- ScopedTask writeTask(getDefaultDomain(), "Write");
- if (auto ec = ctx.writeFile(*merged)) {
- // FIXME: This should be passed to logAllUnhandledErrors but it needs
- // to be passed a Twine instead of a string.
- lld::errs() << "Failed to write file '" << ctx.outputPath() << "': ";
- logAllUnhandledErrors(std::move(ec), lld::errs(), std::string());
- return false;
- }
-
- // Call exit() if we can to avoid calling destructors.
- if (CanExitEarly)
- exitLld(errorCount() ? 1 : 0);
-
-
- return true;
-}
-
-} // end namespace mach_o
-} // end namespace lld
+++ /dev/null
-include "llvm/Option/OptParser.td"
-
-
-// output kinds
-def grp_kind : OptionGroup<"outs">, HelpText<"OUTPUT KIND">;
-def relocatable : Flag<["-"], "r">,
- HelpText<"Create relocatable object file">, Group<grp_kind>;
-def static : Flag<["-"], "static">,
- HelpText<"Create static executable">, Group<grp_kind>;
-def dynamic : Flag<["-"], "dynamic">,
- HelpText<"Create dynamic executable (default)">,Group<grp_kind>;
-def dylib : Flag<["-"], "dylib">,
- HelpText<"Create dynamic library">, Group<grp_kind>;
-def bundle : Flag<["-"], "bundle">,
- HelpText<"Create dynamic bundle">, Group<grp_kind>;
-def execute : Flag<["-"], "execute">,
- HelpText<"Create main executable (default)">, Group<grp_kind>;
-def preload : Flag<["-"], "preload">,
- HelpText<"Create binary for use with embedded systems">, Group<grp_kind>;
-
-// optimizations
-def grp_opts : OptionGroup<"opts">, HelpText<"OPTIMIZATIONS">;
-def dead_strip : Flag<["-"], "dead_strip">,
- HelpText<"Remove unreference code and data">, Group<grp_opts>;
-def macosx_version_min : Separate<["-"], "macosx_version_min">,
- MetaVarName<"<version>">,
- HelpText<"Minimum Mac OS X version">, Group<grp_opts>;
-def ios_version_min : Separate<["-"], "ios_version_min">,
- MetaVarName<"<version>">,
- HelpText<"Minimum iOS version">, Group<grp_opts>;
-def iphoneos_version_min : Separate<["-"], "iphoneos_version_min">,
- Alias<ios_version_min>;
-def ios_simulator_version_min : Separate<["-"], "ios_simulator_version_min">,
- MetaVarName<"<version>">,
- HelpText<"Minimum iOS simulator version">, Group<grp_opts>;
-def sdk_version : Separate<["-"], "sdk_version">,
- MetaVarName<"<version>">,
- HelpText<"SDK version">, Group<grp_opts>;
-def source_version : Separate<["-"], "source_version">,
- MetaVarName<"<version>">,
- HelpText<"Source version">, Group<grp_opts>;
-def version_load_command : Flag<["-"], "version_load_command">,
- HelpText<"Force generation of a version load command">, Group<grp_opts>;
-def no_version_load_command : Flag<["-"], "no_version_load_command">,
- HelpText<"Disable generation of a version load command">, Group<grp_opts>;
-def function_starts : Flag<["-"], "function_starts">,
- HelpText<"Force generation of a function starts load command">,
- Group<grp_opts>;
-def no_function_starts : Flag<["-"], "no_function_starts">,
- HelpText<"Disable generation of a function starts load command">,
- Group<grp_opts>;
-def data_in_code_info : Flag<["-"], "data_in_code_info">,
- HelpText<"Force generation of a data in code load command">,
- Group<grp_opts>;
-def no_data_in_code_info : Flag<["-"], "no_data_in_code_info">,
- HelpText<"Disable generation of a data in code load command">,
- Group<grp_opts>;
-def mllvm : Separate<["-"], "mllvm">,
- MetaVarName<"<option>">,
- HelpText<"Options to pass to LLVM during LTO">, Group<grp_opts>;
-def exported_symbols_list : Separate<["-"], "exported_symbols_list">,
- MetaVarName<"<file-path>">,
- HelpText<"Restricts which symbols will be exported">, Group<grp_opts>;
-def exported_symbol : Separate<["-"], "exported_symbol">,
- MetaVarName<"<symbol>">,
- HelpText<"Restricts which symbols will be exported">, Group<grp_opts>;
-def unexported_symbols_list : Separate<["-"], "unexported_symbols_list">,
- MetaVarName<"<file-path>">,
- HelpText<"Lists symbols that should not be exported">, Group<grp_opts>;
-def unexported_symbol : Separate<["-"], "unexported_symbol">,
- MetaVarName<"<symbol>">,
- HelpText<"A symbol which should not be exported">, Group<grp_opts>;
-def keep_private_externs : Flag<["-"], "keep_private_externs">,
- HelpText<"Private extern (hidden) symbols should not be transformed "
- "into local symbols">, Group<grp_opts>;
-def order_file : Separate<["-"], "order_file">,
- MetaVarName<"<file-path>">,
- HelpText<"re-order and move specified symbols to start of their section">,
- Group<grp_opts>;
-def flat_namespace : Flag<["-"], "flat_namespace">,
- HelpText<"Resolves symbols in any (transitively) linked dynamic libraries. "
- "Source libraries are not recorded: dyld will re-search all "
- "images at runtime and use the first definition found.">,
- Group<grp_opts>;
-def twolevel_namespace : Flag<["-"], "twolevel_namespace">,
- HelpText<"Resolves symbols in listed libraries only. Source libraries are "
- "recorded in the symbol table.">,
- Group<grp_opts>;
-def undefined : Separate<["-"], "undefined">,
- MetaVarName<"<undefined>">,
- HelpText<"Determines how undefined symbols are handled.">,
- Group<grp_opts>;
-def no_objc_category_merging : Flag<["-"], "no_objc_category_merging">,
- HelpText<"Disables the optimisation which merges Objective-C categories "
- "on a class in to the class itself.">,
- Group<grp_opts>;
-
-// main executable options
-def grp_main : OptionGroup<"opts">, HelpText<"MAIN EXECUTABLE OPTIONS">;
-def entry : Separate<["-"], "e">,
- MetaVarName<"<entry-name>">,
- HelpText<"entry symbol name">,Group<grp_main>;
-def pie : Flag<["-"], "pie">,
- HelpText<"Create Position Independent Executable (for ASLR)">,
- Group<grp_main>;
-def no_pie : Flag<["-"], "no_pie">,
- HelpText<"Do not create Position Independent Executable">,
- Group<grp_main>;
-def stack_size : Separate<["-"], "stack_size">,
- HelpText<"Specifies the maximum stack size for the main thread in a program. "
- "Must be a page-size multiple. (default=8Mb)">,
- Group<grp_main>;
-def export_dynamic : Flag<["-"], "export_dynamic">,
- HelpText<"Preserves all global symbols in main executables during LTO">,
- Group<grp_main>;
-
-// dylib executable options
-def grp_dylib : OptionGroup<"opts">, HelpText<"DYLIB EXECUTABLE OPTIONS">;
-def install_name : Separate<["-"], "install_name">,
- MetaVarName<"<path>">,
- HelpText<"The dylib's install name">, Group<grp_dylib>;
-def mark_dead_strippable_dylib : Flag<["-"], "mark_dead_strippable_dylib">,
- HelpText<"Marks the dylib as having no side effects during initialization">,
- Group<grp_dylib>;
-def compatibility_version : Separate<["-"], "compatibility_version">,
- MetaVarName<"<version>">,
- HelpText<"The dylib's compatibility version">, Group<grp_dylib>;
-def current_version : Separate<["-"], "current_version">,
- MetaVarName<"<version>">,
- HelpText<"The dylib's current version">, Group<grp_dylib>;
-
-// dylib executable options - compatibility aliases
-def dylib_install_name : Separate<["-"], "dylib_install_name">,
- Alias<install_name>;
-def dylib_compatibility_version : Separate<["-"], "dylib_compatibility_version">,
- MetaVarName<"<version>">, Alias<compatibility_version>;
-def dylib_current_version : Separate<["-"], "dylib_current_version">,
- MetaVarName<"<version>">, Alias<current_version>;
-
-// bundle executable options
-def grp_bundle : OptionGroup<"opts">, HelpText<"BUNDLE EXECUTABLE OPTIONS">;
-def bundle_loader : Separate<["-"], "bundle_loader">,
- MetaVarName<"<path>">,
- HelpText<"The executable that will be loading this Mach-O bundle">,
- Group<grp_bundle>;
-
-// library options
-def grp_libs : OptionGroup<"libs">, HelpText<"LIBRARY OPTIONS">;
-def L : JoinedOrSeparate<["-"], "L">,
- MetaVarName<"<dir>">,
- HelpText<"Add directory to library search path">, Group<grp_libs>;
-def F : JoinedOrSeparate<["-"], "F">,
- MetaVarName<"<dir>">,
- HelpText<"Add directory to framework search path">, Group<grp_libs>;
-def Z : Flag<["-"], "Z">,
- HelpText<"Do not search standard directories for libraries or frameworks">;
-def all_load : Flag<["-"], "all_load">,
- HelpText<"Forces all members of all static libraries to be loaded">,
- Group<grp_libs>;
-def force_load : Separate<["-"], "force_load">,
- MetaVarName<"<library-path>">,
- HelpText<"Forces all members of specified static libraries to be loaded">,
- Group<grp_libs>;
-def syslibroot : Separate<["-"], "syslibroot">, MetaVarName<"<dir>">,
- HelpText<"Add path to SDK to all absolute library search paths">,
- Group<grp_libs>;
-
-// Input options
-def l : Joined<["-"], "l">,
- MetaVarName<"<libname>">,
- HelpText<"Base name of library searched for in -L directories">;
-def upward_l : Joined<["-"], "upward-l">,
- MetaVarName<"<libname>">,
- HelpText<"Base name of upward library searched for in -L directories">;
-def framework : Separate<["-"], "framework">,
- MetaVarName<"<name>">,
- HelpText<"Base name of framework searched for in -F directories">;
-def upward_framework : Separate<["-"], "upward_framework">,
- MetaVarName<"<name>">,
- HelpText<"Base name of upward framework searched for in -F directories">;
-def upward_library : Separate<["-"], "upward_library">,
- MetaVarName<"<path>">,
- HelpText<"path to upward dylib to link with">;
-def filelist : Separate<["-"], "filelist">,
- MetaVarName<"<path>">,
- HelpText<"file containing paths to input files">;
-
-
-// test case options
-def print_atoms : Flag<["-"], "print_atoms">,
- HelpText<"Emit output as yaml atoms">;
-def test_file_usage : Flag<["-"], "test_file_usage">,
- HelpText<"Only files specified by -file_exists are considered to exist. "
- "Print which files would be used">;
-def path_exists : Separate<["-"], "path_exists">,
- MetaVarName<"<path>">,
- HelpText<"Used with -test_file_usage to declare a path">;
-
-
-// general options
-def output : Separate<["-"], "o">,
- MetaVarName<"<path>">,
- HelpText<"Output file path">;
-def arch : Separate<["-"], "arch">,
- MetaVarName<"<arch-name>">,
- HelpText<"Architecture to link">;
-def sectalign : MultiArg<["-"], "sectalign", 3>,
- MetaVarName<"<segname> <sectname> <alignment>">,
- HelpText<"Alignment for segment/section">;
-def sectcreate : MultiArg<["-"], "sectcreate", 3>,
- MetaVarName<"<segname> <sectname> <file>">,
- HelpText<"Create section <segname>/<sectname> from contents of <file>">;
-def image_base : Separate<["-"], "image_base">;
-def seg1addr : Separate<["-"], "seg1addr">, Alias<image_base>;
-def demangle : Flag<["-"], "demangle">,
- HelpText<"Demangles symbol names in errors and warnings">;
-def dependency_info : Separate<["-"], "dependency_info">,
- MetaVarName<"<file>">,
- HelpText<"Write binary list of files used during link">;
-def S : Flag<["-"], "S">,
- HelpText<"Remove debug information (STABS or DWARF) from the output file">;
-def rpath : Separate<["-"], "rpath">,
- MetaVarName<"<path>">,
- HelpText<"Add path to the runpath search path list for image being created">;
-
-def t : Flag<["-"], "t">,
- HelpText<"Print the names of the input files as ld processes them">;
-def v : Flag<["-"], "v">,
- HelpText<"Print linker information">;
-def error_limit : Separate<["-", "--"], "error-limit">,
- MetaVarName<"<number>">,
- HelpText<"Maximum number of errors to emit before stopping (0 = no limit)">;
-
-// Ignored options
-def lto_library : Separate<["-"], "lto_library">,
- MetaVarName<"<path>">,
- HelpText<"Ignored for compatibility with other linkers">;
-
-// Obsolete options
-def grp_obsolete : OptionGroup<"obsolete">, HelpText<"OBSOLETE OPTIONS">;
-def single_module : Flag<["-"], "single_module">,
- HelpText<"Default for dylibs">, Group<grp_obsolete>;
-def multi_module : Flag<["-"], "multi_module">,
- HelpText<"Unsupported way to build dylibs">, Group<grp_obsolete>;
-def objc_gc_compaction : Flag<["-"], "objc_gc_compaction">,
- HelpText<"Unsupported ObjC GC option">, Group<grp_obsolete>;
-def objc_gc : Flag<["-"], "objc_gc">,
- HelpText<"Unsupported ObjC GC option">, Group<grp_obsolete>;
-def objc_gc_only : Flag<["-"], "objc_gc_only">,
- HelpText<"Unsupported ObjC GC option">, Group<grp_obsolete>;
+++ /dev/null
-add_subdirectory(MachO)
-add_subdirectory(YAML)
-
-if (MSVC)
- add_definitions(-wd4062) # Suppress 'warning C4062: Enumerator has no associated handler in a switch statement.'
-endif()
-
-add_lld_library(lldReaderWriter
- FileArchive.cpp
-
- ADDITIONAL_HEADER_DIRS
- ${LLD_INCLUDE_DIR}/lld/ReaderWriter
-
- LINK_COMPONENTS
- Object
- Support
-
- LINK_LIBS
- lldCore
- )
+++ /dev/null
-//===- lib/ReaderWriter/FileArchive.cpp -----------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Common/LLVM.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reader.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/Object/Archive.h"
-#include "llvm/Object/Error.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
-#include <set>
-#include <string>
-#include <system_error>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-using llvm::object::Archive;
-using llvm::file_magic;
-using llvm::identify_magic;
-
-namespace lld {
-
-namespace {
-
-/// The FileArchive class represents an Archive Library file
-class FileArchive : public lld::ArchiveLibraryFile {
-public:
- FileArchive(std::unique_ptr<MemoryBuffer> mb, const Registry ®,
- StringRef path, bool logLoading)
- : ArchiveLibraryFile(path), _mb(std::shared_ptr<MemoryBuffer>(mb.release())),
- _registry(reg), _logLoading(logLoading) {}
-
- /// Check if any member of the archive contains an Atom with the
- /// specified name and return the File object for that member, or nullptr.
- File *find(StringRef name) override {
- auto member = _symbolMemberMap.find(name);
- if (member == _symbolMemberMap.end())
- return nullptr;
- Archive::Child c = member->second;
-
- // Don't return a member already returned
- Expected<StringRef> buf = c.getBuffer();
- if (!buf) {
- // TODO: Actually report errors helpfully.
- consumeError(buf.takeError());
- return nullptr;
- }
- const char *memberStart = buf->data();
- if (_membersInstantiated.count(memberStart))
- return nullptr;
- _membersInstantiated.insert(memberStart);
-
- std::unique_ptr<File> result;
- if (instantiateMember(c, result))
- return nullptr;
-
- File *file = result.get();
- _filesReturned.push_back(std::move(result));
-
- // Give up the file pointer. It was stored and will be destroyed with destruction of FileArchive
- return file;
- }
-
- /// parse each member
- std::error_code
- parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
- if (std::error_code ec = parse())
- return ec;
- llvm::Error err = llvm::Error::success();
- for (auto mf = _archive->child_begin(err), me = _archive->child_end();
- mf != me; ++mf) {
- std::unique_ptr<File> file;
- if (std::error_code ec = instantiateMember(*mf, file)) {
- // err is Success (or we wouldn't be in the loop body) but we can't
- // return without testing or consuming it.
- consumeError(std::move(err));
- return ec;
- }
- result.push_back(std::move(file));
- }
- if (err)
- return errorToErrorCode(std::move(err));
- return std::error_code();
- }
-
- const AtomRange<DefinedAtom> defined() const override {
- return _noDefinedAtoms;
- }
-
- const AtomRange<UndefinedAtom> undefined() const override {
- return _noUndefinedAtoms;
- }
-
- const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
- return _noSharedLibraryAtoms;
- }
-
- const AtomRange<AbsoluteAtom> absolute() const override {
- return _noAbsoluteAtoms;
- }
-
- void clearAtoms() override {
- _noDefinedAtoms.clear();
- _noUndefinedAtoms.clear();
- _noSharedLibraryAtoms.clear();
- _noAbsoluteAtoms.clear();
- }
-
-protected:
- std::error_code doParse() override {
- // Make Archive object which will be owned by FileArchive object.
- llvm::Error Err = llvm::Error::success();
- _archive.reset(new Archive(_mb->getMemBufferRef(), Err));
- if (Err)
- return errorToErrorCode(std::move(Err));
- std::error_code ec;
- if ((ec = buildTableOfContents()))
- return ec;
- return std::error_code();
- }
-
-private:
- std::error_code instantiateMember(Archive::Child member,
- std::unique_ptr<File> &result) const {
- Expected<llvm::MemoryBufferRef> mbOrErr = member.getMemoryBufferRef();
- if (!mbOrErr)
- return errorToErrorCode(mbOrErr.takeError());
- llvm::MemoryBufferRef mb = mbOrErr.get();
- std::string memberPath = (_archive->getFileName() + "("
- + mb.getBufferIdentifier() + ")").str();
-
- if (_logLoading)
- llvm::errs() << memberPath << "\n";
-
- std::unique_ptr<MemoryBuffer> memberMB(MemoryBuffer::getMemBuffer(
- mb.getBuffer(), mb.getBufferIdentifier(), false));
-
- ErrorOr<std::unique_ptr<File>> fileOrErr =
- _registry.loadFile(std::move(memberMB));
- if (std::error_code ec = fileOrErr.getError())
- return ec;
- result = std::move(fileOrErr.get());
- if (std::error_code ec = result->parse())
- return ec;
- result->setArchivePath(_archive->getFileName());
-
- // The memory buffer is co-owned by the archive file and the children,
- // so that the bufffer is deallocated when all the members are destructed.
- result->setSharedMemoryBuffer(_mb);
- return std::error_code();
- }
-
- std::error_code buildTableOfContents() {
- DEBUG_WITH_TYPE("FileArchive", llvm::dbgs()
- << "Table of contents for archive '"
- << _archive->getFileName() << "':\n");
- for (const Archive::Symbol &sym : _archive->symbols()) {
- StringRef name = sym.getName();
- Expected<Archive::Child> memberOrErr = sym.getMember();
- if (!memberOrErr)
- return errorToErrorCode(memberOrErr.takeError());
- Archive::Child member = memberOrErr.get();
- DEBUG_WITH_TYPE("FileArchive",
- llvm::dbgs()
- << llvm::format("0x%08llX ",
- member.getBuffer()->data())
- << "'" << name << "'\n");
- _symbolMemberMap.insert(std::make_pair(name, member));
- }
- return std::error_code();
- }
-
- typedef std::unordered_map<StringRef, Archive::Child> MemberMap;
- typedef std::set<const char *> InstantiatedSet;
-
- std::shared_ptr<MemoryBuffer> _mb;
- const Registry &_registry;
- std::unique_ptr<Archive> _archive;
- MemberMap _symbolMemberMap;
- InstantiatedSet _membersInstantiated;
- bool _logLoading;
- std::vector<std::unique_ptr<MemoryBuffer>> _memberBuffers;
- std::vector<std::unique_ptr<File>> _filesReturned;
-};
-
-class ArchiveReader : public Reader {
-public:
- ArchiveReader(bool logLoading) : _logLoading(logLoading) {}
-
- bool canParse(file_magic magic, MemoryBufferRef) const override {
- return magic == file_magic::archive;
- }
-
- ErrorOr<std::unique_ptr<File>> loadFile(std::unique_ptr<MemoryBuffer> mb,
- const Registry ®) const override {
- StringRef path = mb->getBufferIdentifier();
- std::unique_ptr<File> ret =
- std::make_unique<FileArchive>(std::move(mb), reg, path, _logLoading);
- return std::move(ret);
- }
-
-private:
- bool _logLoading;
-};
-
-} // anonymous namespace
-
-void Registry::addSupportArchives(bool logLoading) {
- add(std::unique_ptr<Reader>(new ArchiveReader(logLoading)));
-}
-
-} // namespace lld
+++ /dev/null
-//===- lib/FileFormat/MachO/ArchHandler.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-
-ArchHandler::ArchHandler() {
-}
-
-ArchHandler::~ArchHandler() {
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create(
- MachOLinkingContext::Arch arch) {
- switch (arch) {
- case MachOLinkingContext::arch_x86_64:
- return create_x86_64();
- case MachOLinkingContext::arch_x86:
- return create_x86();
- case MachOLinkingContext::arch_armv6:
- case MachOLinkingContext::arch_armv7:
- case MachOLinkingContext::arch_armv7s:
- return create_arm();
- case MachOLinkingContext::arch_arm64:
- return create_arm64();
- default:
- llvm_unreachable("Unknown arch");
- }
-}
-
-
-bool ArchHandler::isLazyPointer(const Reference &ref) {
- // A lazy bind entry is needed for a lazy pointer.
- const StubInfo &info = stubInfo();
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return false;
- if (ref.kindArch() != info.lazyPointerReferenceToFinal.arch)
- return false;
- return (ref.kindValue() == info.lazyPointerReferenceToFinal.kind);
-}
-
-
-ArchHandler::RelocPattern ArchHandler::relocPattern(const Relocation &reloc) {
- assert((reloc.type & 0xFFF0) == 0);
- uint16_t result = reloc.type;
- if (reloc.scattered)
- result |= rScattered;
- if (reloc.pcRel)
- result |= rPcRel;
- if (reloc.isExtern)
- result |= rExtern;
- switch(reloc.length) {
- case 0:
- break;
- case 1:
- result |= rLength2;
- break;
- case 2:
- result |= rLength4;
- break;
- case 3:
- result |= rLength8;
- break;
- default:
- llvm_unreachable("bad r_length");
- }
- return result;
-}
-
-normalized::Relocation
-ArchHandler::relocFromPattern(ArchHandler::RelocPattern pattern) {
- normalized::Relocation result;
- result.offset = 0;
- result.scattered = (pattern & rScattered);
- result.type = (RelocationInfoType)(pattern & 0xF);
- result.pcRel = (pattern & rPcRel);
- result.isExtern = (pattern & rExtern);
- result.value = 0;
- result.symbol = 0;
- switch (pattern & 0x300) {
- case rLength1:
- result.length = 0;
- break;
- case rLength2:
- result.length = 1;
- break;
- case rLength4:
- result.length = 2;
- break;
- case rLength8:
- result.length = 3;
- break;
- }
- return result;
-}
-
-void ArchHandler::appendReloc(normalized::Relocations &relocs, uint32_t offset,
- uint32_t symbol, uint32_t value,
- RelocPattern pattern) {
- normalized::Relocation reloc = relocFromPattern(pattern);
- reloc.offset = offset;
- reloc.symbol = symbol;
- reloc.value = value;
- relocs.push_back(reloc);
-}
-
-
-int16_t ArchHandler::readS16(const uint8_t *addr, bool isBig) {
- return read16(addr, isBig);
-}
-
-int32_t ArchHandler::readS32(const uint8_t *addr, bool isBig) {
- return read32(addr, isBig);
-}
-
-uint32_t ArchHandler::readU32(const uint8_t *addr, bool isBig) {
- return read32(addr, isBig);
-}
-
- int64_t ArchHandler::readS64(const uint8_t *addr, bool isBig) {
- return read64(addr, isBig);
-}
-
-bool ArchHandler::isDwarfCIE(bool isBig, const DefinedAtom *atom) {
- assert(atom->contentType() == DefinedAtom::typeCFI);
- if (atom->rawContent().size() < sizeof(uint32_t))
- return false;
- uint32_t size = read32(atom->rawContent().data(), isBig);
-
- uint32_t idOffset = sizeof(uint32_t);
- if (size == 0xffffffffU)
- idOffset += sizeof(uint64_t);
-
- return read32(atom->rawContent().data() + idOffset, isBig) == 0;
-}
-
-const Atom *ArchHandler::fdeTargetFunction(const DefinedAtom *fde) {
- for (auto ref : *fde) {
- if (ref->kindNamespace() == Reference::KindNamespace::mach_o &&
- ref->kindValue() == unwindRefToFunctionKind()) {
- assert(ref->kindArch() == kindArch() && "unexpected Reference arch");
- return ref->target();
- }
- }
-
- return nullptr;
-}
-
-} // namespace mach_o
-} // namespace lld
-
-
-
+++ /dev/null
-//===- lib/FileFormat/MachO/ArchHandler.h ---------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
-#define LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
-
-#include "Atoms.h"
-#include "File.h"
-#include "MachONormalizedFile.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/Triple.h"
-
-namespace lld {
-namespace mach_o {
-
-///
-/// The ArchHandler class handles all architecture specific aspects of
-/// mach-o linking.
-///
-class ArchHandler {
-public:
- virtual ~ArchHandler();
-
- /// There is no public interface to subclasses of ArchHandler, so this
- /// is the only way to instantiate an ArchHandler.
- static std::unique_ptr<ArchHandler> create(MachOLinkingContext::Arch arch);
-
- /// Get (arch specific) kind strings used by Registry.
- virtual const Registry::KindStrings *kindStrings() = 0;
-
- /// Convert mach-o Arch to Reference::KindArch.
- virtual Reference::KindArch kindArch() = 0;
-
- /// Used by StubPass to update References to shared library functions
- /// to be references to a stub.
- virtual bool isCallSite(const Reference &) = 0;
-
- /// Used by GOTPass to locate GOT References
- virtual bool isGOTAccess(const Reference &, bool &canBypassGOT) {
- return false;
- }
-
- /// Used by TLVPass to locate TLV References.
- virtual bool isTLVAccess(const Reference &) const { return false; }
-
- /// Used by the TLVPass to update TLV References.
- virtual void updateReferenceToTLV(const Reference *) {}
-
- /// Used by ShimPass to insert shims in branches that switch mode.
- virtual bool isNonCallBranch(const Reference &) = 0;
-
- /// Used by GOTPass to update GOT References
- virtual void updateReferenceToGOT(const Reference *, bool targetIsNowGOT) {}
-
- /// Does this architecture make use of __unwind_info sections for exception
- /// handling? If so, it will need a separate pass to create them.
- virtual bool needsCompactUnwind() = 0;
-
- /// Returns the kind of reference to use to synthesize a 32-bit image-offset
- /// value, used in the __unwind_info section.
- virtual Reference::KindValue imageOffsetKind() = 0;
-
- /// Returns the kind of reference to use to synthesize a 32-bit image-offset
- /// indirect value. Used for personality functions in the __unwind_info
- /// section.
- virtual Reference::KindValue imageOffsetKindIndirect() = 0;
-
- /// Architecture specific compact unwind type that signals __eh_frame should
- /// actually be used.
- virtual uint32_t dwarfCompactUnwindType() = 0;
-
- /// Reference from an __eh_frame CIE atom to its personality function it's
- /// describing. Usually pointer-sized and PC-relative, but differs in whether
- /// it needs to be in relocatable objects.
- virtual Reference::KindValue unwindRefToPersonalityFunctionKind() = 0;
-
- /// Reference from an __eh_frame FDE to the CIE it's based on.
- virtual Reference::KindValue unwindRefToCIEKind() = 0;
-
- /// Reference from an __eh_frame FDE atom to the function it's
- /// describing. Usually pointer-sized and PC-relative, but differs in whether
- /// it needs to be in relocatable objects.
- virtual Reference::KindValue unwindRefToFunctionKind() = 0;
-
- /// Reference from an __unwind_info entry of dwarfCompactUnwindType to the
- /// required __eh_frame entry. On current architectures, the low 24 bits
- /// represent the offset of the function's FDE entry from the start of
- /// __eh_frame.
- virtual Reference::KindValue unwindRefToEhFrameKind() = 0;
-
- /// Returns a pointer sized reference kind. On 64-bit targets this will
- /// likely be something like pointer64, and pointer32 on 32-bit targets.
- virtual Reference::KindValue pointerKind() = 0;
-
- virtual const Atom *fdeTargetFunction(const DefinedAtom *fde);
-
- /// Used by normalizedFromAtoms() to know where to generated rebasing and
- /// binding info in final executables.
- virtual bool isPointer(const Reference &) = 0;
-
- /// Used by normalizedFromAtoms() to know where to generated lazy binding
- /// info in final executables.
- virtual bool isLazyPointer(const Reference &);
-
- /// Reference from an __stub_helper entry to the required offset of the
- /// lazy bind commands.
- virtual Reference::KindValue lazyImmediateLocationKind() = 0;
-
- /// Returns true if the specified relocation is paired to the next relocation.
- virtual bool isPairedReloc(const normalized::Relocation &) = 0;
-
- /// Prototype for a helper function. Given a sectionIndex and address,
- /// finds the atom and offset with that atom of that address.
- typedef std::function<llvm::Error (uint32_t sectionIndex, uint64_t addr,
- const lld::Atom **, Reference::Addend *)>
- FindAtomBySectionAndAddress;
-
- /// Prototype for a helper function. Given a symbolIndex, finds the atom
- /// representing that symbol.
- typedef std::function<llvm::Error (uint32_t symbolIndex,
- const lld::Atom **)> FindAtomBySymbolIndex;
-
- /// Analyzes a relocation from a .o file and returns the info
- /// (kind, target, addend) needed to instantiate a Reference.
- /// Two helper functions are passed as parameters to find the target atom
- /// given a symbol index or address.
- virtual llvm::Error
- getReferenceInfo(const normalized::Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool isBigEndian,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) = 0;
-
- /// Analyzes a pair of relocations from a .o file and returns the info
- /// (kind, target, addend) needed to instantiate a Reference.
- /// Two helper functions are passed as parameters to find the target atom
- /// given a symbol index or address.
- virtual llvm::Error
- getPairReferenceInfo(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool isBig, bool scatterable,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) = 0;
-
- /// Prototype for a helper function. Given an atom, finds the symbol table
- /// index for it in the output file.
- typedef std::function<uint32_t (const Atom &atom)> FindSymbolIndexForAtom;
-
- /// Prototype for a helper function. Given an atom, finds the index
- /// of the section that will contain the atom.
- typedef std::function<uint32_t (const Atom &atom)> FindSectionIndexForAtom;
-
- /// Prototype for a helper function. Given an atom, finds the address
- /// assigned to it in the output file.
- typedef std::function<uint64_t (const Atom &atom)> FindAddressForAtom;
-
- /// Some architectures require local symbols on anonymous atoms.
- virtual bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) {
- return false;
- }
-
- /// Copy raw content then apply all fixup References on an Atom.
- virtual void generateAtomContent(const DefinedAtom &atom, bool relocatable,
- FindAddressForAtom findAddress,
- FindAddressForAtom findSectionAddress,
- uint64_t imageBaseAddress,
- llvm::MutableArrayRef<uint8_t> atomContentBuffer) = 0;
-
- /// Used in -r mode to convert a Reference to a mach-o relocation.
- virtual void appendSectionRelocations(const DefinedAtom &atom,
- uint64_t atomSectionOffset,
- const Reference &ref,
- FindSymbolIndexForAtom,
- FindSectionIndexForAtom,
- FindAddressForAtom,
- normalized::Relocations&) = 0;
-
- /// Add arch-specific References.
- virtual void addAdditionalReferences(MachODefinedAtom &atom) { }
-
- // Add Reference for data-in-code marker.
- virtual void addDataInCodeReference(MachODefinedAtom &atom, uint32_t atomOff,
- uint16_t length, uint16_t kind) { }
-
- /// Returns true if the specificed Reference value marks the start or end
- /// of a data-in-code range in an atom.
- virtual bool isDataInCodeTransition(Reference::KindValue refKind) {
- return false;
- }
-
- /// Returns the Reference value for a Reference that marks that start of
- /// a data-in-code range.
- virtual Reference::KindValue dataInCodeTransitionStart(
- const MachODefinedAtom &atom) {
- return 0;
- }
-
- /// Returns the Reference value for a Reference that marks that end of
- /// a data-in-code range.
- virtual Reference::KindValue dataInCodeTransitionEnd(
- const MachODefinedAtom &atom) {
- return 0;
- }
-
- /// Only relevant for 32-bit arm archs.
- virtual bool isThumbFunction(const DefinedAtom &atom) { return false; }
-
- /// Only relevant for 32-bit arm archs.
- virtual const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
- const DefinedAtom &) {
- llvm_unreachable("shims only support on arm");
- }
-
- /// Does a given unwind-cfi atom represent a CIE (as opposed to an FDE).
- static bool isDwarfCIE(bool isBig, const DefinedAtom *atom);
-
- struct ReferenceInfo {
- Reference::KindArch arch;
- uint16_t kind;
- uint32_t offset;
- int32_t addend;
- };
-
- struct OptionalRefInfo {
- bool used;
- uint16_t kind;
- uint32_t offset;
- int32_t addend;
- };
-
- /// Table of architecture specific information for creating stubs.
- struct StubInfo {
- const char* binderSymbolName;
- ReferenceInfo lazyPointerReferenceToHelper;
- ReferenceInfo lazyPointerReferenceToFinal;
- ReferenceInfo nonLazyPointerReferenceToBinder;
- uint8_t codeAlignment;
-
- uint32_t stubSize;
- uint8_t stubBytes[16];
- ReferenceInfo stubReferenceToLP;
- OptionalRefInfo optStubReferenceToLP;
-
- uint32_t stubHelperSize;
- uint8_t stubHelperBytes[16];
- ReferenceInfo stubHelperReferenceToImm;
- ReferenceInfo stubHelperReferenceToHelperCommon;
-
- DefinedAtom::ContentType stubHelperImageCacheContentType;
-
- uint32_t stubHelperCommonSize;
- uint8_t stubHelperCommonAlignment;
- uint8_t stubHelperCommonBytes[36];
- ReferenceInfo stubHelperCommonReferenceToCache;
- OptionalRefInfo optStubHelperCommonReferenceToCache;
- ReferenceInfo stubHelperCommonReferenceToBinder;
- OptionalRefInfo optStubHelperCommonReferenceToBinder;
- };
-
- virtual const StubInfo &stubInfo() = 0;
-
-protected:
- ArchHandler();
-
- static std::unique_ptr<mach_o::ArchHandler> create_x86_64();
- static std::unique_ptr<mach_o::ArchHandler> create_x86();
- static std::unique_ptr<mach_o::ArchHandler> create_arm();
- static std::unique_ptr<mach_o::ArchHandler> create_arm64();
-
- // Handy way to pack mach-o r_type and other bit fields into one 16-bit value.
- typedef uint16_t RelocPattern;
- enum {
- rScattered = 0x8000,
- rPcRel = 0x4000,
- rExtern = 0x2000,
- rLength1 = 0x0000,
- rLength2 = 0x0100,
- rLength4 = 0x0200,
- rLength8 = 0x0300,
- rLenArmLo = rLength1,
- rLenArmHi = rLength2,
- rLenThmbLo = rLength4,
- rLenThmbHi = rLength8
- };
- /// Extract RelocPattern from normalized mach-o relocation.
- static RelocPattern relocPattern(const normalized::Relocation &reloc);
- /// Create normalized Relocation initialized from pattern.
- static normalized::Relocation relocFromPattern(RelocPattern pattern);
- /// One liner to add a relocation.
- static void appendReloc(normalized::Relocations &relocs, uint32_t offset,
- uint32_t symbol, uint32_t value,
- RelocPattern pattern);
-
-
- static int16_t readS16(const uint8_t *addr, bool isBig);
- static int32_t readS32(const uint8_t *addr, bool isBig);
- static uint32_t readU32(const uint8_t *addr, bool isBig);
- static int64_t readS64(const uint8_t *addr, bool isBig);
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_ARCH_HANDLER_H
+++ /dev/null
-//===- lib/FileFormat/MachO/ArchHandler_arm.cpp ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-using llvm::support::ulittle32_t;
-using llvm::support::little32_t;
-
-
-class ArchHandler_arm : public ArchHandler {
-public:
- ArchHandler_arm() = default;
- ~ArchHandler_arm() override = default;
-
- const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
-
- Reference::KindArch kindArch() override { return Reference::KindArch::ARM; }
-
- const ArchHandler::StubInfo &stubInfo() override;
- bool isCallSite(const Reference &) override;
- bool isPointer(const Reference &) override;
- bool isPairedReloc(const normalized::Relocation &) override;
- bool isNonCallBranch(const Reference &) override;
-
- bool needsCompactUnwind() override {
- return false;
- }
- Reference::KindValue imageOffsetKind() override {
- return invalid;
- }
- Reference::KindValue imageOffsetKindIndirect() override {
- return invalid;
- }
-
- Reference::KindValue unwindRefToPersonalityFunctionKind() override {
- return invalid;
- }
-
- Reference::KindValue unwindRefToCIEKind() override {
- return invalid;
- }
-
- Reference::KindValue unwindRefToFunctionKind() override {
- return invalid;
- }
-
- Reference::KindValue unwindRefToEhFrameKind() override {
- return invalid;
- }
-
- Reference::KindValue lazyImmediateLocationKind() override {
- return lazyImmediateLocation;
- }
-
- Reference::KindValue pointerKind() override {
- return invalid;
- }
-
- uint32_t dwarfCompactUnwindType() override {
- // FIXME
- return -1;
- }
-
- llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
- llvm::Error
- getPairReferenceInfo(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap, bool scatterable,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
-
- void generateAtomContent(const DefinedAtom &atom, bool relocatable,
- FindAddressForAtom findAddress,
- FindAddressForAtom findSectionAddress,
- uint64_t imageBaseAddress,
- llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
-
- void appendSectionRelocations(const DefinedAtom &atom,
- uint64_t atomSectionOffset,
- const Reference &ref,
- FindSymbolIndexForAtom,
- FindSectionIndexForAtom,
- FindAddressForAtom,
- normalized::Relocations &) override;
-
- void addAdditionalReferences(MachODefinedAtom &atom) override;
-
- bool isDataInCodeTransition(Reference::KindValue refKind) override {
- switch (refKind) {
- case modeThumbCode:
- case modeArmCode:
- case modeData:
- return true;
- default:
- return false;
- break;
- }
- }
-
- Reference::KindValue dataInCodeTransitionStart(
- const MachODefinedAtom &atom) override {
- return modeData;
- }
-
- Reference::KindValue dataInCodeTransitionEnd(
- const MachODefinedAtom &atom) override {
- return atom.isThumb() ? modeThumbCode : modeArmCode;
- }
-
- bool isThumbFunction(const DefinedAtom &atom) override;
- const DefinedAtom *createShim(MachOFile &file, bool thumbToArm,
- const DefinedAtom &) override;
-
-private:
- friend class Thumb2ToArmShimAtom;
- friend class ArmToThumbShimAtom;
-
- static const Registry::KindStrings _sKindStrings[];
- static const StubInfo _sStubInfoArmPIC;
-
- enum ArmKind : Reference::KindValue {
- invalid, /// for error condition
-
- modeThumbCode, /// Content starting at this offset is thumb.
- modeArmCode, /// Content starting at this offset is arm.
- modeData, /// Content starting at this offset is data.
-
- // Kinds found in mach-o .o files:
- thumb_bl22, /// ex: bl _foo
- thumb_b22, /// ex: b _foo
- thumb_movw, /// ex: movw r1, :lower16:_foo
- thumb_movt, /// ex: movt r1, :lower16:_foo
- thumb_movw_funcRel, /// ex: movw r1, :lower16:(_foo-(L1+4))
- thumb_movt_funcRel, /// ex: movt r1, :upper16:(_foo-(L1+4))
- arm_bl24, /// ex: bl _foo
- arm_b24, /// ex: b _foo
- arm_movw, /// ex: movw r1, :lower16:_foo
- arm_movt, /// ex: movt r1, :lower16:_foo
- arm_movw_funcRel, /// ex: movw r1, :lower16:(_foo-(L1+4))
- arm_movt_funcRel, /// ex: movt r1, :upper16:(_foo-(L1+4))
- pointer32, /// ex: .long _foo
- delta32, /// ex: .long _foo - .
-
- // Kinds introduced by Passes:
- lazyPointer, /// Location contains a lazy pointer.
- lazyImmediateLocation, /// Location contains immediate value used in stub.
- };
-
- // Utility functions for inspecting/updating instructions.
- static bool isThumbMovw(uint32_t instruction);
- static bool isThumbMovt(uint32_t instruction);
- static bool isArmMovw(uint32_t instruction);
- static bool isArmMovt(uint32_t instruction);
- static int32_t getDisplacementFromThumbBranch(uint32_t instruction, uint32_t);
- static int32_t getDisplacementFromArmBranch(uint32_t instruction);
- static uint16_t getWordFromThumbMov(uint32_t instruction);
- static uint16_t getWordFromArmMov(uint32_t instruction);
- static uint32_t clearThumbBit(uint32_t value, const Atom *target);
- static uint32_t setDisplacementInArmBranch(uint32_t instr, int32_t disp,
- bool targetIsThumb);
- static uint32_t setDisplacementInThumbBranch(uint32_t instr, uint32_t ia,
- int32_t disp, bool targetThumb);
- static uint32_t setWordFromThumbMov(uint32_t instruction, uint16_t word);
- static uint32_t setWordFromArmMov(uint32_t instruction, uint16_t word);
-
- StringRef stubName(const DefinedAtom &);
- bool useExternalRelocationTo(const Atom &target);
-
- void applyFixupFinal(const Reference &ref, uint8_t *location,
- uint64_t fixupAddress, uint64_t targetAddress,
- uint64_t inAtomAddress, bool &thumbMode,
- bool targetIsThumb);
-
- void applyFixupRelocatable(const Reference &ref, uint8_t *location,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress, bool &thumbMode,
- bool targetIsThumb);
-};
-
-//===----------------------------------------------------------------------===//
-// ArchHandler_arm
-//===----------------------------------------------------------------------===//
-
-const Registry::KindStrings ArchHandler_arm::_sKindStrings[] = {
- LLD_KIND_STRING_ENTRY(invalid),
- LLD_KIND_STRING_ENTRY(modeThumbCode),
- LLD_KIND_STRING_ENTRY(modeArmCode),
- LLD_KIND_STRING_ENTRY(modeData),
- LLD_KIND_STRING_ENTRY(thumb_bl22),
- LLD_KIND_STRING_ENTRY(thumb_b22),
- LLD_KIND_STRING_ENTRY(thumb_movw),
- LLD_KIND_STRING_ENTRY(thumb_movt),
- LLD_KIND_STRING_ENTRY(thumb_movw_funcRel),
- LLD_KIND_STRING_ENTRY(thumb_movt_funcRel),
- LLD_KIND_STRING_ENTRY(arm_bl24),
- LLD_KIND_STRING_ENTRY(arm_b24),
- LLD_KIND_STRING_ENTRY(arm_movw),
- LLD_KIND_STRING_ENTRY(arm_movt),
- LLD_KIND_STRING_ENTRY(arm_movw_funcRel),
- LLD_KIND_STRING_ENTRY(arm_movt_funcRel),
- LLD_KIND_STRING_ENTRY(pointer32),
- LLD_KIND_STRING_ENTRY(delta32),
- LLD_KIND_STRING_ENTRY(lazyPointer),
- LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
- LLD_KIND_STRING_END
-};
-
-const ArchHandler::StubInfo ArchHandler_arm::_sStubInfoArmPIC = {
- "dyld_stub_binder",
-
- // References in lazy pointer
- { Reference::KindArch::ARM, pointer32, 0, 0 },
- { Reference::KindArch::ARM, lazyPointer, 0, 0 },
-
- // GOT pointer to dyld_stub_binder
- { Reference::KindArch::ARM, pointer32, 0, 0 },
-
- // arm code alignment 2^2
- 2,
-
- // Stub size and code
- 16,
- { 0x04, 0xC0, 0x9F, 0xE5, // ldr ip, pc + 12
- 0x0C, 0xC0, 0x8F, 0xE0, // add ip, pc, ip
- 0x00, 0xF0, 0x9C, 0xE5, // ldr pc, [ip]
- 0x00, 0x00, 0x00, 0x00 }, // .long L_foo$lazy_ptr - (L1$scv + 8)
- { Reference::KindArch::ARM, delta32, 12, 0 },
- { false, 0, 0, 0 },
-
- // Stub Helper size and code
- 12,
- { 0x00, 0xC0, 0x9F, 0xE5, // ldr ip, [pc, #0]
- 0x00, 0x00, 0x00, 0xEA, // b _helperhelper
- 0x00, 0x00, 0x00, 0x00 }, // .long lazy-info-offset
- { Reference::KindArch::ARM, lazyImmediateLocation, 8, 0 },
- { Reference::KindArch::ARM, arm_b24, 4, 0 },
-
- // Stub helper image cache content type
- DefinedAtom::typeGOT,
-
- // Stub Helper-Common size and code
- 36,
- // Stub helper alignment
- 2,
- { // push lazy-info-offset
- 0x04, 0xC0, 0x2D, 0xE5, // str ip, [sp, #-4]!
- // push address of dyld_mageLoaderCache
- 0x10, 0xC0, 0x9F, 0xE5, // ldr ip, L1
- 0x0C, 0xC0, 0x8F, 0xE0, // add ip, pc, ip
- 0x04, 0xC0, 0x2D, 0xE5, // str ip, [sp, #-4]!
- // jump through dyld_stub_binder
- 0x08, 0xC0, 0x9F, 0xE5, // ldr ip, L2
- 0x0C, 0xC0, 0x8F, 0xE0, // add ip, pc, ip
- 0x00, 0xF0, 0x9C, 0xE5, // ldr pc, [ip]
- 0x00, 0x00, 0x00, 0x00, // L1: .long fFastStubGOTAtom - (helper+16)
- 0x00, 0x00, 0x00, 0x00 }, // L2: .long dyld_stub_binder - (helper+28)
- { Reference::KindArch::ARM, delta32, 28, 0xC },
- { false, 0, 0, 0 },
- { Reference::KindArch::ARM, delta32, 32, 0x04 },
- { false, 0, 0, 0 }
-};
-
-const ArchHandler::StubInfo &ArchHandler_arm::stubInfo() {
- // If multiple kinds of stubs are supported, select which StubInfo here.
- return _sStubInfoArmPIC;
-}
-
-bool ArchHandler_arm::isCallSite(const Reference &ref) {
- switch (ref.kindValue()) {
- case thumb_b22:
- case thumb_bl22:
- case arm_b24:
- case arm_bl24:
- return true;
- default:
- return false;
- }
-}
-
-bool ArchHandler_arm::isPointer(const Reference &ref) {
- return (ref.kindValue() == pointer32);
-}
-
-bool ArchHandler_arm::isNonCallBranch(const Reference &ref) {
- switch (ref.kindValue()) {
- case thumb_b22:
- case arm_b24:
- return true;
- default:
- return false;
- }
-}
-
-bool ArchHandler_arm::isPairedReloc(const Relocation &reloc) {
- switch (reloc.type) {
- case ARM_RELOC_SECTDIFF:
- case ARM_RELOC_LOCAL_SECTDIFF:
- case ARM_RELOC_HALF_SECTDIFF:
- case ARM_RELOC_HALF:
- return true;
- default:
- return false;
- }
-}
-
-/// Trace references from stub atom to lazy pointer to target and get its name.
-StringRef ArchHandler_arm::stubName(const DefinedAtom &stubAtom) {
- assert(stubAtom.contentType() == DefinedAtom::typeStub);
- for (const Reference *ref : stubAtom) {
- if (const DefinedAtom* lp = dyn_cast<DefinedAtom>(ref->target())) {
- if (lp->contentType() != DefinedAtom::typeLazyPointer)
- continue;
- for (const Reference *ref2 : *lp) {
- if (ref2->kindValue() != lazyPointer)
- continue;
- return ref2->target()->name();
- }
- }
- }
- return "stub";
-}
-
-/// Extract displacement from an ARM b/bl/blx instruction.
-int32_t ArchHandler_arm::getDisplacementFromArmBranch(uint32_t instruction) {
- // Sign-extend imm24
- int32_t displacement = (instruction & 0x00FFFFFF) << 2;
- if ((displacement & 0x02000000) != 0)
- displacement |= 0xFC000000;
- // If this is BLX and H bit set, add 2.
- if ((instruction & 0xFF000000) == 0xFB000000)
- displacement += 2;
- return displacement;
-}
-
-/// Update an ARM b/bl/blx instruction, switching bl <-> blx as needed.
-uint32_t ArchHandler_arm::setDisplacementInArmBranch(uint32_t instruction,
- int32_t displacement,
- bool targetIsThumb) {
- assert((displacement <= 33554428) && (displacement > (-33554432))
- && "arm branch out of range");
- bool is_blx = ((instruction & 0xF0000000) == 0xF0000000);
- uint32_t newInstruction = (instruction & 0xFF000000);
- uint32_t h = 0;
- if (targetIsThumb) {
- // Force use of BLX.
- newInstruction = 0xFA000000;
- if (!is_blx) {
- assert(((instruction & 0xF0000000) == 0xE0000000)
- && "no conditional arm blx");
- assert(((instruction & 0xFF000000) == 0xEB000000)
- && "no arm pc-rel BX instruction");
- }
- if (displacement & 2)
- h = 1;
- }
- else {
- // Force use of B/BL.
- if (is_blx)
- newInstruction = 0xEB000000;
- }
- newInstruction |= (h << 24) | ((displacement >> 2) & 0x00FFFFFF);
- return newInstruction;
-}
-
-/// Extract displacement from a thumb b/bl/blx instruction.
-int32_t ArchHandler_arm::getDisplacementFromThumbBranch(uint32_t instruction,
- uint32_t instrAddr) {
- bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
- uint32_t s = (instruction >> 10) & 0x1;
- uint32_t j1 = (instruction >> 29) & 0x1;
- uint32_t j2 = (instruction >> 27) & 0x1;
- uint32_t imm10 = instruction & 0x3FF;
- uint32_t imm11 = (instruction >> 16) & 0x7FF;
- uint32_t i1 = (j1 == s);
- uint32_t i2 = (j2 == s);
- uint32_t dis =
- (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
- int32_t sdis = dis;
- int32_t result = s ? (sdis | 0xFE000000) : sdis;
- if (is_blx && (instrAddr & 0x2)) {
- // The thumb blx instruction always has low bit of imm11 as zero. The way
- // a 2-byte aligned blx can branch to a 4-byte aligned ARM target is that
- // the blx instruction always 4-byte aligns the pc before adding the
- // displacement from the blx. We must emulate that when decoding this.
- result -= 2;
- }
- return result;
-}
-
-/// Update a thumb b/bl/blx instruction, switching bl <-> blx as needed.
-uint32_t ArchHandler_arm::setDisplacementInThumbBranch(uint32_t instruction,
- uint32_t instrAddr,
- int32_t displacement,
- bool targetIsThumb) {
- assert((displacement <= 16777214) && (displacement > (-16777216))
- && "thumb branch out of range");
- bool is_bl = ((instruction & 0xD000F800) == 0xD000F000);
- bool is_blx = ((instruction & 0xD000F800) == 0xC000F000);
- bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
- uint32_t newInstruction = (instruction & 0xD000F800);
- if (is_bl || is_blx) {
- if (targetIsThumb) {
- newInstruction = 0xD000F000; // Use bl
- } else {
- newInstruction = 0xC000F000; // Use blx
- // See note in getDisplacementFromThumbBranch() about blx.
- if (instrAddr & 0x2)
- displacement += 2;
- }
- } else if (is_b) {
- assert(targetIsThumb && "no pc-rel thumb branch instruction that "
- "switches to arm mode");
- }
- else {
- llvm_unreachable("thumb branch22 reloc on a non-branch instruction");
- }
- uint32_t s = (uint32_t)(displacement >> 24) & 0x1;
- uint32_t i1 = (uint32_t)(displacement >> 23) & 0x1;
- uint32_t i2 = (uint32_t)(displacement >> 22) & 0x1;
- uint32_t imm10 = (uint32_t)(displacement >> 12) & 0x3FF;
- uint32_t imm11 = (uint32_t)(displacement >> 1) & 0x7FF;
- uint32_t j1 = (i1 == s);
- uint32_t j2 = (i2 == s);
- uint32_t nextDisp = (j1 << 13) | (j2 << 11) | imm11;
- uint32_t firstDisp = (s << 10) | imm10;
- newInstruction |= (nextDisp << 16) | firstDisp;
- return newInstruction;
-}
-
-bool ArchHandler_arm::isThumbMovw(uint32_t instruction) {
- return (instruction & 0x8000FBF0) == 0x0000F240;
-}
-
-bool ArchHandler_arm::isThumbMovt(uint32_t instruction) {
- return (instruction & 0x8000FBF0) == 0x0000F2C0;
-}
-
-bool ArchHandler_arm::isArmMovw(uint32_t instruction) {
- return (instruction & 0x0FF00000) == 0x03000000;
-}
-
-bool ArchHandler_arm::isArmMovt(uint32_t instruction) {
- return (instruction & 0x0FF00000) == 0x03400000;
-}
-
-uint16_t ArchHandler_arm::getWordFromThumbMov(uint32_t instruction) {
- assert(isThumbMovw(instruction) || isThumbMovt(instruction));
- uint32_t i = ((instruction & 0x00000400) >> 10);
- uint32_t imm4 = (instruction & 0x0000000F);
- uint32_t imm3 = ((instruction & 0x70000000) >> 28);
- uint32_t imm8 = ((instruction & 0x00FF0000) >> 16);
- return (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
-}
-
-uint16_t ArchHandler_arm::getWordFromArmMov(uint32_t instruction) {
- assert(isArmMovw(instruction) || isArmMovt(instruction));
- uint32_t imm4 = ((instruction & 0x000F0000) >> 16);
- uint32_t imm12 = (instruction & 0x00000FFF);
- return (imm4 << 12) | imm12;
-}
-
-uint32_t ArchHandler_arm::setWordFromThumbMov(uint32_t instr, uint16_t word) {
- assert(isThumbMovw(instr) || isThumbMovt(instr));
- uint32_t imm4 = (word & 0xF000) >> 12;
- uint32_t i = (word & 0x0800) >> 11;
- uint32_t imm3 = (word & 0x0700) >> 8;
- uint32_t imm8 = word & 0x00FF;
- return (instr & 0x8F00FBF0) | imm4 | (i << 10) | (imm3 << 28) | (imm8 << 16);
-}
-
-uint32_t ArchHandler_arm::setWordFromArmMov(uint32_t instr, uint16_t word) {
- assert(isArmMovw(instr) || isArmMovt(instr));
- uint32_t imm4 = (word & 0xF000) >> 12;
- uint32_t imm12 = word & 0x0FFF;
- return (instr & 0xFFF0F000) | (imm4 << 16) | imm12;
-}
-
-uint32_t ArchHandler_arm::clearThumbBit(uint32_t value, const Atom *target) {
- // The assembler often adds one to the address of a thumb function.
- // We need to undo that so it does not look like an addend.
- if (value & 1) {
- if (isa<DefinedAtom>(target)) {
- const MachODefinedAtom *machoTarget =
- reinterpret_cast<const MachODefinedAtom *>(target);
- if (machoTarget->isThumb())
- value &= -2; // mask off thumb-bit
- }
- }
- return value;
-}
-
-llvm::Error ArchHandler_arm::getReferenceInfo(
- const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom,
- uint64_t fixupAddress, bool isBig,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
- const lld::Atom **target, Reference::Addend *addend) {
- const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- uint64_t targetAddress;
- uint32_t instruction = *(const ulittle32_t *)fixupContent;
- int32_t displacement;
- switch (relocPattern(reloc)) {
- case ARM_THUMB_RELOC_BR22 | rPcRel | rExtern | rLength4:
- // ex: bl _foo (and _foo is undefined)
- if ((instruction & 0xD000F800) == 0x9000F000)
- *kind = thumb_b22;
- else
- *kind = thumb_bl22;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- // Instruction contains branch to addend.
- displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
- *addend = fixupAddress + 4 + displacement;
- return llvm::Error::success();
- case ARM_THUMB_RELOC_BR22 | rPcRel | rLength4:
- // ex: bl _foo (and _foo is defined)
- if ((instruction & 0xD000F800) == 0x9000F000)
- *kind = thumb_b22;
- else
- *kind = thumb_bl22;
- displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
- targetAddress = fixupAddress + 4 + displacement;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- case ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4:
- // ex: bl _foo+4 (and _foo is defined)
- if ((instruction & 0xD000F800) == 0x9000F000)
- *kind = thumb_b22;
- else
- *kind = thumb_bl22;
- displacement = getDisplacementFromThumbBranch(instruction, fixupAddress);
- targetAddress = fixupAddress + 4 + displacement;
- if (auto ec = atomFromAddress(0, reloc.value, target, addend))
- return ec;
- // reloc.value is target atom's address. Instruction contains branch
- // to atom+addend.
- *addend += (targetAddress - reloc.value);
- return llvm::Error::success();
- case ARM_RELOC_BR24 | rPcRel | rExtern | rLength4:
- // ex: bl _foo (and _foo is undefined)
- if (((instruction & 0x0F000000) == 0x0A000000)
- && ((instruction & 0xF0000000) != 0xF0000000))
- *kind = arm_b24;
- else
- *kind = arm_bl24;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- // Instruction contains branch to addend.
- displacement = getDisplacementFromArmBranch(instruction);
- *addend = fixupAddress + 8 + displacement;
- return llvm::Error::success();
- case ARM_RELOC_BR24 | rPcRel | rLength4:
- // ex: bl _foo (and _foo is defined)
- if (((instruction & 0x0F000000) == 0x0A000000)
- && ((instruction & 0xF0000000) != 0xF0000000))
- *kind = arm_b24;
- else
- *kind = arm_bl24;
- displacement = getDisplacementFromArmBranch(instruction);
- targetAddress = fixupAddress + 8 + displacement;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- case ARM_RELOC_BR24 | rScattered | rPcRel | rLength4:
- // ex: bl _foo+4 (and _foo is defined)
- if (((instruction & 0x0F000000) == 0x0A000000)
- && ((instruction & 0xF0000000) != 0xF0000000))
- *kind = arm_b24;
- else
- *kind = arm_bl24;
- displacement = getDisplacementFromArmBranch(instruction);
- targetAddress = fixupAddress + 8 + displacement;
- if (auto ec = atomFromAddress(0, reloc.value, target, addend))
- return ec;
- // reloc.value is target atom's address. Instruction contains branch
- // to atom+addend.
- *addend += (targetAddress - reloc.value);
- return llvm::Error::success();
- case ARM_RELOC_VANILLA | rExtern | rLength4:
- // ex: .long _foo (and _foo is undefined)
- *kind = pointer32;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = instruction;
- return llvm::Error::success();
- case ARM_RELOC_VANILLA | rLength4:
- // ex: .long _foo (and _foo is defined)
- *kind = pointer32;
- if (auto ec = atomFromAddress(reloc.symbol, instruction, target, addend))
- return ec;
- *addend = clearThumbBit((uint32_t) * addend, *target);
- return llvm::Error::success();
- case ARM_RELOC_VANILLA | rScattered | rLength4:
- // ex: .long _foo+a (and _foo is defined)
- *kind = pointer32;
- if (auto ec = atomFromAddress(0, reloc.value, target, addend))
- return ec;
- *addend += (clearThumbBit(instruction, *target) - reloc.value);
- return llvm::Error::success();
- default:
- return llvm::make_error<GenericError>("unsupported arm relocation type");
- }
- return llvm::Error::success();
-}
-
-llvm::Error
-ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool isBig,
- bool scatterable,
- FindAtomBySectionAndAddress atomFromAddr,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) {
- bool pointerDiff = false;
- bool funcRel;
- bool top;
- bool thumbReloc;
- switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
- case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbLo) << 16 |
- ARM_RELOC_PAIR | rScattered | rLenThmbLo):
- // ex: movw r1, :lower16:(_x-L1) [thumb mode]
- *kind = thumb_movw_funcRel;
- funcRel = true;
- top = false;
- thumbReloc = true;
- break;
- case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbHi) << 16 |
- ARM_RELOC_PAIR | rScattered | rLenThmbHi):
- // ex: movt r1, :upper16:(_x-L1) [thumb mode]
- *kind = thumb_movt_funcRel;
- funcRel = true;
- top = true;
- thumbReloc = true;
- break;
- case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmLo) << 16 |
- ARM_RELOC_PAIR | rScattered | rLenArmLo):
- // ex: movw r1, :lower16:(_x-L1) [arm mode]
- *kind = arm_movw_funcRel;
- funcRel = true;
- top = false;
- thumbReloc = false;
- break;
- case ((ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmHi) << 16 |
- ARM_RELOC_PAIR | rScattered | rLenArmHi):
- // ex: movt r1, :upper16:(_x-L1) [arm mode]
- *kind = arm_movt_funcRel;
- funcRel = true;
- top = true;
- thumbReloc = false;
- break;
- case ((ARM_RELOC_HALF | rLenThmbLo) << 16 |
- ARM_RELOC_PAIR | rLenThmbLo):
- // ex: movw r1, :lower16:_x [thumb mode]
- *kind = thumb_movw;
- funcRel = false;
- top = false;
- thumbReloc = true;
- break;
- case ((ARM_RELOC_HALF | rLenThmbHi) << 16 |
- ARM_RELOC_PAIR | rLenThmbHi):
- // ex: movt r1, :upper16:_x [thumb mode]
- *kind = thumb_movt;
- funcRel = false;
- top = true;
- thumbReloc = true;
- break;
- case ((ARM_RELOC_HALF | rLenArmLo) << 16 |
- ARM_RELOC_PAIR | rLenArmLo):
- // ex: movw r1, :lower16:_x [arm mode]
- *kind = arm_movw;
- funcRel = false;
- top = false;
- thumbReloc = false;
- break;
- case ((ARM_RELOC_HALF | rLenArmHi) << 16 |
- ARM_RELOC_PAIR | rLenArmHi):
- // ex: movt r1, :upper16:_x [arm mode]
- *kind = arm_movt;
- funcRel = false;
- top = true;
- thumbReloc = false;
- break;
- case ((ARM_RELOC_HALF | rScattered | rLenThmbLo) << 16 |
- ARM_RELOC_PAIR | rLenThmbLo):
- // ex: movw r1, :lower16:_x+a [thumb mode]
- *kind = thumb_movw;
- funcRel = false;
- top = false;
- thumbReloc = true;
- break;
- case ((ARM_RELOC_HALF | rScattered | rLenThmbHi) << 16 |
- ARM_RELOC_PAIR | rLenThmbHi):
- // ex: movt r1, :upper16:_x+a [thumb mode]
- *kind = thumb_movt;
- funcRel = false;
- top = true;
- thumbReloc = true;
- break;
- case ((ARM_RELOC_HALF | rScattered | rLenArmLo) << 16 |
- ARM_RELOC_PAIR | rLenArmLo):
- // ex: movw r1, :lower16:_x+a [arm mode]
- *kind = arm_movw;
- funcRel = false;
- top = false;
- thumbReloc = false;
- break;
- case ((ARM_RELOC_HALF | rScattered | rLenArmHi) << 16 |
- ARM_RELOC_PAIR | rLenArmHi):
- // ex: movt r1, :upper16:_x+a [arm mode]
- *kind = arm_movt;
- funcRel = false;
- top = true;
- thumbReloc = false;
- break;
- case ((ARM_RELOC_HALF | rExtern | rLenThmbLo) << 16 |
- ARM_RELOC_PAIR | rLenThmbLo):
- // ex: movw r1, :lower16:_undef [thumb mode]
- *kind = thumb_movw;
- funcRel = false;
- top = false;
- thumbReloc = true;
- break;
- case ((ARM_RELOC_HALF | rExtern | rLenThmbHi) << 16 |
- ARM_RELOC_PAIR | rLenThmbHi):
- // ex: movt r1, :upper16:_undef [thumb mode]
- *kind = thumb_movt;
- funcRel = false;
- top = true;
- thumbReloc = true;
- break;
- case ((ARM_RELOC_HALF | rExtern | rLenArmLo) << 16 |
- ARM_RELOC_PAIR | rLenArmLo):
- // ex: movw r1, :lower16:_undef [arm mode]
- *kind = arm_movw;
- funcRel = false;
- top = false;
- thumbReloc = false;
- break;
- case ((ARM_RELOC_HALF | rExtern | rLenArmHi) << 16 |
- ARM_RELOC_PAIR | rLenArmHi):
- // ex: movt r1, :upper16:_undef [arm mode]
- *kind = arm_movt;
- funcRel = false;
- top = true;
- thumbReloc = false;
- break;
- case ((ARM_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
- ARM_RELOC_PAIR | rScattered | rLength4):
- case ((ARM_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
- ARM_RELOC_PAIR | rScattered | rLength4):
- // ex: .long _foo - .
- pointerDiff = true;
- break;
- default:
- return llvm::make_error<GenericError>("unsupported arm relocation pair");
- }
- const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- uint32_t instruction = *(const ulittle32_t *)fixupContent;
- uint32_t value;
- uint32_t fromAddress;
- uint32_t toAddress;
- uint16_t instruction16;
- uint16_t other16;
- const lld::Atom *fromTarget;
- Reference::Addend offsetInTo;
- Reference::Addend offsetInFrom;
- if (pointerDiff) {
- toAddress = reloc1.value;
- fromAddress = reloc2.value;
- if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
- return ec;
- if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
- return ec;
- if (scatterable && (fromTarget != inAtom))
- return llvm::make_error<GenericError>(
- "SECTDIFF relocation where subtrahend label is not in atom");
- *kind = delta32;
- value = clearThumbBit(instruction, *target);
- *addend = (int32_t)(value - (toAddress - fixupAddress));
- } else if (funcRel) {
- toAddress = reloc1.value;
- fromAddress = reloc2.value;
- if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
- return ec;
- if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
- return ec;
- if (fromTarget != inAtom)
- return llvm::make_error<GenericError>("ARM_RELOC_HALF_SECTDIFF relocation"
- " where subtrahend label is not in atom");
- other16 = (reloc2.offset & 0xFFFF);
- if (thumbReloc) {
- if (top) {
- if (!isThumbMovt(instruction))
- return llvm::make_error<GenericError>("expected movt instruction");
- }
- else {
- if (!isThumbMovw(instruction))
- return llvm::make_error<GenericError>("expected movw instruction");
- }
- instruction16 = getWordFromThumbMov(instruction);
- }
- else {
- if (top) {
- if (!isArmMovt(instruction))
- return llvm::make_error<GenericError>("expected movt instruction");
- }
- else {
- if (!isArmMovw(instruction))
- return llvm::make_error<GenericError>("expected movw instruction");
- }
- instruction16 = getWordFromArmMov(instruction);
- }
- if (top)
- value = (instruction16 << 16) | other16;
- else
- value = (other16 << 16) | instruction16;
- value = clearThumbBit(value, *target);
- int64_t ta = (int64_t) value - (toAddress - fromAddress);
- *addend = ta - offsetInFrom;
- return llvm::Error::success();
- } else {
- uint32_t sectIndex;
- if (thumbReloc) {
- if (top) {
- if (!isThumbMovt(instruction))
- return llvm::make_error<GenericError>("expected movt instruction");
- }
- else {
- if (!isThumbMovw(instruction))
- return llvm::make_error<GenericError>("expected movw instruction");
- }
- instruction16 = getWordFromThumbMov(instruction);
- }
- else {
- if (top) {
- if (!isArmMovt(instruction))
- return llvm::make_error<GenericError>("expected movt instruction");
- }
- else {
- if (!isArmMovw(instruction))
- return llvm::make_error<GenericError>("expected movw instruction");
- }
- instruction16 = getWordFromArmMov(instruction);
- }
- other16 = (reloc2.offset & 0xFFFF);
- if (top)
- value = (instruction16 << 16) | other16;
- else
- value = (other16 << 16) | instruction16;
- if (reloc1.isExtern) {
- if (auto ec = atomFromSymbolIndex(reloc1.symbol, target))
- return ec;
- *addend = value;
- } else {
- if (reloc1.scattered) {
- toAddress = reloc1.value;
- sectIndex = 0;
- } else {
- toAddress = value;
- sectIndex = reloc1.symbol;
- }
- if (auto ec = atomFromAddr(sectIndex, toAddress, target, &offsetInTo))
- return ec;
- *addend = value - toAddress;
- }
- }
-
- return llvm::Error::success();
-}
-
-void ArchHandler_arm::applyFixupFinal(const Reference &ref, uint8_t *loc,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress,
- bool &thumbMode, bool targetIsThumb) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::ARM);
- ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
- int32_t displacement;
- uint16_t value16;
- uint32_t value32;
- switch (static_cast<ArmKind>(ref.kindValue())) {
- case modeThumbCode:
- thumbMode = true;
- break;
- case modeArmCode:
- thumbMode = false;
- break;
- case modeData:
- break;
- case thumb_b22:
- case thumb_bl22:
- assert(thumbMode);
- displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
- value32 = setDisplacementInThumbBranch(*loc32, fixupAddress,
- displacement, targetIsThumb);
- *loc32 = value32;
- break;
- case thumb_movw:
- assert(thumbMode);
- value16 = (targetAddress + ref.addend()) & 0xFFFF;
- if (targetIsThumb)
- value16 |= 1;
- *loc32 = setWordFromThumbMov(*loc32, value16);
- break;
- case thumb_movt:
- assert(thumbMode);
- value16 = (targetAddress + ref.addend()) >> 16;
- *loc32 = setWordFromThumbMov(*loc32, value16);
- break;
- case thumb_movw_funcRel:
- assert(thumbMode);
- value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
- if (targetIsThumb)
- value16 |= 1;
- *loc32 = setWordFromThumbMov(*loc32, value16);
- break;
- case thumb_movt_funcRel:
- assert(thumbMode);
- value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
- *loc32 = setWordFromThumbMov(*loc32, value16);
- break;
- case arm_b24:
- case arm_bl24:
- assert(!thumbMode);
- displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
- value32 = setDisplacementInArmBranch(*loc32, displacement, targetIsThumb);
- *loc32 = value32;
- break;
- case arm_movw:
- assert(!thumbMode);
- value16 = (targetAddress + ref.addend()) & 0xFFFF;
- if (targetIsThumb)
- value16 |= 1;
- *loc32 = setWordFromArmMov(*loc32, value16);
- break;
- case arm_movt:
- assert(!thumbMode);
- value16 = (targetAddress + ref.addend()) >> 16;
- *loc32 = setWordFromArmMov(*loc32, value16);
- break;
- case arm_movw_funcRel:
- assert(!thumbMode);
- value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
- if (targetIsThumb)
- value16 |= 1;
- *loc32 = setWordFromArmMov(*loc32, value16);
- break;
- case arm_movt_funcRel:
- assert(!thumbMode);
- value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
- *loc32 = setWordFromArmMov(*loc32, value16);
- break;
- case pointer32:
- if (targetIsThumb)
- *loc32 = targetAddress + ref.addend() + 1;
- else
- *loc32 = targetAddress + ref.addend();
- break;
- case delta32:
- if (targetIsThumb)
- *loc32 = targetAddress - fixupAddress + ref.addend() + 1;
- else
- *loc32 = targetAddress - fixupAddress + ref.addend();
- break;
- case lazyPointer:
- // do nothing
- break;
- case lazyImmediateLocation:
- *loc32 = ref.addend();
- break;
- case invalid:
- llvm_unreachable("invalid ARM Reference Kind");
- break;
- }
-}
-
-void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
- bool relocatable,
- FindAddressForAtom findAddress,
- FindAddressForAtom findSectionAddress,
- uint64_t imageBaseAddress,
- llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
- // Copy raw bytes.
- std::copy(atom.rawContent().begin(), atom.rawContent().end(),
- atomContentBuffer.begin());
- // Apply fix-ups.
- bool thumbMode = false;
- for (const Reference *ref : atom) {
- uint32_t offset = ref->offsetInAtom();
- const Atom *target = ref->target();
- uint64_t targetAddress = 0;
- bool targetIsThumb = false;
- if (const DefinedAtom *defTarg = dyn_cast<DefinedAtom>(target)) {
- targetAddress = findAddress(*target);
- targetIsThumb = isThumbFunction(*defTarg);
- }
- uint64_t atomAddress = findAddress(atom);
- uint64_t fixupAddress = atomAddress + offset;
- if (relocatable) {
- applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
- targetAddress, atomAddress, thumbMode,
- targetIsThumb);
- } else {
- applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
- targetAddress, atomAddress, thumbMode, targetIsThumb);
- }
- }
-}
-
-bool ArchHandler_arm::useExternalRelocationTo(const Atom &target) {
- // Undefined symbols are referenced via external relocations.
- if (isa<UndefinedAtom>(&target))
- return true;
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
- switch (defAtom->merge()) {
- case DefinedAtom::mergeAsTentative:
- // Tentative definitions are referenced via external relocations.
- return true;
- case DefinedAtom::mergeAsWeak:
- case DefinedAtom::mergeAsWeakAndAddressUsed:
- // Global weak-defs are referenced via external relocations.
- return (defAtom->scope() == DefinedAtom::scopeGlobal);
- default:
- break;
- }
- }
- // Everything else is reference via an internal relocation.
- return false;
-}
-
-void ArchHandler_arm::applyFixupRelocatable(const Reference &ref, uint8_t *loc,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress,
- bool &thumbMode,
- bool targetIsThumb) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::ARM);
- bool useExternalReloc = useExternalRelocationTo(*ref.target());
- ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
- int32_t displacement;
- uint16_t value16;
- uint32_t value32;
- bool targetIsUndef = isa<UndefinedAtom>(ref.target());
- switch (static_cast<ArmKind>(ref.kindValue())) {
- case modeThumbCode:
- thumbMode = true;
- break;
- case modeArmCode:
- thumbMode = false;
- break;
- case modeData:
- break;
- case thumb_b22:
- case thumb_bl22:
- assert(thumbMode);
- if (useExternalReloc)
- displacement = (ref.addend() - (fixupAddress + 4));
- else
- displacement = (targetAddress - (fixupAddress + 4)) + ref.addend();
- value32 = setDisplacementInThumbBranch(*loc32, fixupAddress,
- displacement,
- targetIsUndef || targetIsThumb);
- *loc32 = value32;
- break;
- case thumb_movw:
- assert(thumbMode);
- if (useExternalReloc)
- value16 = ref.addend() & 0xFFFF;
- else
- value16 = (targetAddress + ref.addend()) & 0xFFFF;
- *loc32 = setWordFromThumbMov(*loc32, value16);
- break;
- case thumb_movt:
- assert(thumbMode);
- if (useExternalReloc)
- value16 = ref.addend() >> 16;
- else
- value16 = (targetAddress + ref.addend()) >> 16;
- *loc32 = setWordFromThumbMov(*loc32, value16);
- break;
- case thumb_movw_funcRel:
- assert(thumbMode);
- value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
- *loc32 = setWordFromThumbMov(*loc32, value16);
- break;
- case thumb_movt_funcRel:
- assert(thumbMode);
- value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
- *loc32 = setWordFromThumbMov(*loc32, value16);
- break;
- case arm_b24:
- case arm_bl24:
- assert(!thumbMode);
- if (useExternalReloc)
- displacement = (ref.addend() - (fixupAddress + 8));
- else
- displacement = (targetAddress - (fixupAddress + 8)) + ref.addend();
- value32 = setDisplacementInArmBranch(*loc32, displacement,
- targetIsThumb);
- *loc32 = value32;
- break;
- case arm_movw:
- assert(!thumbMode);
- if (useExternalReloc)
- value16 = ref.addend() & 0xFFFF;
- else
- value16 = (targetAddress + ref.addend()) & 0xFFFF;
- *loc32 = setWordFromArmMov(*loc32, value16);
- break;
- case arm_movt:
- assert(!thumbMode);
- if (useExternalReloc)
- value16 = ref.addend() >> 16;
- else
- value16 = (targetAddress + ref.addend()) >> 16;
- *loc32 = setWordFromArmMov(*loc32, value16);
- break;
- case arm_movw_funcRel:
- assert(!thumbMode);
- value16 = (targetAddress - inAtomAddress + ref.addend()) & 0xFFFF;
- *loc32 = setWordFromArmMov(*loc32, value16);
- break;
- case arm_movt_funcRel:
- assert(!thumbMode);
- value16 = (targetAddress - inAtomAddress + ref.addend()) >> 16;
- *loc32 = setWordFromArmMov(*loc32, value16);
- break;
- case pointer32:
- *loc32 = targetAddress + ref.addend();
- break;
- case delta32:
- *loc32 = targetAddress - fixupAddress + ref.addend();
- break;
- case lazyPointer:
- case lazyImmediateLocation:
- // do nothing
- break;
- case invalid:
- llvm_unreachable("invalid ARM Reference Kind");
- break;
- }
-}
-
-void ArchHandler_arm::appendSectionRelocations(
- const DefinedAtom &atom,
- uint64_t atomSectionOffset,
- const Reference &ref,
- FindSymbolIndexForAtom symbolIndexForAtom,
- FindSectionIndexForAtom sectionIndexForAtom,
- FindAddressForAtom addressForAtom,
- normalized::Relocations &relocs) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::ARM);
- uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
- bool useExternalReloc = useExternalRelocationTo(*ref.target());
- uint32_t targetAtomAddress;
- uint32_t fromAtomAddress;
- uint16_t other16;
- switch (static_cast<ArmKind>(ref.kindValue())) {
- case modeThumbCode:
- case modeArmCode:
- case modeData:
- // Do nothing.
- break;
- case thumb_b22:
- case thumb_bl22:
- if (useExternalReloc) {
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM_THUMB_RELOC_BR22 | rExtern | rPcRel | rLength4);
- } else {
- if (ref.addend() != 0)
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- ARM_THUMB_RELOC_BR22 | rScattered | rPcRel | rLength4);
- else
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
- ARM_THUMB_RELOC_BR22 | rPcRel | rLength4);
- }
- break;
- case thumb_movw:
- if (useExternalReloc) {
- other16 = ref.addend() >> 16;
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM_RELOC_HALF | rExtern | rLenThmbLo);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenThmbLo);
- } else {
- targetAtomAddress = addressForAtom(*ref.target());
- if (ref.addend() != 0) {
- other16 = (targetAtomAddress + ref.addend()) >> 16;
- appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
- ARM_RELOC_HALF | rScattered | rLenThmbLo);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenThmbLo);
- } else {
- other16 = (targetAtomAddress + ref.addend()) >> 16;
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
- ARM_RELOC_HALF | rLenThmbLo);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenThmbLo);
- }
- }
- break;
- case thumb_movt:
- if (useExternalReloc) {
- other16 = ref.addend() & 0xFFFF;
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM_RELOC_HALF | rExtern | rLenThmbHi);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenThmbHi);
- } else {
- targetAtomAddress = addressForAtom(*ref.target());
- if (ref.addend() != 0) {
- other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
- appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
- ARM_RELOC_HALF | rScattered | rLenThmbHi);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenThmbHi);
- } else {
- other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
- ARM_RELOC_HALF | rLenThmbHi);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenThmbHi);
- }
- }
- break;
- case thumb_movw_funcRel:
- fromAtomAddress = addressForAtom(atom);
- targetAtomAddress = addressForAtom(*ref.target());
- other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16;
- appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
- ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbLo);
- appendReloc(relocs, other16, 0, fromAtomAddress,
- ARM_RELOC_PAIR | rScattered | rLenThmbLo);
- break;
- case thumb_movt_funcRel:
- fromAtomAddress = addressForAtom(atom);
- targetAtomAddress = addressForAtom(*ref.target());
- other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF;
- appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
- ARM_RELOC_HALF_SECTDIFF | rScattered | rLenThmbHi);
- appendReloc(relocs, other16, 0, fromAtomAddress,
- ARM_RELOC_PAIR | rScattered | rLenThmbHi);
- break;
- case arm_b24:
- case arm_bl24:
- if (useExternalReloc) {
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM_RELOC_BR24 | rExtern | rPcRel | rLength4);
- } else {
- if (ref.addend() != 0)
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- ARM_RELOC_BR24 | rScattered | rPcRel | rLength4);
- else
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
- ARM_RELOC_BR24 | rPcRel | rLength4);
- }
- break;
- case arm_movw:
- if (useExternalReloc) {
- other16 = ref.addend() >> 16;
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM_RELOC_HALF | rExtern | rLenArmLo);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenArmLo);
- } else {
- targetAtomAddress = addressForAtom(*ref.target());
- if (ref.addend() != 0) {
- other16 = (targetAtomAddress + ref.addend()) >> 16;
- appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
- ARM_RELOC_HALF | rScattered | rLenArmLo);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenArmLo);
- } else {
- other16 = (targetAtomAddress + ref.addend()) >> 16;
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
- ARM_RELOC_HALF | rLenArmLo);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenArmLo);
- }
- }
- break;
- case arm_movt:
- if (useExternalReloc) {
- other16 = ref.addend() & 0xFFFF;
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM_RELOC_HALF | rExtern | rLenArmHi);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenArmHi);
- } else {
- targetAtomAddress = addressForAtom(*ref.target());
- if (ref.addend() != 0) {
- other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
- appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
- ARM_RELOC_HALF | rScattered | rLenArmHi);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenArmHi);
- } else {
- other16 = (targetAtomAddress + ref.addend()) & 0xFFFF;
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
- ARM_RELOC_HALF | rLenArmHi);
- appendReloc(relocs, other16, 0, 0,
- ARM_RELOC_PAIR | rLenArmHi);
- }
- }
- break;
- case arm_movw_funcRel:
- fromAtomAddress = addressForAtom(atom);
- targetAtomAddress = addressForAtom(*ref.target());
- other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) >> 16;
- appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
- ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmLo);
- appendReloc(relocs, other16, 0, fromAtomAddress,
- ARM_RELOC_PAIR | rScattered | rLenArmLo);
- break;
- case arm_movt_funcRel:
- fromAtomAddress = addressForAtom(atom);
- targetAtomAddress = addressForAtom(*ref.target());
- other16 = (targetAtomAddress - fromAtomAddress + ref.addend()) & 0xFFFF;
- appendReloc(relocs, sectionOffset, 0, targetAtomAddress,
- ARM_RELOC_HALF_SECTDIFF | rScattered | rLenArmHi);
- appendReloc(relocs, other16, 0, fromAtomAddress,
- ARM_RELOC_PAIR | rScattered | rLenArmHi);
- break;
- case pointer32:
- if (useExternalReloc) {
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM_RELOC_VANILLA | rExtern | rLength4);
- }
- else {
- if (ref.addend() != 0)
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- ARM_RELOC_VANILLA | rScattered | rLength4);
- else
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
- ARM_RELOC_VANILLA | rLength4);
- }
- break;
- case delta32:
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- ARM_RELOC_SECTDIFF | rScattered | rLength4);
- appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
- ref.offsetInAtom(),
- ARM_RELOC_PAIR | rScattered | rLength4);
- break;
- case lazyPointer:
- case lazyImmediateLocation:
- // do nothing
- break;
- case invalid:
- llvm_unreachable("invalid ARM Reference Kind");
- break;
- }
-}
-
-void ArchHandler_arm::addAdditionalReferences(MachODefinedAtom &atom) {
- if (atom.isThumb()) {
- atom.addReference(Reference::KindNamespace::mach_o,
- Reference::KindArch::ARM, modeThumbCode, 0, &atom, 0);
- }
-}
-
-bool ArchHandler_arm::isThumbFunction(const DefinedAtom &atom) {
- for (const Reference *ref : atom) {
- if (ref->offsetInAtom() != 0)
- return false;
- if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
- continue;
- assert(ref->kindArch() == Reference::KindArch::ARM);
- if (ref->kindValue() == modeThumbCode)
- return true;
- }
- return false;
-}
-
-class Thumb2ToArmShimAtom : public SimpleDefinedAtom {
-public:
- Thumb2ToArmShimAtom(MachOFile &file, StringRef targetName,
- const DefinedAtom &target)
- : SimpleDefinedAtom(file) {
- addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
- ArchHandler_arm::modeThumbCode, 0, this, 0);
- addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
- ArchHandler_arm::delta32, 8, &target, 0);
- std::string name = std::string(targetName) + "$shim";
- StringRef tmp(name);
- _name = tmp.copy(file.allocator());
- }
-
- ~Thumb2ToArmShimAtom() override = default;
-
- StringRef name() const override {
- return _name;
- }
-
- ContentType contentType() const override {
- return DefinedAtom::typeCode;
- }
-
- Alignment alignment() const override { return 4; }
-
- uint64_t size() const override {
- return 12;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permR_X;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- static const uint8_t bytes[] =
- { 0xDF, 0xF8, 0x04, 0xC0, // ldr ip, pc + 4
- 0xFF, 0x44, // add ip, pc, ip
- 0x60, 0x47, // ldr pc, [ip]
- 0x00, 0x00, 0x00, 0x00 }; // .long target - this
- assert(sizeof(bytes) == size());
- return llvm::makeArrayRef(bytes, sizeof(bytes));
- }
-private:
- StringRef _name;
-};
-
-class ArmToThumbShimAtom : public SimpleDefinedAtom {
-public:
- ArmToThumbShimAtom(MachOFile &file, StringRef targetName,
- const DefinedAtom &target)
- : SimpleDefinedAtom(file) {
- addReference(Reference::KindNamespace::mach_o, Reference::KindArch::ARM,
- ArchHandler_arm::delta32, 12, &target, 0);
- std::string name = std::string(targetName) + "$shim";
- StringRef tmp(name);
- _name = tmp.copy(file.allocator());
- }
-
- ~ArmToThumbShimAtom() override = default;
-
- StringRef name() const override {
- return _name;
- }
-
- ContentType contentType() const override {
- return DefinedAtom::typeCode;
- }
-
- Alignment alignment() const override { return 4; }
-
- uint64_t size() const override {
- return 16;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permR_X;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- static const uint8_t bytes[] =
- { 0x04, 0xC0, 0x9F, 0xE5, // ldr ip, pc + 4
- 0x0C, 0xC0, 0x8F, 0xE0, // add ip, pc, ip
- 0x1C, 0xFF, 0x2F, 0xE1, // ldr pc, [ip]
- 0x00, 0x00, 0x00, 0x00 }; // .long target - this
- assert(sizeof(bytes) == size());
- return llvm::makeArrayRef(bytes, sizeof(bytes));
- }
-private:
- StringRef _name;
-};
-
-const DefinedAtom *ArchHandler_arm::createShim(MachOFile &file,
- bool thumbToArm,
- const DefinedAtom &target) {
- bool isStub = (target.contentType() == DefinedAtom::typeStub);
- StringRef targetName = isStub ? stubName(target) : target.name();
- if (thumbToArm)
- return new (file.allocator()) Thumb2ToArmShimAtom(file, targetName, target);
- else
- return new (file.allocator()) ArmToThumbShimAtom(file, targetName, target);
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm() {
- return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm());
-}
-
-} // namespace mach_o
-} // namespace lld
+++ /dev/null
-//===- lib/FileFormat/MachO/ArchHandler_arm64.cpp -------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-using llvm::support::ulittle32_t;
-using llvm::support::ulittle64_t;
-
-using llvm::support::little32_t;
-using llvm::support::little64_t;
-
-class ArchHandler_arm64 : public ArchHandler {
-public:
- ArchHandler_arm64() = default;
- ~ArchHandler_arm64() override = default;
-
- const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
-
- Reference::KindArch kindArch() override {
- return Reference::KindArch::AArch64;
- }
-
- /// Used by GOTPass to locate GOT References
- bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return false;
- assert(ref.kindArch() == Reference::KindArch::AArch64);
- switch (ref.kindValue()) {
- case gotPage21:
- case gotOffset12:
- canBypassGOT = true;
- return true;
- case delta32ToGOT:
- case unwindCIEToPersonalityFunction:
- case imageOffsetGot:
- canBypassGOT = false;
- return true;
- default:
- return false;
- }
- }
-
- /// Used by GOTPass to update GOT References.
- void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override {
- // If GOT slot was instantiated, transform:
- // gotPage21/gotOffset12 -> page21/offset12scale8
- // If GOT slot optimized away, transform:
- // gotPage21/gotOffset12 -> page21/addOffset12
- assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
- assert(ref->kindArch() == Reference::KindArch::AArch64);
- switch (ref->kindValue()) {
- case gotPage21:
- const_cast<Reference *>(ref)->setKindValue(page21);
- break;
- case gotOffset12:
- const_cast<Reference *>(ref)->setKindValue(targetNowGOT ?
- offset12scale8 : addOffset12);
- break;
- case delta32ToGOT:
- const_cast<Reference *>(ref)->setKindValue(delta32);
- break;
- case imageOffsetGot:
- const_cast<Reference *>(ref)->setKindValue(imageOffset);
- break;
- default:
- llvm_unreachable("Not a GOT reference");
- }
- }
-
- const StubInfo &stubInfo() override { return _sStubInfo; }
-
- bool isCallSite(const Reference &) override;
- bool isNonCallBranch(const Reference &) override {
- return false;
- }
-
- bool isPointer(const Reference &) override;
- bool isPairedReloc(const normalized::Relocation &) override;
-
- bool needsCompactUnwind() override {
- return true;
- }
- Reference::KindValue imageOffsetKind() override {
- return imageOffset;
- }
- Reference::KindValue imageOffsetKindIndirect() override {
- return imageOffsetGot;
- }
-
- Reference::KindValue unwindRefToPersonalityFunctionKind() override {
- return unwindCIEToPersonalityFunction;
- }
-
- Reference::KindValue unwindRefToCIEKind() override {
- return negDelta32;
- }
-
- Reference::KindValue unwindRefToFunctionKind() override {
- return unwindFDEToFunction;
- }
-
- Reference::KindValue unwindRefToEhFrameKind() override {
- return unwindInfoToEhFrame;
- }
-
- Reference::KindValue pointerKind() override {
- return pointer64;
- }
-
- Reference::KindValue lazyImmediateLocationKind() override {
- return lazyImmediateLocation;
- }
-
- uint32_t dwarfCompactUnwindType() override {
- return 0x03000000;
- }
-
- llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool isBig,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
- llvm::Error
- getPairReferenceInfo(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool isBig, bool scatterable,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
-
- bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) override {
- return (atom->contentType() == DefinedAtom::typeCString);
- }
-
- void generateAtomContent(const DefinedAtom &atom, bool relocatable,
- FindAddressForAtom findAddress,
- FindAddressForAtom findSectionAddress,
- uint64_t imageBaseAddress,
- llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
-
- void appendSectionRelocations(const DefinedAtom &atom,
- uint64_t atomSectionOffset,
- const Reference &ref,
- FindSymbolIndexForAtom symbolIndexForAtom,
- FindSectionIndexForAtom sectionIndexForAtom,
- FindAddressForAtom addressForAtom,
- normalized::Relocations &relocs) override;
-
-private:
- static const Registry::KindStrings _sKindStrings[];
- static const StubInfo _sStubInfo;
-
- enum Arm64Kind : Reference::KindValue {
- invalid, /// for error condition
-
- // Kinds found in mach-o .o files:
- branch26, /// ex: bl _foo
- page21, /// ex: adrp x1, _foo@PAGE
- offset12, /// ex: ldrb w0, [x1, _foo@PAGEOFF]
- offset12scale2, /// ex: ldrs w0, [x1, _foo@PAGEOFF]
- offset12scale4, /// ex: ldr w0, [x1, _foo@PAGEOFF]
- offset12scale8, /// ex: ldr x0, [x1, _foo@PAGEOFF]
- offset12scale16, /// ex: ldr q0, [x1, _foo@PAGEOFF]
- gotPage21, /// ex: adrp x1, _foo@GOTPAGE
- gotOffset12, /// ex: ldr w0, [x1, _foo@GOTPAGEOFF]
- tlvPage21, /// ex: adrp x1, _foo@TLVPAGE
- tlvOffset12, /// ex: ldr w0, [x1, _foo@TLVPAGEOFF]
-
- pointer64, /// ex: .quad _foo
- delta64, /// ex: .quad _foo - .
- delta32, /// ex: .long _foo - .
- negDelta32, /// ex: .long . - _foo
- pointer64ToGOT, /// ex: .quad _foo@GOT
- delta32ToGOT, /// ex: .long _foo@GOT - .
-
- // Kinds introduced by Passes:
- addOffset12, /// Location contains LDR to change into ADD.
- lazyPointer, /// Location contains a lazy pointer.
- lazyImmediateLocation, /// Location contains immediate value used in stub.
- imageOffset, /// Location contains offset of atom in final image
- imageOffsetGot, /// Location contains offset of GOT entry for atom in
- /// final image (typically personality function).
- unwindCIEToPersonalityFunction, /// Nearly delta32ToGOT, but cannot be
- /// rematerialized in relocatable object
- /// (yay for implicit contracts!).
- unwindFDEToFunction, /// Nearly delta64, but cannot be rematerialized in
- /// relocatable object (yay for implicit contracts!).
- unwindInfoToEhFrame, /// Fix low 24 bits of compact unwind encoding to
- /// refer to __eh_frame entry.
- };
-
- void applyFixupFinal(const Reference &ref, uint8_t *location,
- uint64_t fixupAddress, uint64_t targetAddress,
- uint64_t inAtomAddress, uint64_t imageBaseAddress,
- FindAddressForAtom findSectionAddress);
-
- void applyFixupRelocatable(const Reference &ref, uint8_t *location,
- uint64_t fixupAddress, uint64_t targetAddress,
- uint64_t inAtomAddress, bool targetUnnamed);
-
- // Utility functions for inspecting/updating instructions.
- static uint32_t setDisplacementInBranch26(uint32_t instr, int32_t disp);
- static uint32_t setDisplacementInADRP(uint32_t instr, int64_t disp);
- static Arm64Kind offset12KindFromInstruction(uint32_t instr);
- static uint32_t setImm12(uint32_t instr, uint32_t offset);
-};
-
-const Registry::KindStrings ArchHandler_arm64::_sKindStrings[] = {
- LLD_KIND_STRING_ENTRY(invalid),
- LLD_KIND_STRING_ENTRY(branch26),
- LLD_KIND_STRING_ENTRY(page21),
- LLD_KIND_STRING_ENTRY(offset12),
- LLD_KIND_STRING_ENTRY(offset12scale2),
- LLD_KIND_STRING_ENTRY(offset12scale4),
- LLD_KIND_STRING_ENTRY(offset12scale8),
- LLD_KIND_STRING_ENTRY(offset12scale16),
- LLD_KIND_STRING_ENTRY(gotPage21),
- LLD_KIND_STRING_ENTRY(gotOffset12),
- LLD_KIND_STRING_ENTRY(tlvPage21),
- LLD_KIND_STRING_ENTRY(tlvOffset12),
- LLD_KIND_STRING_ENTRY(pointer64),
- LLD_KIND_STRING_ENTRY(delta64),
- LLD_KIND_STRING_ENTRY(delta32),
- LLD_KIND_STRING_ENTRY(negDelta32),
- LLD_KIND_STRING_ENTRY(pointer64ToGOT),
- LLD_KIND_STRING_ENTRY(delta32ToGOT),
-
- LLD_KIND_STRING_ENTRY(addOffset12),
- LLD_KIND_STRING_ENTRY(lazyPointer),
- LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
- LLD_KIND_STRING_ENTRY(imageOffset),
- LLD_KIND_STRING_ENTRY(imageOffsetGot),
- LLD_KIND_STRING_ENTRY(unwindCIEToPersonalityFunction),
- LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
- LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
-
- LLD_KIND_STRING_END
-};
-
-const ArchHandler::StubInfo ArchHandler_arm64::_sStubInfo = {
- "dyld_stub_binder",
-
- // Lazy pointer references
- { Reference::KindArch::AArch64, pointer64, 0, 0 },
- { Reference::KindArch::AArch64, lazyPointer, 0, 0 },
-
- // GOT pointer to dyld_stub_binder
- { Reference::KindArch::AArch64, pointer64, 0, 0 },
-
- // arm64 code alignment 2^1
- 1,
-
- // Stub size and code
- 12,
- { 0x10, 0x00, 0x00, 0x90, // ADRP X16, lazy_pointer@page
- 0x10, 0x02, 0x40, 0xF9, // LDR X16, [X16, lazy_pointer@pageoff]
- 0x00, 0x02, 0x1F, 0xD6 }, // BR X16
- { Reference::KindArch::AArch64, page21, 0, 0 },
- { true, offset12scale8, 4, 0 },
-
- // Stub Helper size and code
- 12,
- { 0x50, 0x00, 0x00, 0x18, // LDR W16, L0
- 0x00, 0x00, 0x00, 0x14, // LDR B helperhelper
- 0x00, 0x00, 0x00, 0x00 }, // L0: .long 0
- { Reference::KindArch::AArch64, lazyImmediateLocation, 8, 0 },
- { Reference::KindArch::AArch64, branch26, 4, 0 },
-
- // Stub helper image cache content type
- DefinedAtom::typeGOT,
-
- // Stub Helper-Common size and code
- 24,
- // Stub helper alignment
- 2,
- { 0x11, 0x00, 0x00, 0x90, // ADRP X17, dyld_ImageLoaderCache@page
- 0x31, 0x02, 0x00, 0x91, // ADD X17, X17, dyld_ImageLoaderCache@pageoff
- 0xF0, 0x47, 0xBF, 0xA9, // STP X16/X17, [SP, #-16]!
- 0x10, 0x00, 0x00, 0x90, // ADRP X16, _fast_lazy_bind@page
- 0x10, 0x02, 0x40, 0xF9, // LDR X16, [X16,_fast_lazy_bind@pageoff]
- 0x00, 0x02, 0x1F, 0xD6 }, // BR X16
- { Reference::KindArch::AArch64, page21, 0, 0 },
- { true, offset12, 4, 0 },
- { Reference::KindArch::AArch64, page21, 12, 0 },
- { true, offset12scale8, 16, 0 }
-};
-
-bool ArchHandler_arm64::isCallSite(const Reference &ref) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return false;
- assert(ref.kindArch() == Reference::KindArch::AArch64);
- return (ref.kindValue() == branch26);
-}
-
-bool ArchHandler_arm64::isPointer(const Reference &ref) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return false;
- assert(ref.kindArch() == Reference::KindArch::AArch64);
- Reference::KindValue kind = ref.kindValue();
- return (kind == pointer64);
-}
-
-bool ArchHandler_arm64::isPairedReloc(const Relocation &r) {
- return ((r.type == ARM64_RELOC_ADDEND) || (r.type == ARM64_RELOC_SUBTRACTOR));
-}
-
-uint32_t ArchHandler_arm64::setDisplacementInBranch26(uint32_t instr,
- int32_t displacement) {
- assert((displacement <= 134217727) && (displacement > (-134217728)) &&
- "arm64 branch out of range");
- return (instr & 0xFC000000) | ((uint32_t)(displacement >> 2) & 0x03FFFFFF);
-}
-
-uint32_t ArchHandler_arm64::setDisplacementInADRP(uint32_t instruction,
- int64_t displacement) {
- assert((displacement <= 0x100000000LL) && (displacement > (-0x100000000LL)) &&
- "arm64 ADRP out of range");
- assert(((instruction & 0x9F000000) == 0x90000000) &&
- "reloc not on ADRP instruction");
- uint32_t immhi = (displacement >> 9) & (0x00FFFFE0);
- uint32_t immlo = (displacement << 17) & (0x60000000);
- return (instruction & 0x9F00001F) | immlo | immhi;
-}
-
-ArchHandler_arm64::Arm64Kind
-ArchHandler_arm64::offset12KindFromInstruction(uint32_t instruction) {
- if (instruction & 0x08000000) {
- switch ((instruction >> 30) & 0x3) {
- case 0:
- if ((instruction & 0x04800000) == 0x04800000)
- return offset12scale16;
- return offset12;
- case 1:
- return offset12scale2;
- case 2:
- return offset12scale4;
- case 3:
- return offset12scale8;
- }
- }
- return offset12;
-}
-
-uint32_t ArchHandler_arm64::setImm12(uint32_t instruction, uint32_t offset) {
- assert(((offset & 0xFFFFF000) == 0) && "imm12 offset out of range");
- uint32_t imm12 = offset << 10;
- return (instruction & 0xFFC003FF) | imm12;
-}
-
-llvm::Error ArchHandler_arm64::getReferenceInfo(
- const Relocation &reloc, const DefinedAtom *inAtom, uint32_t offsetInAtom,
- uint64_t fixupAddress, bool isBig,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
- const lld::Atom **target, Reference::Addend *addend) {
- const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- switch (relocPattern(reloc)) {
- case ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4:
- // ex: bl _foo
- *kind = branch26;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = 0;
- return llvm::Error::success();
- case ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4:
- // ex: adrp x1, _foo@PAGE
- *kind = page21;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = 0;
- return llvm::Error::success();
- case ARM64_RELOC_PAGEOFF12 | rExtern | rLength4:
- // ex: ldr x0, [x1, _foo@PAGEOFF]
- *kind = offset12KindFromInstruction(*(const little32_t *)fixupContent);
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = 0;
- return llvm::Error::success();
- case ARM64_RELOC_GOT_LOAD_PAGE21 | rPcRel | rExtern | rLength4:
- // ex: adrp x1, _foo@GOTPAGE
- *kind = gotPage21;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = 0;
- return llvm::Error::success();
- case ARM64_RELOC_GOT_LOAD_PAGEOFF12 | rExtern | rLength4:
- // ex: ldr x0, [x1, _foo@GOTPAGEOFF]
- *kind = gotOffset12;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = 0;
- return llvm::Error::success();
- case ARM64_RELOC_TLVP_LOAD_PAGE21 | rPcRel | rExtern | rLength4:
- // ex: adrp x1, _foo@TLVPAGE
- *kind = tlvPage21;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = 0;
- return llvm::Error::success();
- case ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4:
- // ex: ldr x0, [x1, _foo@TLVPAGEOFF]
- *kind = tlvOffset12;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = 0;
- return llvm::Error::success();
- case ARM64_RELOC_UNSIGNED | rExtern | rLength8:
- // ex: .quad _foo + N
- *kind = pointer64;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = *(const little64_t *)fixupContent;
- return llvm::Error::success();
- case ARM64_RELOC_UNSIGNED | rLength8:
- // ex: .quad Lfoo + N
- *kind = pointer64;
- return atomFromAddress(reloc.symbol, *(const little64_t *)fixupContent,
- target, addend);
- case ARM64_RELOC_POINTER_TO_GOT | rExtern | rLength8:
- // ex: .quad _foo@GOT
- *kind = pointer64ToGOT;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = 0;
- return llvm::Error::success();
- case ARM64_RELOC_POINTER_TO_GOT | rPcRel | rExtern | rLength4:
- // ex: .long _foo@GOT - .
-
- // If we are in an .eh_frame section, then the kind of the relocation should
- // not be delta32ToGOT. It may instead be unwindCIEToPersonalityFunction.
- if (inAtom->contentType() == DefinedAtom::typeCFI)
- *kind = unwindCIEToPersonalityFunction;
- else
- *kind = delta32ToGOT;
-
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = 0;
- return llvm::Error::success();
- default:
- return llvm::make_error<GenericError>("unsupported arm64 relocation type");
- }
-}
-
-llvm::Error ArchHandler_arm64::getPairReferenceInfo(
- const normalized::Relocation &reloc1, const normalized::Relocation &reloc2,
- const DefinedAtom *inAtom, uint32_t offsetInAtom, uint64_t fixupAddress,
- bool swap, bool scatterable, FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex, Reference::KindValue *kind,
- const lld::Atom **target, Reference::Addend *addend) {
- const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
- case ((ARM64_RELOC_ADDEND | rLength4) << 16 |
- ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4):
- // ex: bl _foo+8
- *kind = branch26;
- if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
- return ec;
- *addend = reloc1.symbol;
- return llvm::Error::success();
- case ((ARM64_RELOC_ADDEND | rLength4) << 16 |
- ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4):
- // ex: adrp x1, _foo@PAGE
- *kind = page21;
- if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
- return ec;
- *addend = reloc1.symbol;
- return llvm::Error::success();
- case ((ARM64_RELOC_ADDEND | rLength4) << 16 |
- ARM64_RELOC_PAGEOFF12 | rExtern | rLength4): {
- // ex: ldr w0, [x1, _foo@PAGEOFF]
- uint32_t cont32 = (int32_t)*(const little32_t *)fixupContent;
- *kind = offset12KindFromInstruction(cont32);
- if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
- return ec;
- *addend = reloc1.symbol;
- return llvm::Error::success();
- }
- case ((ARM64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
- ARM64_RELOC_UNSIGNED | rExtern | rLength8):
- // ex: .quad _foo - .
- if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
- return ec;
-
- // If we are in an .eh_frame section, then the kind of the relocation should
- // not be delta64. It may instead be unwindFDEToFunction.
- if (inAtom->contentType() == DefinedAtom::typeCFI)
- *kind = unwindFDEToFunction;
- else
- *kind = delta64;
-
- // The offsets of the 2 relocations must match
- if (reloc1.offset != reloc2.offset)
- return llvm::make_error<GenericError>(
- "paired relocs must have the same offset");
- *addend = (int64_t)*(const little64_t *)fixupContent + offsetInAtom;
- return llvm::Error::success();
- case ((ARM64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
- ARM64_RELOC_UNSIGNED | rExtern | rLength4):
- // ex: .quad _foo - .
- *kind = delta32;
- if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
- return ec;
- *addend = (int32_t)*(const little32_t *)fixupContent + offsetInAtom;
- return llvm::Error::success();
- default:
- return llvm::make_error<GenericError>("unsupported arm64 relocation pair");
- }
-}
-
-void ArchHandler_arm64::generateAtomContent(
- const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
- FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
- llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
- // Copy raw bytes.
- std::copy(atom.rawContent().begin(), atom.rawContent().end(),
- atomContentBuffer.begin());
- // Apply fix-ups.
-#ifndef NDEBUG
- if (atom.begin() != atom.end()) {
- DEBUG_WITH_TYPE("atom-content", llvm::dbgs()
- << "Applying fixups to atom:\n"
- << " address="
- << llvm::format(" 0x%09lX", &atom)
- << ", file=#"
- << atom.file().ordinal()
- << ", atom=#"
- << atom.ordinal()
- << ", name="
- << atom.name()
- << ", type="
- << atom.contentType()
- << "\n");
- }
-#endif
- for (const Reference *ref : atom) {
- uint32_t offset = ref->offsetInAtom();
- const Atom *target = ref->target();
- bool targetUnnamed = target->name().empty();
- uint64_t targetAddress = 0;
- if (isa<DefinedAtom>(target))
- targetAddress = findAddress(*target);
- uint64_t atomAddress = findAddress(atom);
- uint64_t fixupAddress = atomAddress + offset;
- if (relocatable) {
- applyFixupRelocatable(*ref, &atomContentBuffer[offset], fixupAddress,
- targetAddress, atomAddress, targetUnnamed);
- } else {
- applyFixupFinal(*ref, &atomContentBuffer[offset], fixupAddress,
- targetAddress, atomAddress, imageBaseAddress,
- findSectionAddress);
- }
- }
-}
-
-void ArchHandler_arm64::applyFixupFinal(const Reference &ref, uint8_t *loc,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress,
- uint64_t imageBaseAddress,
- FindAddressForAtom findSectionAddress) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::AArch64);
- ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
- ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
- int32_t displacement;
- uint32_t instruction;
- uint32_t value32;
- uint32_t value64;
- switch (static_cast<Arm64Kind>(ref.kindValue())) {
- case branch26:
- displacement = (targetAddress - fixupAddress) + ref.addend();
- *loc32 = setDisplacementInBranch26(*loc32, displacement);
- return;
- case page21:
- case gotPage21:
- case tlvPage21:
- displacement =
- ((targetAddress + ref.addend()) & (-4096)) - (fixupAddress & (-4096));
- *loc32 = setDisplacementInADRP(*loc32, displacement);
- return;
- case offset12:
- case gotOffset12:
- case tlvOffset12:
- displacement = (targetAddress + ref.addend()) & 0x00000FFF;
- *loc32 = setImm12(*loc32, displacement);
- return;
- case offset12scale2:
- displacement = (targetAddress + ref.addend()) & 0x00000FFF;
- assert(((displacement & 0x1) == 0) &&
- "scaled imm12 not accessing 2-byte aligneds");
- *loc32 = setImm12(*loc32, displacement >> 1);
- return;
- case offset12scale4:
- displacement = (targetAddress + ref.addend()) & 0x00000FFF;
- assert(((displacement & 0x3) == 0) &&
- "scaled imm12 not accessing 4-byte aligned");
- *loc32 = setImm12(*loc32, displacement >> 2);
- return;
- case offset12scale8:
- displacement = (targetAddress + ref.addend()) & 0x00000FFF;
- assert(((displacement & 0x7) == 0) &&
- "scaled imm12 not accessing 8-byte aligned");
- *loc32 = setImm12(*loc32, displacement >> 3);
- return;
- case offset12scale16:
- displacement = (targetAddress + ref.addend()) & 0x00000FFF;
- assert(((displacement & 0xF) == 0) &&
- "scaled imm12 not accessing 16-byte aligned");
- *loc32 = setImm12(*loc32, displacement >> 4);
- return;
- case addOffset12:
- instruction = *loc32;
- assert(((instruction & 0xFFC00000) == 0xF9400000) &&
- "GOT reloc is not an LDR instruction");
- displacement = (targetAddress + ref.addend()) & 0x00000FFF;
- value32 = 0x91000000 | (instruction & 0x000003FF);
- instruction = setImm12(value32, displacement);
- *loc32 = instruction;
- return;
- case pointer64:
- case pointer64ToGOT:
- *loc64 = targetAddress + ref.addend();
- return;
- case delta64:
- case unwindFDEToFunction:
- *loc64 = (targetAddress - fixupAddress) + ref.addend();
- return;
- case delta32:
- case delta32ToGOT:
- case unwindCIEToPersonalityFunction:
- *loc32 = (targetAddress - fixupAddress) + ref.addend();
- return;
- case negDelta32:
- *loc32 = fixupAddress - targetAddress + ref.addend();
- return;
- case lazyPointer:
- // Do nothing
- return;
- case lazyImmediateLocation:
- *loc32 = ref.addend();
- return;
- case imageOffset:
- *loc32 = (targetAddress - imageBaseAddress) + ref.addend();
- return;
- case imageOffsetGot:
- llvm_unreachable("imageOffsetGot should have been changed to imageOffset");
- break;
- case unwindInfoToEhFrame:
- value64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
- assert(value64 < 0xffffffU && "offset in __eh_frame too large");
- *loc32 = (*loc32 & 0xff000000U) | value64;
- return;
- case invalid:
- // Fall into llvm_unreachable().
- break;
- }
- llvm_unreachable("invalid arm64 Reference Kind");
-}
-
-void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
- uint8_t *loc,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress,
- bool targetUnnamed) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::AArch64);
- ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
- ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
- switch (static_cast<Arm64Kind>(ref.kindValue())) {
- case branch26:
- *loc32 = setDisplacementInBranch26(*loc32, 0);
- return;
- case page21:
- case gotPage21:
- case tlvPage21:
- *loc32 = setDisplacementInADRP(*loc32, 0);
- return;
- case offset12:
- case offset12scale2:
- case offset12scale4:
- case offset12scale8:
- case offset12scale16:
- case gotOffset12:
- case tlvOffset12:
- *loc32 = setImm12(*loc32, 0);
- return;
- case pointer64:
- if (targetUnnamed)
- *loc64 = targetAddress + ref.addend();
- else
- *loc64 = ref.addend();
- return;
- case delta64:
- *loc64 = ref.addend() + inAtomAddress - fixupAddress;
- return;
- case unwindFDEToFunction:
- // We don't emit unwindFDEToFunction in -r mode as they are implicitly
- // generated from the data in the __eh_frame section. So here we need
- // to use the targetAddress so that we can generate the full relocation
- // when we parse again later.
- *loc64 = targetAddress - fixupAddress;
- return;
- case delta32:
- *loc32 = ref.addend() + inAtomAddress - fixupAddress;
- return;
- case negDelta32:
- // We don't emit negDelta32 in -r mode as they are implicitly
- // generated from the data in the __eh_frame section. So here we need
- // to use the targetAddress so that we can generate the full relocation
- // when we parse again later.
- *loc32 = fixupAddress - targetAddress + ref.addend();
- return;
- case pointer64ToGOT:
- *loc64 = 0;
- return;
- case delta32ToGOT:
- *loc32 = inAtomAddress - fixupAddress;
- return;
- case unwindCIEToPersonalityFunction:
- // We don't emit unwindCIEToPersonalityFunction in -r mode as they are
- // implicitly generated from the data in the __eh_frame section. So here we
- // need to use the targetAddress so that we can generate the full relocation
- // when we parse again later.
- *loc32 = targetAddress - fixupAddress;
- return;
- case addOffset12:
- llvm_unreachable("lazy reference kind implies GOT pass was run");
- case lazyPointer:
- case lazyImmediateLocation:
- llvm_unreachable("lazy reference kind implies Stubs pass was run");
- case imageOffset:
- case imageOffsetGot:
- case unwindInfoToEhFrame:
- llvm_unreachable("fixup implies __unwind_info");
- return;
- case invalid:
- // Fall into llvm_unreachable().
- break;
- }
- llvm_unreachable("unknown arm64 Reference Kind");
-}
-
-void ArchHandler_arm64::appendSectionRelocations(
- const DefinedAtom &atom, uint64_t atomSectionOffset, const Reference &ref,
- FindSymbolIndexForAtom symbolIndexForAtom,
- FindSectionIndexForAtom sectionIndexForAtom,
- FindAddressForAtom addressForAtom, normalized::Relocations &relocs) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::AArch64);
- uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
- switch (static_cast<Arm64Kind>(ref.kindValue())) {
- case branch26:
- if (ref.addend()) {
- appendReloc(relocs, sectionOffset, ref.addend(), 0,
- ARM64_RELOC_ADDEND | rLength4);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4);
- } else {
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_BRANCH26 | rPcRel | rExtern | rLength4);
- }
- return;
- case page21:
- if (ref.addend()) {
- appendReloc(relocs, sectionOffset, ref.addend(), 0,
- ARM64_RELOC_ADDEND | rLength4);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4);
- } else {
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_PAGE21 | rPcRel | rExtern | rLength4);
- }
- return;
- case offset12:
- case offset12scale2:
- case offset12scale4:
- case offset12scale8:
- case offset12scale16:
- if (ref.addend()) {
- appendReloc(relocs, sectionOffset, ref.addend(), 0,
- ARM64_RELOC_ADDEND | rLength4);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_PAGEOFF12 | rExtern | rLength4);
- } else {
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_PAGEOFF12 | rExtern | rLength4);
- }
- return;
- case gotPage21:
- assert(ref.addend() == 0);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_GOT_LOAD_PAGE21 | rPcRel | rExtern | rLength4);
- return;
- case gotOffset12:
- assert(ref.addend() == 0);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_GOT_LOAD_PAGEOFF12 | rExtern | rLength4);
- return;
- case tlvPage21:
- assert(ref.addend() == 0);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_TLVP_LOAD_PAGE21 | rPcRel | rExtern | rLength4);
- return;
- case tlvOffset12:
- assert(ref.addend() == 0);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_TLVP_LOAD_PAGEOFF12 | rExtern | rLength4);
- return;
- case pointer64:
- if (ref.target()->name().empty())
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_UNSIGNED | rLength8);
- else
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_UNSIGNED | rExtern | rLength8);
- return;
- case delta64:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
- ARM64_RELOC_SUBTRACTOR | rExtern | rLength8);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_UNSIGNED | rExtern | rLength8);
- return;
- case delta32:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
- ARM64_RELOC_SUBTRACTOR | rExtern | rLength4 );
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_UNSIGNED | rExtern | rLength4 );
- return;
- case pointer64ToGOT:
- assert(ref.addend() == 0);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_POINTER_TO_GOT | rExtern | rLength8);
- return;
- case delta32ToGOT:
- assert(ref.addend() == 0);
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- ARM64_RELOC_POINTER_TO_GOT | rPcRel | rExtern | rLength4);
- return;
- case addOffset12:
- llvm_unreachable("lazy reference kind implies GOT pass was run");
- case lazyPointer:
- case lazyImmediateLocation:
- llvm_unreachable("lazy reference kind implies Stubs pass was run");
- case imageOffset:
- case imageOffsetGot:
- llvm_unreachable("deltas from mach_header can only be in final images");
- case unwindCIEToPersonalityFunction:
- case unwindFDEToFunction:
- case unwindInfoToEhFrame:
- case negDelta32:
- // Do nothing.
- return;
- case invalid:
- // Fall into llvm_unreachable().
- break;
- }
- llvm_unreachable("unknown arm64 Reference Kind");
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm64() {
- return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm64());
-}
-
-} // namespace mach_o
-} // namespace lld
+++ /dev/null
-//===- lib/FileFormat/MachO/ArchHandler_x86.cpp ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-using llvm::support::ulittle16_t;
-using llvm::support::ulittle32_t;
-
-using llvm::support::little16_t;
-using llvm::support::little32_t;
-
-class ArchHandler_x86 : public ArchHandler {
-public:
- ArchHandler_x86() = default;
- ~ArchHandler_x86() override = default;
-
- const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
-
- Reference::KindArch kindArch() override { return Reference::KindArch::x86; }
-
- const StubInfo &stubInfo() override { return _sStubInfo; }
- bool isCallSite(const Reference &) override;
- bool isNonCallBranch(const Reference &) override {
- return false;
- }
-
- bool isPointer(const Reference &) override;
- bool isPairedReloc(const normalized::Relocation &) override;
-
- bool needsCompactUnwind() override {
- return false;
- }
-
- Reference::KindValue imageOffsetKind() override {
- return invalid;
- }
-
- Reference::KindValue imageOffsetKindIndirect() override {
- return invalid;
- }
-
- Reference::KindValue unwindRefToPersonalityFunctionKind() override {
- return invalid;
- }
-
- Reference::KindValue unwindRefToCIEKind() override {
- return negDelta32;
- }
-
- Reference::KindValue unwindRefToFunctionKind() override{
- return delta32;
- }
-
- Reference::KindValue lazyImmediateLocationKind() override {
- return lazyImmediateLocation;
- }
-
- Reference::KindValue unwindRefToEhFrameKind() override {
- return invalid;
- }
-
- Reference::KindValue pointerKind() override {
- return invalid;
- }
-
- uint32_t dwarfCompactUnwindType() override {
- return 0x04000000U;
- }
-
- llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
- llvm::Error
- getPairReferenceInfo(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap, bool scatterable,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
-
- void generateAtomContent(const DefinedAtom &atom, bool relocatable,
- FindAddressForAtom findAddress,
- FindAddressForAtom findSectionAddress,
- uint64_t imageBaseAddress,
- llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
-
- void appendSectionRelocations(const DefinedAtom &atom,
- uint64_t atomSectionOffset,
- const Reference &ref,
- FindSymbolIndexForAtom symbolIndexForAtom,
- FindSectionIndexForAtom sectionIndexForAtom,
- FindAddressForAtom addressForAtom,
- normalized::Relocations &relocs) override;
-
- bool isDataInCodeTransition(Reference::KindValue refKind) override {
- return refKind == modeCode || refKind == modeData;
- }
-
- Reference::KindValue dataInCodeTransitionStart(
- const MachODefinedAtom &atom) override {
- return modeData;
- }
-
- Reference::KindValue dataInCodeTransitionEnd(
- const MachODefinedAtom &atom) override {
- return modeCode;
- }
-
-private:
- static const Registry::KindStrings _sKindStrings[];
- static const StubInfo _sStubInfo;
-
- enum X86Kind : Reference::KindValue {
- invalid, /// for error condition
-
- modeCode, /// Content starting at this offset is code.
- modeData, /// Content starting at this offset is data.
-
- // Kinds found in mach-o .o files:
- branch32, /// ex: call _foo
- branch16, /// ex: callw _foo
- abs32, /// ex: movl _foo, %eax
- funcRel32, /// ex: movl _foo-L1(%eax), %eax
- pointer32, /// ex: .long _foo
- delta32, /// ex: .long _foo - .
- negDelta32, /// ex: .long . - _foo
-
- // Kinds introduced by Passes:
- lazyPointer, /// Location contains a lazy pointer.
- lazyImmediateLocation, /// Location contains immediate value used in stub.
- };
-
- static bool useExternalRelocationTo(const Atom &target);
-
- void applyFixupFinal(const Reference &ref, uint8_t *location,
- uint64_t fixupAddress, uint64_t targetAddress,
- uint64_t inAtomAddress);
-
- void applyFixupRelocatable(const Reference &ref, uint8_t *location,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress);
-};
-
-//===----------------------------------------------------------------------===//
-// ArchHandler_x86
-//===----------------------------------------------------------------------===//
-
-const Registry::KindStrings ArchHandler_x86::_sKindStrings[] = {
- LLD_KIND_STRING_ENTRY(invalid),
- LLD_KIND_STRING_ENTRY(modeCode),
- LLD_KIND_STRING_ENTRY(modeData),
- LLD_KIND_STRING_ENTRY(branch32),
- LLD_KIND_STRING_ENTRY(branch16),
- LLD_KIND_STRING_ENTRY(abs32),
- LLD_KIND_STRING_ENTRY(funcRel32),
- LLD_KIND_STRING_ENTRY(pointer32),
- LLD_KIND_STRING_ENTRY(delta32),
- LLD_KIND_STRING_ENTRY(negDelta32),
- LLD_KIND_STRING_ENTRY(lazyPointer),
- LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
- LLD_KIND_STRING_END
-};
-
-const ArchHandler::StubInfo ArchHandler_x86::_sStubInfo = {
- "dyld_stub_binder",
-
- // Lazy pointer references
- { Reference::KindArch::x86, pointer32, 0, 0 },
- { Reference::KindArch::x86, lazyPointer, 0, 0 },
-
- // GOT pointer to dyld_stub_binder
- { Reference::KindArch::x86, pointer32, 0, 0 },
-
- // x86 code alignment
- 1,
-
- // Stub size and code
- 6,
- { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 }, // jmp *lazyPointer
- { Reference::KindArch::x86, abs32, 2, 0 },
- { false, 0, 0, 0 },
-
- // Stub Helper size and code
- 10,
- { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $lazy-info-offset
- 0xE9, 0x00, 0x00, 0x00, 0x00 }, // jmp helperhelper
- { Reference::KindArch::x86, lazyImmediateLocation, 1, 0 },
- { Reference::KindArch::x86, branch32, 6, 0 },
-
- // Stub helper image cache content type
- DefinedAtom::typeNonLazyPointer,
-
- // Stub Helper-Common size and code
- 12,
- // Stub helper alignment
- 2,
- { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $dyld_ImageLoaderCache
- 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *_fast_lazy_bind
- 0x90 }, // nop
- { Reference::KindArch::x86, abs32, 1, 0 },
- { false, 0, 0, 0 },
- { Reference::KindArch::x86, abs32, 7, 0 },
- { false, 0, 0, 0 }
-};
-
-bool ArchHandler_x86::isCallSite(const Reference &ref) {
- return (ref.kindValue() == branch32);
-}
-
-bool ArchHandler_x86::isPointer(const Reference &ref) {
- return (ref.kindValue() == pointer32);
-}
-
-bool ArchHandler_x86::isPairedReloc(const Relocation &reloc) {
- if (!reloc.scattered)
- return false;
- return (reloc.type == GENERIC_RELOC_LOCAL_SECTDIFF) ||
- (reloc.type == GENERIC_RELOC_SECTDIFF);
-}
-
-llvm::Error
-ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) {
- DefinedAtom::ContentPermissions perms;
- const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- uint64_t targetAddress;
- switch (relocPattern(reloc)) {
- case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4:
- // ex: call _foo (and _foo undefined)
- *kind = branch32;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = fixupAddress + 4 + (int32_t)*(const little32_t *)fixupContent;
- break;
- case GENERIC_RELOC_VANILLA | rPcRel | rLength4:
- // ex: call _foo (and _foo defined)
- *kind = branch32;
- targetAddress =
- fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- break;
- case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4:
- // ex: call _foo+n (and _foo defined)
- *kind = branch32;
- targetAddress =
- fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent;
- if (auto ec = atomFromAddress(0, reloc.value, target, addend))
- return ec;
- *addend = targetAddress - reloc.value;
- break;
- case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2:
- // ex: callw _foo (and _foo undefined)
- *kind = branch16;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = fixupAddress + 2 + (int16_t)*(const little16_t *)fixupContent;
- break;
- case GENERIC_RELOC_VANILLA | rPcRel | rLength2:
- // ex: callw _foo (and _foo defined)
- *kind = branch16;
- targetAddress =
- fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- break;
- case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2:
- // ex: callw _foo+n (and _foo defined)
- *kind = branch16;
- targetAddress =
- fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent;
- if (auto ec = atomFromAddress(0, reloc.value, target, addend))
- return ec;
- *addend = targetAddress - reloc.value;
- break;
- case GENERIC_RELOC_VANILLA | rExtern | rLength4:
- // ex: movl _foo, %eax (and _foo undefined)
- // ex: .long _foo (and _foo undefined)
- perms = inAtom->permissions();
- *kind =
- ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
- : pointer32;
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = *(const ulittle32_t *)fixupContent;
- break;
- case GENERIC_RELOC_VANILLA | rLength4:
- // ex: movl _foo, %eax (and _foo defined)
- // ex: .long _foo (and _foo defined)
- perms = inAtom->permissions();
- *kind =
- ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
- : pointer32;
- targetAddress = *(const ulittle32_t *)fixupContent;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- break;
- case GENERIC_RELOC_VANILLA | rScattered | rLength4:
- // ex: .long _foo+n (and _foo defined)
- perms = inAtom->permissions();
- *kind =
- ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32
- : pointer32;
- if (auto ec = atomFromAddress(0, reloc.value, target, addend))
- return ec;
- *addend = *(const ulittle32_t *)fixupContent - reloc.value;
- break;
- default:
- return llvm::make_error<GenericError>("unsupported i386 relocation type");
- }
- return llvm::Error::success();
-}
-
-llvm::Error
-ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- bool scatterable,
- FindAtomBySectionAndAddress atomFromAddr,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) {
- const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- DefinedAtom::ContentPermissions perms = inAtom->permissions();
- uint32_t fromAddress;
- uint32_t toAddress;
- uint32_t value;
- const lld::Atom *fromTarget;
- Reference::Addend offsetInTo;
- Reference::Addend offsetInFrom;
- switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
- case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 |
- GENERIC_RELOC_PAIR | rScattered | rLength4):
- case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 |
- GENERIC_RELOC_PAIR | rScattered | rLength4):
- toAddress = reloc1.value;
- fromAddress = reloc2.value;
- value = *(const little32_t *)fixupContent;
- if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo))
- return ec;
- if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom))
- return ec;
- if (fromTarget != inAtom) {
- if (*target != inAtom)
- return llvm::make_error<GenericError>(
- "SECTDIFF relocation where neither target is in atom");
- *kind = negDelta32;
- *addend = toAddress - value - fromAddress;
- *target = fromTarget;
- } else {
- if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) {
- // SECTDIFF relocations are used in i386 codegen where the function
- // prolog does a CALL to the next instruction which POPs the return
- // address into EBX which becomes the pic-base register. The POP
- // instruction is label the used for the subtrahend in expressions.
- // The funcRel32 kind represents the 32-bit delta to some symbol from
- // the start of the function (atom) containing the funcRel32.
- *kind = funcRel32;
- uint32_t ta = fromAddress + value - toAddress;
- *addend = ta - offsetInFrom;
- } else {
- *kind = delta32;
- *addend = fromAddress + value - toAddress;
- }
- }
- return llvm::Error::success();
- break;
- default:
- return llvm::make_error<GenericError>("unsupported i386 relocation type");
- }
-}
-
-void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom,
- bool relocatable,
- FindAddressForAtom findAddress,
- FindAddressForAtom findSectionAddress,
- uint64_t imageBaseAddress,
- llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
- // Copy raw bytes.
- std::copy(atom.rawContent().begin(), atom.rawContent().end(),
- atomContentBuffer.begin());
- // Apply fix-ups.
- for (const Reference *ref : atom) {
- uint32_t offset = ref->offsetInAtom();
- const Atom *target = ref->target();
- uint64_t targetAddress = 0;
- if (isa<DefinedAtom>(target))
- targetAddress = findAddress(*target);
- uint64_t atomAddress = findAddress(atom);
- uint64_t fixupAddress = atomAddress + offset;
- if (relocatable) {
- applyFixupRelocatable(*ref, &atomContentBuffer[offset],
- fixupAddress, targetAddress,
- atomAddress);
- } else {
- applyFixupFinal(*ref, &atomContentBuffer[offset],
- fixupAddress, targetAddress,
- atomAddress);
- }
- }
-}
-
-void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *loc,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::x86);
- ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
- switch (static_cast<X86Kind>(ref.kindValue())) {
- case branch32:
- *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend();
- break;
- case branch16:
- *loc32 = (targetAddress - (fixupAddress + 2)) + ref.addend();
- break;
- case pointer32:
- case abs32:
- *loc32 = targetAddress + ref.addend();
- break;
- case funcRel32:
- *loc32 = targetAddress - inAtomAddress + ref.addend();
- break;
- case delta32:
- *loc32 = targetAddress - fixupAddress + ref.addend();
- break;
- case negDelta32:
- *loc32 = fixupAddress - targetAddress + ref.addend();
- break;
- case modeCode:
- case modeData:
- case lazyPointer:
- // do nothing
- break;
- case lazyImmediateLocation:
- *loc32 = ref.addend();
- break;
- case invalid:
- llvm_unreachable("invalid x86 Reference Kind");
- break;
- }
-}
-
-void ArchHandler_x86::applyFixupRelocatable(const Reference &ref,
- uint8_t *loc,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::x86);
- bool useExternalReloc = useExternalRelocationTo(*ref.target());
- ulittle16_t *loc16 = reinterpret_cast<ulittle16_t *>(loc);
- ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
- switch (static_cast<X86Kind>(ref.kindValue())) {
- case branch32:
- if (useExternalReloc)
- *loc32 = ref.addend() - (fixupAddress + 4);
- else
- *loc32 =(targetAddress - (fixupAddress+4)) + ref.addend();
- break;
- case branch16:
- if (useExternalReloc)
- *loc16 = ref.addend() - (fixupAddress + 2);
- else
- *loc16 = (targetAddress - (fixupAddress+2)) + ref.addend();
- break;
- case pointer32:
- case abs32:
- *loc32 = targetAddress + ref.addend();
- break;
- case funcRel32:
- *loc32 = targetAddress - inAtomAddress + ref.addend(); // FIXME
- break;
- case delta32:
- *loc32 = targetAddress - fixupAddress + ref.addend();
- break;
- case negDelta32:
- *loc32 = fixupAddress - targetAddress + ref.addend();
- break;
- case modeCode:
- case modeData:
- case lazyPointer:
- case lazyImmediateLocation:
- // do nothing
- break;
- case invalid:
- llvm_unreachable("invalid x86 Reference Kind");
- break;
- }
-}
-
-bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) {
- // Undefined symbols are referenced via external relocations.
- if (isa<UndefinedAtom>(&target))
- return true;
- if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) {
- switch (defAtom->merge()) {
- case DefinedAtom::mergeAsTentative:
- // Tentative definitions are referenced via external relocations.
- return true;
- case DefinedAtom::mergeAsWeak:
- case DefinedAtom::mergeAsWeakAndAddressUsed:
- // Global weak-defs are referenced via external relocations.
- return (defAtom->scope() == DefinedAtom::scopeGlobal);
- default:
- break;
- }
- }
- // Everything else is reference via an internal relocation.
- return false;
-}
-
-void ArchHandler_x86::appendSectionRelocations(
- const DefinedAtom &atom,
- uint64_t atomSectionOffset,
- const Reference &ref,
- FindSymbolIndexForAtom symbolIndexForAtom,
- FindSectionIndexForAtom sectionIndexForAtom,
- FindAddressForAtom addressForAtom,
- normalized::Relocations &relocs) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::x86);
- uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
- bool useExternalReloc = useExternalRelocationTo(*ref.target());
- switch (static_cast<X86Kind>(ref.kindValue())) {
- case modeCode:
- case modeData:
- break;
- case branch32:
- if (useExternalReloc) {
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength4);
- } else {
- if (ref.addend() != 0)
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4);
- else
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
- GENERIC_RELOC_VANILLA | rPcRel | rLength4);
- }
- break;
- case branch16:
- if (useExternalReloc) {
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength2);
- } else {
- if (ref.addend() != 0)
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2);
- else
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0,
- GENERIC_RELOC_VANILLA | rPcRel | rLength2);
- }
- break;
- case pointer32:
- case abs32:
- if (useExternalReloc)
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- GENERIC_RELOC_VANILLA | rExtern | rLength4);
- else {
- if (ref.addend() != 0)
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- GENERIC_RELOC_VANILLA | rScattered | rLength4);
- else
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- GENERIC_RELOC_VANILLA | rLength4);
- }
- break;
- case funcRel32:
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
- appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(),
- GENERIC_RELOC_PAIR | rScattered | rLength4);
- break;
- case delta32:
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
- appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
- ref.offsetInAtom(),
- GENERIC_RELOC_PAIR | rScattered | rLength4);
- break;
- case negDelta32:
- appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) +
- ref.offsetInAtom(),
- GENERIC_RELOC_SECTDIFF | rScattered | rLength4);
- appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()),
- GENERIC_RELOC_PAIR | rScattered | rLength4);
- break;
- case lazyPointer:
- case lazyImmediateLocation:
- llvm_unreachable("lazy reference kind implies Stubs pass was run");
- break;
- case invalid:
- llvm_unreachable("unknown x86 Reference Kind");
- break;
- }
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86() {
- return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86());
-}
-
-} // namespace mach_o
-} // namespace lld
+++ /dev/null
-//===- lib/FileFormat/MachO/ArchHandler_x86_64.cpp ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-namespace lld {
-namespace mach_o {
-
-using llvm::support::ulittle32_t;
-using llvm::support::ulittle64_t;
-
-using llvm::support::little32_t;
-using llvm::support::little64_t;
-
-class ArchHandler_x86_64 : public ArchHandler {
-public:
- ArchHandler_x86_64() = default;
- ~ArchHandler_x86_64() override = default;
-
- const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
-
- Reference::KindArch kindArch() override {
- return Reference::KindArch::x86_64;
- }
-
- /// Used by GOTPass to locate GOT References
- bool isGOTAccess(const Reference &ref, bool &canBypassGOT) override {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return false;
- assert(ref.kindArch() == Reference::KindArch::x86_64);
- switch (ref.kindValue()) {
- case ripRel32GotLoad:
- canBypassGOT = true;
- return true;
- case ripRel32Got:
- canBypassGOT = false;
- return true;
- case imageOffsetGot:
- canBypassGOT = false;
- return true;
- default:
- return false;
- }
- }
-
- bool isTLVAccess(const Reference &ref) const override {
- assert(ref.kindNamespace() == Reference::KindNamespace::mach_o);
- assert(ref.kindArch() == Reference::KindArch::x86_64);
- return ref.kindValue() == ripRel32Tlv;
- }
-
- void updateReferenceToTLV(const Reference *ref) override {
- assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
- assert(ref->kindArch() == Reference::KindArch::x86_64);
- assert(ref->kindValue() == ripRel32Tlv);
- const_cast<Reference*>(ref)->setKindValue(ripRel32);
- }
-
- /// Used by GOTPass to update GOT References
- void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override {
- assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
- assert(ref->kindArch() == Reference::KindArch::x86_64);
-
- switch (ref->kindValue()) {
- case ripRel32Got:
- assert(targetNowGOT && "target must be GOT");
- LLVM_FALLTHROUGH;
- case ripRel32GotLoad:
- const_cast<Reference *>(ref)
- ->setKindValue(targetNowGOT ? ripRel32 : ripRel32GotLoadNowLea);
- break;
- case imageOffsetGot:
- const_cast<Reference *>(ref)->setKindValue(imageOffset);
- break;
- default:
- llvm_unreachable("unknown GOT reference kind");
- }
- }
-
- bool needsCompactUnwind() override {
- return true;
- }
-
- Reference::KindValue imageOffsetKind() override {
- return imageOffset;
- }
-
- Reference::KindValue imageOffsetKindIndirect() override {
- return imageOffsetGot;
- }
-
- Reference::KindValue unwindRefToPersonalityFunctionKind() override {
- return ripRel32Got;
- }
-
- Reference::KindValue unwindRefToCIEKind() override {
- return negDelta32;
- }
-
- Reference::KindValue unwindRefToFunctionKind() override{
- return unwindFDEToFunction;
- }
-
- Reference::KindValue lazyImmediateLocationKind() override {
- return lazyImmediateLocation;
- }
-
- Reference::KindValue unwindRefToEhFrameKind() override {
- return unwindInfoToEhFrame;
- }
-
- Reference::KindValue pointerKind() override {
- return pointer64;
- }
-
- uint32_t dwarfCompactUnwindType() override {
- return 0x04000000U;
- }
-
- const StubInfo &stubInfo() override { return _sStubInfo; }
-
- bool isNonCallBranch(const Reference &) override {
- return false;
- }
-
- bool isCallSite(const Reference &) override;
- bool isPointer(const Reference &) override;
- bool isPairedReloc(const normalized::Relocation &) override;
-
- llvm::Error getReferenceInfo(const normalized::Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
- llvm::Error
- getPairReferenceInfo(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap, bool scatterable,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) override;
-
- bool needsLocalSymbolInRelocatableFile(const DefinedAtom *atom) override {
- return (atom->contentType() == DefinedAtom::typeCString);
- }
-
- void generateAtomContent(const DefinedAtom &atom, bool relocatable,
- FindAddressForAtom findAddress,
- FindAddressForAtom findSectionAddress,
- uint64_t imageBase,
- llvm::MutableArrayRef<uint8_t> atomContentBuffer) override;
-
- void appendSectionRelocations(const DefinedAtom &atom,
- uint64_t atomSectionOffset,
- const Reference &ref,
- FindSymbolIndexForAtom symbolIndexForAtom,
- FindSectionIndexForAtom sectionIndexForAtom,
- FindAddressForAtom addressForAtom,
- normalized::Relocations &relocs) override;
-
- bool isDataInCodeTransition(Reference::KindValue refKind) override {
- return refKind == modeCode || refKind == modeData;
- }
-
- Reference::KindValue dataInCodeTransitionStart(
- const MachODefinedAtom &atom) override {
- return modeData;
- }
-
- Reference::KindValue dataInCodeTransitionEnd(
- const MachODefinedAtom &atom) override {
- return modeCode;
- }
-
-private:
- static const Registry::KindStrings _sKindStrings[];
- static const StubInfo _sStubInfo;
-
- enum X86_64Kind: Reference::KindValue {
- invalid, /// for error condition
-
- modeCode, /// Content starting at this offset is code.
- modeData, /// Content starting at this offset is data.
-
- // Kinds found in mach-o .o files:
- branch32, /// ex: call _foo
- ripRel32, /// ex: movq _foo(%rip), %rax
- ripRel32Minus1, /// ex: movb $0x12, _foo(%rip)
- ripRel32Minus2, /// ex: movw $0x1234, _foo(%rip)
- ripRel32Minus4, /// ex: movl $0x12345678, _foo(%rip)
- ripRel32Anon, /// ex: movq L1(%rip), %rax
- ripRel32Minus1Anon, /// ex: movb $0x12, L1(%rip)
- ripRel32Minus2Anon, /// ex: movw $0x1234, L1(%rip)
- ripRel32Minus4Anon, /// ex: movw $0x12345678, L1(%rip)
- ripRel32GotLoad, /// ex: movq _foo@GOTPCREL(%rip), %rax
- ripRel32Got, /// ex: pushq _foo@GOTPCREL(%rip)
- ripRel32Tlv, /// ex: movq _foo@TLVP(%rip), %rdi
- pointer64, /// ex: .quad _foo
- pointer64Anon, /// ex: .quad L1
- delta64, /// ex: .quad _foo - .
- delta32, /// ex: .long _foo - .
- delta64Anon, /// ex: .quad L1 - .
- delta32Anon, /// ex: .long L1 - .
- negDelta64, /// ex: .quad . - _foo
- negDelta32, /// ex: .long . - _foo
-
- // Kinds introduced by Passes:
- ripRel32GotLoadNowLea, /// Target of GOT load is in linkage unit so
- /// "movq _foo@GOTPCREL(%rip), %rax" can be changed
- /// to "leaq _foo(%rip), %rax
- lazyPointer, /// Location contains a lazy pointer.
- lazyImmediateLocation, /// Location contains immediate value used in stub.
-
- imageOffset, /// Location contains offset of atom in final image
- imageOffsetGot, /// Location contains offset of GOT entry for atom in
- /// final image (typically personality function).
- unwindFDEToFunction, /// Nearly delta64, but cannot be rematerialized in
- /// relocatable object (yay for implicit contracts!).
- unwindInfoToEhFrame, /// Fix low 24 bits of compact unwind encoding to
- /// refer to __eh_frame entry.
- tlvInitSectionOffset /// Location contains offset tlv init-value atom
- /// within the __thread_data section.
- };
-
- Reference::KindValue kindFromReloc(const normalized::Relocation &reloc);
-
- void applyFixupFinal(const Reference &ref, uint8_t *location,
- uint64_t fixupAddress, uint64_t targetAddress,
- uint64_t inAtomAddress, uint64_t imageBaseAddress,
- FindAddressForAtom findSectionAddress);
-
- void applyFixupRelocatable(const Reference &ref, uint8_t *location,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress);
-};
-
-const Registry::KindStrings ArchHandler_x86_64::_sKindStrings[] = {
- LLD_KIND_STRING_ENTRY(invalid),
- LLD_KIND_STRING_ENTRY(modeCode),
- LLD_KIND_STRING_ENTRY(modeData),
- LLD_KIND_STRING_ENTRY(branch32),
- LLD_KIND_STRING_ENTRY(ripRel32),
- LLD_KIND_STRING_ENTRY(ripRel32Minus1),
- LLD_KIND_STRING_ENTRY(ripRel32Minus2),
- LLD_KIND_STRING_ENTRY(ripRel32Minus4),
- LLD_KIND_STRING_ENTRY(ripRel32Anon),
- LLD_KIND_STRING_ENTRY(ripRel32Minus1Anon),
- LLD_KIND_STRING_ENTRY(ripRel32Minus2Anon),
- LLD_KIND_STRING_ENTRY(ripRel32Minus4Anon),
- LLD_KIND_STRING_ENTRY(ripRel32GotLoad),
- LLD_KIND_STRING_ENTRY(ripRel32GotLoadNowLea),
- LLD_KIND_STRING_ENTRY(ripRel32Got),
- LLD_KIND_STRING_ENTRY(ripRel32Tlv),
- LLD_KIND_STRING_ENTRY(lazyPointer),
- LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
- LLD_KIND_STRING_ENTRY(pointer64),
- LLD_KIND_STRING_ENTRY(pointer64Anon),
- LLD_KIND_STRING_ENTRY(delta32),
- LLD_KIND_STRING_ENTRY(delta64),
- LLD_KIND_STRING_ENTRY(delta32Anon),
- LLD_KIND_STRING_ENTRY(delta64Anon),
- LLD_KIND_STRING_ENTRY(negDelta64),
- LLD_KIND_STRING_ENTRY(negDelta32),
- LLD_KIND_STRING_ENTRY(imageOffset),
- LLD_KIND_STRING_ENTRY(imageOffsetGot),
- LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
- LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
- LLD_KIND_STRING_ENTRY(tlvInitSectionOffset),
- LLD_KIND_STRING_END
-};
-
-const ArchHandler::StubInfo ArchHandler_x86_64::_sStubInfo = {
- "dyld_stub_binder",
-
- // Lazy pointer references
- { Reference::KindArch::x86_64, pointer64, 0, 0 },
- { Reference::KindArch::x86_64, lazyPointer, 0, 0 },
-
- // GOT pointer to dyld_stub_binder
- { Reference::KindArch::x86_64, pointer64, 0, 0 },
-
- // x86_64 code alignment 2^1
- 1,
-
- // Stub size and code
- 6,
- { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 }, // jmp *lazyPointer
- { Reference::KindArch::x86_64, ripRel32, 2, 0 },
- { false, 0, 0, 0 },
-
- // Stub Helper size and code
- 10,
- { 0x68, 0x00, 0x00, 0x00, 0x00, // pushq $lazy-info-offset
- 0xE9, 0x00, 0x00, 0x00, 0x00 }, // jmp helperhelper
- { Reference::KindArch::x86_64, lazyImmediateLocation, 1, 0 },
- { Reference::KindArch::x86_64, branch32, 6, 0 },
-
- // Stub helper image cache content type
- DefinedAtom::typeNonLazyPointer,
-
- // Stub Helper-Common size and code
- 16,
- // Stub helper alignment
- 2,
- { 0x4C, 0x8D, 0x1D, 0x00, 0x00, 0x00, 0x00, // leaq cache(%rip),%r11
- 0x41, 0x53, // push %r11
- 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *binder(%rip)
- 0x90 }, // nop
- { Reference::KindArch::x86_64, ripRel32, 3, 0 },
- { false, 0, 0, 0 },
- { Reference::KindArch::x86_64, ripRel32, 11, 0 },
- { false, 0, 0, 0 }
-
-};
-
-bool ArchHandler_x86_64::isCallSite(const Reference &ref) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return false;
- assert(ref.kindArch() == Reference::KindArch::x86_64);
- return (ref.kindValue() == branch32);
-}
-
-bool ArchHandler_x86_64::isPointer(const Reference &ref) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return false;
- assert(ref.kindArch() == Reference::KindArch::x86_64);
- Reference::KindValue kind = ref.kindValue();
- return (kind == pointer64 || kind == pointer64Anon);
-}
-
-bool ArchHandler_x86_64::isPairedReloc(const Relocation &reloc) {
- return (reloc.type == X86_64_RELOC_SUBTRACTOR);
-}
-
-Reference::KindValue
-ArchHandler_x86_64::kindFromReloc(const Relocation &reloc) {
- switch(relocPattern(reloc)) {
- case X86_64_RELOC_BRANCH | rPcRel | rExtern | rLength4:
- return branch32;
- case X86_64_RELOC_SIGNED | rPcRel | rExtern | rLength4:
- return ripRel32;
- case X86_64_RELOC_SIGNED | rPcRel | rLength4:
- return ripRel32Anon;
- case X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4:
- return ripRel32Minus1;
- case X86_64_RELOC_SIGNED_1 | rPcRel | rLength4:
- return ripRel32Minus1Anon;
- case X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4:
- return ripRel32Minus2;
- case X86_64_RELOC_SIGNED_2 | rPcRel | rLength4:
- return ripRel32Minus2Anon;
- case X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4:
- return ripRel32Minus4;
- case X86_64_RELOC_SIGNED_4 | rPcRel | rLength4:
- return ripRel32Minus4Anon;
- case X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4:
- return ripRel32GotLoad;
- case X86_64_RELOC_GOT | rPcRel | rExtern | rLength4:
- return ripRel32Got;
- case X86_64_RELOC_TLV | rPcRel | rExtern | rLength4:
- return ripRel32Tlv;
- case X86_64_RELOC_UNSIGNED | rExtern | rLength8:
- return pointer64;
- case X86_64_RELOC_UNSIGNED | rLength8:
- return pointer64Anon;
- default:
- return invalid;
- }
-}
-
-llvm::Error
-ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) {
- *kind = kindFromReloc(reloc);
- if (*kind == invalid)
- return llvm::make_error<GenericError>("unknown type");
- const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- uint64_t targetAddress;
- switch (*kind) {
- case branch32:
- case ripRel32:
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = *(const little32_t *)fixupContent;
- return llvm::Error::success();
- case ripRel32Minus1:
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = (int32_t)*(const little32_t *)fixupContent + 1;
- return llvm::Error::success();
- case ripRel32Minus2:
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = (int32_t)*(const little32_t *)fixupContent + 2;
- return llvm::Error::success();
- case ripRel32Minus4:
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = (int32_t)*(const little32_t *)fixupContent + 4;
- return llvm::Error::success();
- case ripRel32Anon:
- targetAddress = fixupAddress + 4 + *(const little32_t *)fixupContent;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- case ripRel32Minus1Anon:
- targetAddress = fixupAddress + 5 + *(const little32_t *)fixupContent;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- case ripRel32Minus2Anon:
- targetAddress = fixupAddress + 6 + *(const little32_t *)fixupContent;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- case ripRel32Minus4Anon:
- targetAddress = fixupAddress + 8 + *(const little32_t *)fixupContent;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- case ripRel32GotLoad:
- case ripRel32Got:
- case ripRel32Tlv:
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- *addend = *(const little32_t *)fixupContent;
- return llvm::Error::success();
- case tlvInitSectionOffset:
- case pointer64:
- if (auto ec = atomFromSymbolIndex(reloc.symbol, target))
- return ec;
- // If this is the 3rd pointer of a tlv-thunk (i.e. the pointer to the TLV's
- // initial value) we need to handle it specially.
- if (inAtom->contentType() == DefinedAtom::typeThunkTLV &&
- offsetInAtom == 16) {
- *kind = tlvInitSectionOffset;
- assert(*addend == 0 && "TLV-init has non-zero addend?");
- } else
- *addend = *(const little64_t *)fixupContent;
- return llvm::Error::success();
- case pointer64Anon:
- targetAddress = *(const little64_t *)fixupContent;
- return atomFromAddress(reloc.symbol, targetAddress, target, addend);
- default:
- llvm_unreachable("bad reloc kind");
- }
-}
-
-llvm::Error
-ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
- const normalized::Relocation &reloc2,
- const DefinedAtom *inAtom,
- uint32_t offsetInAtom,
- uint64_t fixupAddress, bool swap,
- bool scatterable,
- FindAtomBySectionAndAddress atomFromAddress,
- FindAtomBySymbolIndex atomFromSymbolIndex,
- Reference::KindValue *kind,
- const lld::Atom **target,
- Reference::Addend *addend) {
- const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
- uint64_t targetAddress;
- const lld::Atom *fromTarget;
- if (auto ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget))
- return ec;
-
- switch(relocPattern(reloc1) << 16 | relocPattern(reloc2)) {
- case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
- X86_64_RELOC_UNSIGNED | rExtern | rLength8): {
- if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
- return ec;
- uint64_t encodedAddend = (int64_t)*(const little64_t *)fixupContent;
- if (inAtom == fromTarget) {
- if (inAtom->contentType() == DefinedAtom::typeCFI)
- *kind = unwindFDEToFunction;
- else
- *kind = delta64;
- *addend = encodedAddend + offsetInAtom;
- } else if (inAtom == *target) {
- *kind = negDelta64;
- *addend = encodedAddend - offsetInAtom;
- *target = fromTarget;
- } else
- return llvm::make_error<GenericError>("Invalid pointer diff");
- return llvm::Error::success();
- }
- case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
- X86_64_RELOC_UNSIGNED | rExtern | rLength4): {
- if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
- return ec;
- uint32_t encodedAddend = (int32_t)*(const little32_t *)fixupContent;
- if (inAtom == fromTarget) {
- *kind = delta32;
- *addend = encodedAddend + offsetInAtom;
- } else if (inAtom == *target) {
- *kind = negDelta32;
- *addend = encodedAddend - offsetInAtom;
- *target = fromTarget;
- } else
- return llvm::make_error<GenericError>("Invalid pointer diff");
- return llvm::Error::success();
- }
- case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength8) << 16 |
- X86_64_RELOC_UNSIGNED | rLength8):
- if (fromTarget != inAtom)
- return llvm::make_error<GenericError>("pointer diff not in base atom");
- *kind = delta64Anon;
- targetAddress = offsetInAtom + (int64_t)*(const little64_t *)fixupContent;
- return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
- case ((X86_64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
- X86_64_RELOC_UNSIGNED | rLength4):
- if (fromTarget != inAtom)
- return llvm::make_error<GenericError>("pointer diff not in base atom");
- *kind = delta32Anon;
- targetAddress = offsetInAtom + (int32_t)*(const little32_t *)fixupContent;
- return atomFromAddress(reloc2.symbol, targetAddress, target, addend);
- default:
- return llvm::make_error<GenericError>("unknown pair");
- }
-}
-
-void ArchHandler_x86_64::generateAtomContent(
- const DefinedAtom &atom, bool relocatable, FindAddressForAtom findAddress,
- FindAddressForAtom findSectionAddress, uint64_t imageBaseAddress,
- llvm::MutableArrayRef<uint8_t> atomContentBuffer) {
- // Copy raw bytes.
- std::copy(atom.rawContent().begin(), atom.rawContent().end(),
- atomContentBuffer.begin());
- // Apply fix-ups.
- for (const Reference *ref : atom) {
- uint32_t offset = ref->offsetInAtom();
- const Atom *target = ref->target();
- uint64_t targetAddress = 0;
- if (isa<DefinedAtom>(target))
- targetAddress = findAddress(*target);
- uint64_t atomAddress = findAddress(atom);
- uint64_t fixupAddress = atomAddress + offset;
- if (relocatable) {
- applyFixupRelocatable(*ref, &atomContentBuffer[offset],
- fixupAddress, targetAddress,
- atomAddress);
- } else {
- applyFixupFinal(*ref, &atomContentBuffer[offset],
- fixupAddress, targetAddress,
- atomAddress, imageBaseAddress, findSectionAddress);
- }
- }
-}
-
-void ArchHandler_x86_64::applyFixupFinal(
- const Reference &ref, uint8_t *loc, uint64_t fixupAddress,
- uint64_t targetAddress, uint64_t inAtomAddress, uint64_t imageBaseAddress,
- FindAddressForAtom findSectionAddress) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::x86_64);
- ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
- ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
- switch (static_cast<X86_64Kind>(ref.kindValue())) {
- case branch32:
- case ripRel32:
- case ripRel32Anon:
- case ripRel32Got:
- case ripRel32GotLoad:
- case ripRel32Tlv:
- *loc32 = targetAddress - (fixupAddress + 4) + ref.addend();
- return;
- case pointer64:
- case pointer64Anon:
- *loc64 = targetAddress + ref.addend();
- return;
- case tlvInitSectionOffset:
- *loc64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
- return;
- case ripRel32Minus1:
- case ripRel32Minus1Anon:
- *loc32 = targetAddress - (fixupAddress + 5) + ref.addend();
- return;
- case ripRel32Minus2:
- case ripRel32Minus2Anon:
- *loc32 = targetAddress - (fixupAddress + 6) + ref.addend();
- return;
- case ripRel32Minus4:
- case ripRel32Minus4Anon:
- *loc32 = targetAddress - (fixupAddress + 8) + ref.addend();
- return;
- case delta32:
- case delta32Anon:
- *loc32 = targetAddress - fixupAddress + ref.addend();
- return;
- case delta64:
- case delta64Anon:
- case unwindFDEToFunction:
- *loc64 = targetAddress - fixupAddress + ref.addend();
- return;
- case ripRel32GotLoadNowLea:
- // Change MOVQ to LEA
- assert(loc[-2] == 0x8B);
- loc[-2] = 0x8D;
- *loc32 = targetAddress - (fixupAddress + 4) + ref.addend();
- return;
- case negDelta64:
- *loc64 = fixupAddress - targetAddress + ref.addend();
- return;
- case negDelta32:
- *loc32 = fixupAddress - targetAddress + ref.addend();
- return;
- case modeCode:
- case modeData:
- case lazyPointer:
- // Do nothing
- return;
- case lazyImmediateLocation:
- *loc32 = ref.addend();
- return;
- case imageOffset:
- case imageOffsetGot:
- *loc32 = (targetAddress - imageBaseAddress) + ref.addend();
- return;
- case unwindInfoToEhFrame: {
- uint64_t val = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
- assert(val < 0xffffffU && "offset in __eh_frame too large");
- *loc32 = (*loc32 & 0xff000000U) | val;
- return;
- }
- case invalid:
- // Fall into llvm_unreachable().
- break;
- }
- llvm_unreachable("invalid x86_64 Reference Kind");
-}
-
-void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
- uint8_t *loc,
- uint64_t fixupAddress,
- uint64_t targetAddress,
- uint64_t inAtomAddress) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::x86_64);
- ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc);
- ulittle64_t *loc64 = reinterpret_cast<ulittle64_t *>(loc);
- switch (static_cast<X86_64Kind>(ref.kindValue())) {
- case branch32:
- case ripRel32:
- case ripRel32Got:
- case ripRel32GotLoad:
- case ripRel32Tlv:
- *loc32 = ref.addend();
- return;
- case ripRel32Anon:
- *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend();
- return;
- case tlvInitSectionOffset:
- case pointer64:
- *loc64 = ref.addend();
- return;
- case pointer64Anon:
- *loc64 = targetAddress + ref.addend();
- return;
- case ripRel32Minus1:
- *loc32 = ref.addend() - 1;
- return;
- case ripRel32Minus1Anon:
- *loc32 = (targetAddress - (fixupAddress + 5)) + ref.addend();
- return;
- case ripRel32Minus2:
- *loc32 = ref.addend() - 2;
- return;
- case ripRel32Minus2Anon:
- *loc32 = (targetAddress - (fixupAddress + 6)) + ref.addend();
- return;
- case ripRel32Minus4:
- *loc32 = ref.addend() - 4;
- return;
- case ripRel32Minus4Anon:
- *loc32 = (targetAddress - (fixupAddress + 8)) + ref.addend();
- return;
- case delta32:
- *loc32 = ref.addend() + inAtomAddress - fixupAddress;
- return;
- case delta32Anon:
- // The value we write here should be the delta to the target
- // after taking in to account the difference from the fixup back to the
- // last defined label
- // ie, if we have:
- // _base: ...
- // Lfixup: .quad Ltarget - .
- // ...
- // Ltarget:
- //
- // Then we want to encode the value (Ltarget + addend) - (LFixup - _base)
- *loc32 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress);
- return;
- case delta64:
- *loc64 = ref.addend() + inAtomAddress - fixupAddress;
- return;
- case delta64Anon:
- // The value we write here should be the delta to the target
- // after taking in to account the difference from the fixup back to the
- // last defined label
- // ie, if we have:
- // _base: ...
- // Lfixup: .quad Ltarget - .
- // ...
- // Ltarget:
- //
- // Then we want to encode the value (Ltarget + addend) - (LFixup - _base)
- *loc64 = (targetAddress + ref.addend()) - (fixupAddress - inAtomAddress);
- return;
- case negDelta64:
- *loc64 = ref.addend() + fixupAddress - inAtomAddress;
- return;
- case negDelta32:
- *loc32 = ref.addend() + fixupAddress - inAtomAddress;
- return;
- case ripRel32GotLoadNowLea:
- llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
- return;
- case lazyPointer:
- case lazyImmediateLocation:
- llvm_unreachable("lazy reference kind implies Stubs pass was run");
- return;
- case imageOffset:
- case imageOffsetGot:
- case unwindInfoToEhFrame:
- llvm_unreachable("fixup implies __unwind_info");
- return;
- case modeCode:
- case modeData:
- case unwindFDEToFunction:
- // Do nothing for now
- return;
- case invalid:
- // Fall into llvm_unreachable().
- break;
- }
- llvm_unreachable("unknown x86_64 Reference Kind");
-}
-
-void ArchHandler_x86_64::appendSectionRelocations(
- const DefinedAtom &atom,
- uint64_t atomSectionOffset,
- const Reference &ref,
- FindSymbolIndexForAtom symbolIndexForAtom,
- FindSectionIndexForAtom sectionIndexForAtom,
- FindAddressForAtom addressForAtom,
- normalized::Relocations &relocs) {
- if (ref.kindNamespace() != Reference::KindNamespace::mach_o)
- return;
- assert(ref.kindArch() == Reference::KindArch::x86_64);
- uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom();
- switch (static_cast<X86_64Kind>(ref.kindValue())) {
- case modeCode:
- case modeData:
- return;
- case branch32:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_BRANCH | rPcRel | rExtern | rLength4);
- return;
- case ripRel32:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SIGNED | rPcRel | rExtern | rLength4 );
- return;
- case ripRel32Anon:
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SIGNED | rPcRel | rLength4 );
- return;
- case ripRel32Got:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_GOT | rPcRel | rExtern | rLength4 );
- return;
- case ripRel32GotLoad:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4 );
- return;
- case ripRel32Tlv:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_TLV | rPcRel | rExtern | rLength4 );
- return;
- case tlvInitSectionOffset:
- case pointer64:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_UNSIGNED | rExtern | rLength8);
- return;
- case pointer64Anon:
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_UNSIGNED | rLength8);
- return;
- case ripRel32Minus1:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4 );
- return;
- case ripRel32Minus1Anon:
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SIGNED_1 | rPcRel | rLength4 );
- return;
- case ripRel32Minus2:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4 );
- return;
- case ripRel32Minus2Anon:
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SIGNED_2 | rPcRel | rLength4 );
- return;
- case ripRel32Minus4:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4 );
- return;
- case ripRel32Minus4Anon:
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SIGNED_4 | rPcRel | rLength4 );
- return;
- case delta32:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
- X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_UNSIGNED | rExtern | rLength4 );
- return;
- case delta32Anon:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
- X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_UNSIGNED | rLength4 );
- return;
- case delta64:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
- X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_UNSIGNED | rExtern | rLength8 );
- return;
- case delta64Anon:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
- X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
- appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_UNSIGNED | rLength8 );
- return;
- case unwindFDEToFunction:
- case unwindInfoToEhFrame:
- return;
- case negDelta32:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
- X86_64_RELOC_UNSIGNED | rExtern | rLength4 );
- return;
- case negDelta64:
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SUBTRACTOR | rExtern | rLength8 );
- appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
- X86_64_RELOC_UNSIGNED | rExtern | rLength8 );
- return;
- case ripRel32GotLoadNowLea:
- llvm_unreachable("ripRel32GotLoadNowLea implies GOT pass was run");
- return;
- case lazyPointer:
- case lazyImmediateLocation:
- llvm_unreachable("lazy reference kind implies Stubs pass was run");
- return;
- case imageOffset:
- case imageOffsetGot:
- llvm_unreachable("__unwind_info references should have been resolved");
- return;
- case invalid:
- // Fall into llvm_unreachable().
- break;
- }
- llvm_unreachable("unknown x86_64 Reference Kind");
-}
-
-std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86_64() {
- return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86_64());
-}
-
-} // namespace mach_o
-} // namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/Atoms.h ---------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_ATOMS_H
-#define LLD_READER_WRITER_MACHO_ATOMS_H
-
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include <cstdint>
-#include <string>
-
-namespace lld {
-
-class File;
-
-namespace mach_o {
-
-class MachODefinedAtom : public SimpleDefinedAtom {
-public:
- MachODefinedAtom(const File &f, const StringRef name, Scope scope,
- ContentType type, Merge merge, bool thumb, bool noDeadStrip,
- const ArrayRef<uint8_t> content, Alignment align)
- : SimpleDefinedAtom(f), _name(name), _content(content),
- _align(align), _contentType(type), _scope(scope), _merge(merge),
- _thumb(thumb), _noDeadStrip(noDeadStrip) {}
-
- // Constructor for zero-fill content
- MachODefinedAtom(const File &f, const StringRef name, Scope scope,
- ContentType type, uint64_t size, bool noDeadStrip,
- Alignment align)
- : SimpleDefinedAtom(f), _name(name),
- _content(ArrayRef<uint8_t>(nullptr, size)), _align(align),
- _contentType(type), _scope(scope), _merge(mergeNo), _thumb(false),
- _noDeadStrip(noDeadStrip) {}
-
- ~MachODefinedAtom() override = default;
-
- uint64_t size() const override { return _content.size(); }
-
- ContentType contentType() const override { return _contentType; }
-
- Alignment alignment() const override { return _align; }
-
- StringRef name() const override { return _name; }
-
- Scope scope() const override { return _scope; }
-
- Merge merge() const override { return _merge; }
-
- DeadStripKind deadStrip() const override {
- if (_contentType == DefinedAtom::typeInitializerPtr)
- return deadStripNever;
- if (_contentType == DefinedAtom::typeTerminatorPtr)
- return deadStripNever;
- if (_noDeadStrip)
- return deadStripNever;
- return deadStripNormal;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- // Note: Zerofill atoms have a content pointer which is null.
- return _content;
- }
-
- bool isThumb() const { return _thumb; }
-
-private:
- const StringRef _name;
- const ArrayRef<uint8_t> _content;
- const DefinedAtom::Alignment _align;
- const ContentType _contentType;
- const Scope _scope;
- const Merge _merge;
- const bool _thumb;
- const bool _noDeadStrip;
-};
-
-class MachODefinedCustomSectionAtom : public MachODefinedAtom {
-public:
- MachODefinedCustomSectionAtom(const File &f, const StringRef name,
- Scope scope, ContentType type, Merge merge,
- bool thumb, bool noDeadStrip,
- const ArrayRef<uint8_t> content,
- StringRef sectionName, Alignment align)
- : MachODefinedAtom(f, name, scope, type, merge, thumb, noDeadStrip,
- content, align),
- _sectionName(sectionName) {}
-
- ~MachODefinedCustomSectionAtom() override = default;
-
- SectionChoice sectionChoice() const override {
- return DefinedAtom::sectionCustomRequired;
- }
-
- StringRef customSectionName() const override {
- return _sectionName;
- }
-private:
- StringRef _sectionName;
-};
-
-class MachOTentativeDefAtom : public SimpleDefinedAtom {
-public:
- MachOTentativeDefAtom(const File &f, const StringRef name, Scope scope,
- uint64_t size, DefinedAtom::Alignment align)
- : SimpleDefinedAtom(f), _name(std::string(name)), _scope(scope),
- _size(size), _align(align) {}
-
- ~MachOTentativeDefAtom() override = default;
-
- uint64_t size() const override { return _size; }
-
- Merge merge() const override { return DefinedAtom::mergeAsTentative; }
-
- ContentType contentType() const override { return DefinedAtom::typeZeroFill; }
-
- Alignment alignment() const override { return _align; }
-
- StringRef name() const override { return _name; }
-
- Scope scope() const override { return _scope; }
-
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-
-private:
- const std::string _name;
- const Scope _scope;
- const uint64_t _size;
- const DefinedAtom::Alignment _align;
-};
-
-class MachOSharedLibraryAtom : public SharedLibraryAtom {
-public:
- MachOSharedLibraryAtom(const File &file, StringRef name,
- StringRef dylibInstallName, bool weakDef)
- : SharedLibraryAtom(), _file(file), _name(name),
- _dylibInstallName(dylibInstallName) {}
- ~MachOSharedLibraryAtom() override = default;
-
- StringRef loadName() const override { return _dylibInstallName; }
-
- bool canBeNullAtRuntime() const override {
- // FIXME: this may actually be changeable. For now, all symbols are strongly
- // defined though.
- return false;
- }
-
- const File &file() const override { return _file; }
-
- StringRef name() const override { return _name; }
-
- Type type() const override {
- // Unused in MachO (I think).
- return Type::Unknown;
- }
-
- uint64_t size() const override {
- // Unused in MachO (I think)
- return 0;
- }
-
-private:
- const File &_file;
- StringRef _name;
- StringRef _dylibInstallName;
-};
-
-} // end namespace mach_o
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_ATOMS_H
+++ /dev/null
-add_lld_library(lldMachOOld
- ArchHandler.cpp
- ArchHandler_arm.cpp
- ArchHandler_arm64.cpp
- ArchHandler_x86.cpp
- ArchHandler_x86_64.cpp
- CompactUnwindPass.cpp
- GOTPass.cpp
- LayoutPass.cpp
- MachOLinkingContext.cpp
- MachONormalizedFileBinaryReader.cpp
- MachONormalizedFileBinaryWriter.cpp
- MachONormalizedFileFromAtoms.cpp
- MachONormalizedFileToAtoms.cpp
- MachONormalizedFileYAML.cpp
- ObjCPass.cpp
- ShimPass.cpp
- StubsPass.cpp
- TLVPass.cpp
- WriterMachO.cpp
-
- LINK_COMPONENTS
- DebugInfoDWARF
- Demangle
- Object
- Support
- TextAPI
-
- LINK_LIBS
- lldCommon
- lldCore
- lldYAML
- ${LLVM_PTHREAD_LIB}
- )
-
-include_directories(.)
+++ /dev/null
-//===- lib/ReaderWriter/MachO/CompactUnwindPass.cpp -------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file A pass to convert MachO's __compact_unwind sections into the final
-/// __unwind_info format used during runtime. See
-/// mach-o/compact_unwind_encoding.h for more details on the formats involved.
-///
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
-
-#define DEBUG_TYPE "macho-compact-unwind"
-
-namespace lld {
-namespace mach_o {
-
-namespace {
-struct CompactUnwindEntry {
- const Atom *rangeStart;
- const Atom *personalityFunction;
- const Atom *lsdaLocation;
- const Atom *ehFrame;
-
- uint32_t rangeLength;
-
- // There are 3 types of compact unwind entry, distinguished by the encoding
- // value: 0 indicates a function with no unwind info;
- // _archHandler.dwarfCompactUnwindType() indicates that the entry defers to
- // __eh_frame, and that the ehFrame entry will be valid; any other value is a
- // real compact unwind entry -- personalityFunction will be set and
- // lsdaLocation may be.
- uint32_t encoding;
-
- CompactUnwindEntry(const DefinedAtom *function)
- : rangeStart(function), personalityFunction(nullptr),
- lsdaLocation(nullptr), ehFrame(nullptr), rangeLength(function->size()),
- encoding(0) {}
-
- CompactUnwindEntry()
- : rangeStart(nullptr), personalityFunction(nullptr),
- lsdaLocation(nullptr), ehFrame(nullptr), rangeLength(0), encoding(0) {}
-};
-
-struct UnwindInfoPage {
- ArrayRef<CompactUnwindEntry> entries;
-};
-}
-
-class UnwindInfoAtom : public SimpleDefinedAtom {
-public:
- UnwindInfoAtom(ArchHandler &archHandler, const File &file, bool isBig,
- std::vector<const Atom *> &personalities,
- std::vector<uint32_t> &commonEncodings,
- std::vector<UnwindInfoPage> &pages, uint32_t numLSDAs)
- : SimpleDefinedAtom(file), _archHandler(archHandler),
- _commonEncodingsOffset(7 * sizeof(uint32_t)),
- _personalityArrayOffset(_commonEncodingsOffset +
- commonEncodings.size() * sizeof(uint32_t)),
- _topLevelIndexOffset(_personalityArrayOffset +
- personalities.size() * sizeof(uint32_t)),
- _lsdaIndexOffset(_topLevelIndexOffset +
- 3 * (pages.size() + 1) * sizeof(uint32_t)),
- _firstPageOffset(_lsdaIndexOffset + 2 * numLSDAs * sizeof(uint32_t)),
- _isBig(isBig) {
-
- addHeader(commonEncodings.size(), personalities.size(), pages.size());
- addCommonEncodings(commonEncodings);
- addPersonalityFunctions(personalities);
- addTopLevelIndexes(pages);
- addLSDAIndexes(pages, numLSDAs);
- addSecondLevelPages(pages);
- }
-
- ~UnwindInfoAtom() override = default;
-
- ContentType contentType() const override {
- return DefinedAtom::typeProcessedUnwindInfo;
- }
-
- Alignment alignment() const override { return 4; }
-
- uint64_t size() const override { return _contents.size(); }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permR__;
- }
-
- ArrayRef<uint8_t> rawContent() const override { return _contents; }
-
- void addHeader(uint32_t numCommon, uint32_t numPersonalities,
- uint32_t numPages) {
- using normalized::write32;
-
- uint32_t headerSize = 7 * sizeof(uint32_t);
- _contents.resize(headerSize);
-
- uint8_t *headerEntries = _contents.data();
- // version
- write32(headerEntries, 1, _isBig);
- // commonEncodingsArraySectionOffset
- write32(headerEntries + sizeof(uint32_t), _commonEncodingsOffset, _isBig);
- // commonEncodingsArrayCount
- write32(headerEntries + 2 * sizeof(uint32_t), numCommon, _isBig);
- // personalityArraySectionOffset
- write32(headerEntries + 3 * sizeof(uint32_t), _personalityArrayOffset,
- _isBig);
- // personalityArrayCount
- write32(headerEntries + 4 * sizeof(uint32_t), numPersonalities, _isBig);
- // indexSectionOffset
- write32(headerEntries + 5 * sizeof(uint32_t), _topLevelIndexOffset, _isBig);
- // indexCount
- write32(headerEntries + 6 * sizeof(uint32_t), numPages + 1, _isBig);
- }
-
- /// Add the list of common encodings to the section; this is simply an array
- /// of uint32_t compact values. Size has already been specified in the header.
- void addCommonEncodings(std::vector<uint32_t> &commonEncodings) {
- using normalized::write32;
-
- _contents.resize(_commonEncodingsOffset +
- commonEncodings.size() * sizeof(uint32_t));
- uint8_t *commonEncodingsArea =
- reinterpret_cast<uint8_t *>(_contents.data() + _commonEncodingsOffset);
-
- for (uint32_t encoding : commonEncodings) {
- write32(commonEncodingsArea, encoding, _isBig);
- commonEncodingsArea += sizeof(uint32_t);
- }
- }
-
- void addPersonalityFunctions(std::vector<const Atom *> personalities) {
- _contents.resize(_personalityArrayOffset +
- personalities.size() * sizeof(uint32_t));
-
- for (unsigned i = 0; i < personalities.size(); ++i)
- addImageReferenceIndirect(_personalityArrayOffset + i * sizeof(uint32_t),
- personalities[i]);
- }
-
- void addTopLevelIndexes(std::vector<UnwindInfoPage> &pages) {
- using normalized::write32;
-
- uint32_t numIndexes = pages.size() + 1;
- _contents.resize(_topLevelIndexOffset + numIndexes * 3 * sizeof(uint32_t));
-
- uint32_t pageLoc = _firstPageOffset;
-
- // The most difficult job here is calculating the LSDAs; everything else
- // follows fairly naturally, but we can't state where the first
- uint8_t *indexData = &_contents[_topLevelIndexOffset];
- uint32_t numLSDAs = 0;
- for (unsigned i = 0; i < pages.size(); ++i) {
- // functionOffset
- addImageReference(_topLevelIndexOffset + 3 * i * sizeof(uint32_t),
- pages[i].entries[0].rangeStart);
- // secondLevelPagesSectionOffset
- write32(indexData + (3 * i + 1) * sizeof(uint32_t), pageLoc, _isBig);
- write32(indexData + (3 * i + 2) * sizeof(uint32_t),
- _lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t), _isBig);
-
- for (auto &entry : pages[i].entries)
- if (entry.lsdaLocation)
- ++numLSDAs;
- }
-
- // Finally, write out the final sentinel index
- auto &finalEntry = pages[pages.size() - 1].entries.back();
- addImageReference(_topLevelIndexOffset +
- 3 * pages.size() * sizeof(uint32_t),
- finalEntry.rangeStart, finalEntry.rangeLength);
- // secondLevelPagesSectionOffset => 0
- write32(indexData + (3 * pages.size() + 2) * sizeof(uint32_t),
- _lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t), _isBig);
- }
-
- void addLSDAIndexes(std::vector<UnwindInfoPage> &pages, uint32_t numLSDAs) {
- _contents.resize(_lsdaIndexOffset + numLSDAs * 2 * sizeof(uint32_t));
-
- uint32_t curOffset = _lsdaIndexOffset;
- for (auto &page : pages) {
- for (auto &entry : page.entries) {
- if (!entry.lsdaLocation)
- continue;
-
- addImageReference(curOffset, entry.rangeStart);
- addImageReference(curOffset + sizeof(uint32_t), entry.lsdaLocation);
- curOffset += 2 * sizeof(uint32_t);
- }
- }
- }
-
- void addSecondLevelPages(std::vector<UnwindInfoPage> &pages) {
- for (auto &page : pages) {
- addRegularSecondLevelPage(page);
- }
- }
-
- void addRegularSecondLevelPage(const UnwindInfoPage &page) {
- uint32_t curPageOffset = _contents.size();
- const int16_t headerSize = sizeof(uint32_t) + 2 * sizeof(uint16_t);
- uint32_t curPageSize =
- headerSize + 2 * page.entries.size() * sizeof(uint32_t);
- _contents.resize(curPageOffset + curPageSize);
-
- using normalized::write32;
- using normalized::write16;
- // 2 => regular page
- write32(&_contents[curPageOffset], 2, _isBig);
- // offset of 1st entry
- write16(&_contents[curPageOffset + 4], headerSize, _isBig);
- write16(&_contents[curPageOffset + 6], page.entries.size(), _isBig);
-
- uint32_t pagePos = curPageOffset + headerSize;
- for (auto &entry : page.entries) {
- addImageReference(pagePos, entry.rangeStart);
-
- write32(_contents.data() + pagePos + sizeof(uint32_t), entry.encoding,
- _isBig);
- if ((entry.encoding & 0x0f000000U) ==
- _archHandler.dwarfCompactUnwindType())
- addEhFrameReference(pagePos + sizeof(uint32_t), entry.ehFrame);
-
- pagePos += 2 * sizeof(uint32_t);
- }
- }
-
- void addEhFrameReference(uint32_t offset, const Atom *dest,
- Reference::Addend addend = 0) {
- addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
- _archHandler.unwindRefToEhFrameKind(), offset, dest, addend);
- }
-
- void addImageReference(uint32_t offset, const Atom *dest,
- Reference::Addend addend = 0) {
- addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
- _archHandler.imageOffsetKind(), offset, dest, addend);
- }
-
- void addImageReferenceIndirect(uint32_t offset, const Atom *dest) {
- addReference(Reference::KindNamespace::mach_o, _archHandler.kindArch(),
- _archHandler.imageOffsetKindIndirect(), offset, dest, 0);
- }
-
-private:
- mach_o::ArchHandler &_archHandler;
- std::vector<uint8_t> _contents;
- uint32_t _commonEncodingsOffset;
- uint32_t _personalityArrayOffset;
- uint32_t _topLevelIndexOffset;
- uint32_t _lsdaIndexOffset;
- uint32_t _firstPageOffset;
- bool _isBig;
-};
-
-/// Pass for instantiating and optimizing GOT slots.
-///
-class CompactUnwindPass : public Pass {
-public:
- CompactUnwindPass(const MachOLinkingContext &context)
- : _ctx(context), _archHandler(_ctx.archHandler()),
- _file(*_ctx.make_file<MachOFile>("<mach-o Compact Unwind Pass>")),
- _isBig(MachOLinkingContext::isBigEndian(_ctx.arch())) {
- _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
- }
-
-private:
- llvm::Error perform(SimpleFile &mergedFile) override {
- LLVM_DEBUG(llvm::dbgs() << "MachO Compact Unwind pass\n");
-
- std::map<const Atom *, CompactUnwindEntry> unwindLocs;
- std::map<const Atom *, const Atom *> dwarfFrames;
- std::vector<const Atom *> personalities;
- uint32_t numLSDAs = 0;
-
- // First collect all __compact_unwind and __eh_frame entries, addressable by
- // the function referred to.
- collectCompactUnwindEntries(mergedFile, unwindLocs, personalities,
- numLSDAs);
-
- collectDwarfFrameEntries(mergedFile, dwarfFrames);
-
- // Skip rest of pass if no unwind info.
- if (unwindLocs.empty() && dwarfFrames.empty())
- return llvm::Error::success();
-
- // FIXME: if there are more than 4 personality functions then we need to
- // defer to DWARF info for the ones we don't put in the list. They should
- // also probably be sorted by frequency.
- assert(personalities.size() <= 4);
-
- // TODO: Find common encodings for use by compressed pages.
- std::vector<uint32_t> commonEncodings;
-
- // Now sort the entries by final address and fixup the compact encoding to
- // its final form (i.e. set personality function bits & create DWARF
- // references where needed).
- std::vector<CompactUnwindEntry> unwindInfos = createUnwindInfoEntries(
- mergedFile, unwindLocs, personalities, dwarfFrames);
-
- // Remove any unused eh-frame atoms.
- pruneUnusedEHFrames(mergedFile, unwindInfos, unwindLocs, dwarfFrames);
-
- // Finally, we can start creating pages based on these entries.
-
- LLVM_DEBUG(llvm::dbgs() << " Splitting entries into pages\n");
- // FIXME: we split the entries into pages naively: lots of 4k pages followed
- // by a small one. ld64 tried to minimize space and align them to real 4k
- // boundaries. That might be worth doing, or perhaps we could perform some
- // minor balancing for expected number of lookups.
- std::vector<UnwindInfoPage> pages;
- auto remainingInfos = llvm::makeArrayRef(unwindInfos);
- do {
- pages.push_back(UnwindInfoPage());
-
- // FIXME: we only create regular pages at the moment. These can hold up to
- // 1021 entries according to the documentation.
- unsigned entriesInPage = std::min(1021U, (unsigned)remainingInfos.size());
-
- pages.back().entries = remainingInfos.slice(0, entriesInPage);
- remainingInfos = remainingInfos.slice(entriesInPage);
-
- LLVM_DEBUG(llvm::dbgs()
- << " Page from "
- << pages.back().entries[0].rangeStart->name() << " to "
- << pages.back().entries.back().rangeStart->name() << " + "
- << llvm::format("0x%x",
- pages.back().entries.back().rangeLength)
- << " has " << entriesInPage << " entries\n");
- } while (!remainingInfos.empty());
-
- auto *unwind = new (_file.allocator())
- UnwindInfoAtom(_archHandler, _file, _isBig, personalities,
- commonEncodings, pages, numLSDAs);
- mergedFile.addAtom(*unwind);
-
- // Finally, remove all __compact_unwind atoms now that we've processed them.
- mergedFile.removeDefinedAtomsIf([](const DefinedAtom *atom) {
- return atom->contentType() == DefinedAtom::typeCompactUnwindInfo;
- });
-
- return llvm::Error::success();
- }
-
- void collectCompactUnwindEntries(
- const SimpleFile &mergedFile,
- std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
- std::vector<const Atom *> &personalities, uint32_t &numLSDAs) {
- LLVM_DEBUG(llvm::dbgs() << " Collecting __compact_unwind entries\n");
-
- for (const DefinedAtom *atom : mergedFile.defined()) {
- if (atom->contentType() != DefinedAtom::typeCompactUnwindInfo)
- continue;
-
- auto unwindEntry = extractCompactUnwindEntry(atom);
- unwindLocs.insert(std::make_pair(unwindEntry.rangeStart, unwindEntry));
-
- LLVM_DEBUG(llvm::dbgs() << " Entry for "
- << unwindEntry.rangeStart->name() << ", encoding="
- << llvm::format("0x%08x", unwindEntry.encoding));
- if (unwindEntry.personalityFunction)
- LLVM_DEBUG(llvm::dbgs()
- << ", personality="
- << unwindEntry.personalityFunction->name()
- << ", lsdaLoc=" << unwindEntry.lsdaLocation->name());
- LLVM_DEBUG(llvm::dbgs() << '\n');
-
- // Count number of LSDAs we see, since we need to know how big the index
- // will be while laying out the section.
- if (unwindEntry.lsdaLocation)
- ++numLSDAs;
-
- // Gather the personality functions now, so that they're in deterministic
- // order (derived from the DefinedAtom order).
- if (unwindEntry.personalityFunction &&
- !llvm::count(personalities, unwindEntry.personalityFunction))
- personalities.push_back(unwindEntry.personalityFunction);
- }
- }
-
- CompactUnwindEntry extractCompactUnwindEntry(const DefinedAtom *atom) {
- CompactUnwindEntry entry;
-
- for (const Reference *ref : *atom) {
- switch (ref->offsetInAtom()) {
- case 0:
- // FIXME: there could legitimately be functions with multiple encoding
- // entries. However, nothing produces them at the moment.
- assert(ref->addend() == 0 && "unexpected offset into function");
- entry.rangeStart = ref->target();
- break;
- case 0x10:
- assert(ref->addend() == 0 && "unexpected offset into personality fn");
- entry.personalityFunction = ref->target();
- break;
- case 0x18:
- assert(ref->addend() == 0 && "unexpected offset into LSDA atom");
- entry.lsdaLocation = ref->target();
- break;
- }
- }
-
- if (atom->rawContent().size() < 4 * sizeof(uint32_t))
- return entry;
-
- using normalized::read32;
- entry.rangeLength =
- read32(atom->rawContent().data() + 2 * sizeof(uint32_t), _isBig);
- entry.encoding =
- read32(atom->rawContent().data() + 3 * sizeof(uint32_t), _isBig);
- return entry;
- }
-
- void
- collectDwarfFrameEntries(const SimpleFile &mergedFile,
- std::map<const Atom *, const Atom *> &dwarfFrames) {
- for (const DefinedAtom *ehFrameAtom : mergedFile.defined()) {
- if (ehFrameAtom->contentType() != DefinedAtom::typeCFI)
- continue;
- if (ArchHandler::isDwarfCIE(_isBig, ehFrameAtom))
- continue;
-
- if (const Atom *function = _archHandler.fdeTargetFunction(ehFrameAtom))
- dwarfFrames[function] = ehFrameAtom;
- }
- }
-
- /// Every atom defined in __TEXT,__text needs an entry in the final
- /// __unwind_info section (in order). These comes from two sources:
- /// + Input __compact_unwind sections where possible (after adding the
- /// personality function offset which is only known now).
- /// + A synthesised reference to __eh_frame if there's no __compact_unwind
- /// or too many personality functions to be accommodated.
- std::vector<CompactUnwindEntry> createUnwindInfoEntries(
- const SimpleFile &mergedFile,
- const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
- const std::vector<const Atom *> &personalities,
- const std::map<const Atom *, const Atom *> &dwarfFrames) {
- std::vector<CompactUnwindEntry> unwindInfos;
-
- LLVM_DEBUG(llvm::dbgs() << " Creating __unwind_info entries\n");
- // The final order in the __unwind_info section must be derived from the
- // order of typeCode atoms, since that's how they'll be put into the object
- // file eventually (yuck!).
- for (const DefinedAtom *atom : mergedFile.defined()) {
- if (atom->contentType() != DefinedAtom::typeCode)
- continue;
-
- unwindInfos.push_back(finalizeUnwindInfoEntryForAtom(
- atom, unwindLocs, personalities, dwarfFrames));
-
- LLVM_DEBUG(llvm::dbgs()
- << " Entry for " << atom->name() << ", final encoding="
- << llvm::format("0x%08x", unwindInfos.back().encoding)
- << '\n');
- }
-
- return unwindInfos;
- }
-
- /// Remove unused EH frames.
- ///
- /// An EH frame is considered unused if there is a corresponding compact
- /// unwind atom that doesn't require the EH frame.
- void pruneUnusedEHFrames(
- SimpleFile &mergedFile,
- const std::vector<CompactUnwindEntry> &unwindInfos,
- const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
- const std::map<const Atom *, const Atom *> &dwarfFrames) {
-
- // Worklist of all 'used' FDEs.
- std::vector<const DefinedAtom *> usedDwarfWorklist;
-
- // We have to check two conditions when building the worklist:
- // (1) EH frames used by compact unwind entries.
- for (auto &entry : unwindInfos)
- if (entry.ehFrame)
- usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.ehFrame));
-
- // (2) EH frames that reference functions with no corresponding compact
- // unwind info.
- for (auto &entry : dwarfFrames)
- if (!unwindLocs.count(entry.first))
- usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.second));
-
- // Add all transitively referenced CFI atoms by processing the worklist.
- std::set<const Atom *> usedDwarfFrames;
- while (!usedDwarfWorklist.empty()) {
- const DefinedAtom *cfiAtom = usedDwarfWorklist.back();
- usedDwarfWorklist.pop_back();
- usedDwarfFrames.insert(cfiAtom);
- for (const auto *ref : *cfiAtom) {
- const DefinedAtom *cfiTarget = dyn_cast<DefinedAtom>(ref->target());
- if (cfiTarget->contentType() == DefinedAtom::typeCFI)
- usedDwarfWorklist.push_back(cfiTarget);
- }
- }
-
- // Finally, delete all unreferenced CFI atoms.
- mergedFile.removeDefinedAtomsIf([&](const DefinedAtom *atom) {
- if ((atom->contentType() == DefinedAtom::typeCFI) &&
- !usedDwarfFrames.count(atom))
- return true;
- return false;
- });
- }
-
- CompactUnwindEntry finalizeUnwindInfoEntryForAtom(
- const DefinedAtom *function,
- const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
- const std::vector<const Atom *> &personalities,
- const std::map<const Atom *, const Atom *> &dwarfFrames) {
- auto unwindLoc = unwindLocs.find(function);
-
- CompactUnwindEntry entry;
- if (unwindLoc == unwindLocs.end()) {
- // Default entry has correct encoding (0 => no unwind), but we need to
- // synthesise the function.
- entry.rangeStart = function;
- entry.rangeLength = function->size();
- } else
- entry = unwindLoc->second;
-
-
- // If there's no __compact_unwind entry, or it explicitly says to use
- // __eh_frame, we need to try and fill in the correct DWARF atom.
- if (entry.encoding == _archHandler.dwarfCompactUnwindType() ||
- entry.encoding == 0) {
- auto dwarfFrame = dwarfFrames.find(function);
- if (dwarfFrame != dwarfFrames.end()) {
- entry.encoding = _archHandler.dwarfCompactUnwindType();
- entry.ehFrame = dwarfFrame->second;
- }
- }
-
- auto personality = llvm::find(personalities, entry.personalityFunction);
- uint32_t personalityIdx = personality == personalities.end()
- ? 0
- : personality - personalities.begin() + 1;
-
- // FIXME: We should also use DWARF when there isn't enough room for the
- // personality function in the compact encoding.
- assert(personalityIdx < 4 && "too many personality functions");
-
- entry.encoding |= personalityIdx << 28;
-
- if (entry.lsdaLocation)
- entry.encoding |= 1U << 30;
-
- return entry;
- }
-
- const MachOLinkingContext &_ctx;
- mach_o::ArchHandler &_archHandler;
- MachOFile &_file;
- bool _isBig;
-};
-
-void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx) {
- assert(ctx.needsCompactUnwindPass());
- pm.add(std::make_unique<CompactUnwindPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_DEBUGINFO_H
-#define LLD_READER_WRITER_MACHO_DEBUGINFO_H
-
-#include "lld/Core/Atom.h"
-#include <vector>
-
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-
-
-namespace lld {
-namespace mach_o {
-
-class DebugInfo {
-public:
- enum class Kind {
- Dwarf,
- Stabs
- };
-
- Kind kind() const { return _kind; }
-
- void setAllocator(std::unique_ptr<llvm::BumpPtrAllocator> allocator) {
- _allocator = std::move(allocator);
- }
-
-protected:
- DebugInfo(Kind kind) : _kind(kind) {}
-
-private:
- std::unique_ptr<llvm::BumpPtrAllocator> _allocator;
- Kind _kind;
-};
-
-struct TranslationUnitSource {
- StringRef name;
- StringRef path;
-};
-
-class DwarfDebugInfo : public DebugInfo {
-public:
- DwarfDebugInfo(TranslationUnitSource tu)
- : DebugInfo(Kind::Dwarf), _tu(std::move(tu)) {}
-
- static inline bool classof(const DebugInfo *di) {
- return di->kind() == Kind::Dwarf;
- }
-
- const TranslationUnitSource &translationUnitSource() const { return _tu; }
-
-private:
- TranslationUnitSource _tu;
-};
-
-struct Stab {
- Stab(const Atom* atom, uint8_t type, uint8_t other, uint16_t desc,
- uint32_t value, StringRef str)
- : atom(atom), type(type), other(other), desc(desc), value(value),
- str(str) {}
-
- const class Atom* atom;
- uint8_t type;
- uint8_t other;
- uint16_t desc;
- uint32_t value;
- StringRef str;
-};
-
-inline raw_ostream& operator<<(raw_ostream &os, Stab &s) {
- os << "Stab -- atom: " << llvm::format("%p", s.atom) << ", type: " << (uint32_t)s.type
- << ", other: " << (uint32_t)s.other << ", desc: " << s.desc << ", value: " << s.value
- << ", str: '" << s.str << "'";
- return os;
-}
-
-class StabsDebugInfo : public DebugInfo {
-public:
-
- typedef std::vector<Stab> StabsList;
-
- StabsDebugInfo(StabsList stabs)
- : DebugInfo(Kind::Stabs), _stabs(std::move(stabs)) {}
-
- static inline bool classof(const DebugInfo *di) {
- return di->kind() == Kind::Stabs;
- }
-
- const StabsList& stabs() const { return _stabs; }
-
-public:
- StabsList _stabs;
-};
-
-} // end namespace mach_o
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_DEBUGINFO_H
+++ /dev/null
-//===- lib/ReaderWriter/MachO/ExecutableAtoms.h ---------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
-#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
-
-#include "Atoms.h"
-#include "File.h"
-
-#include "llvm/BinaryFormat/MachO.h"
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-
-namespace lld {
-namespace mach_o {
-
-
-//
-// CEntryFile adds an UndefinedAtom for "_main" so that the Resolving
-// phase will fail if "_main" is undefined.
-//
-class CEntryFile : public SimpleFile {
-public:
- CEntryFile(const MachOLinkingContext &context)
- : SimpleFile("C entry", kindCEntryObject),
- _undefMain(*this, context.entrySymbolName()) {
- this->addAtom(_undefMain);
- }
-
-private:
- SimpleUndefinedAtom _undefMain;
-};
-
-
-//
-// StubHelperFile adds an UndefinedAtom for "dyld_stub_binder" so that
-// the Resolveing phase will fail if "dyld_stub_binder" is undefined.
-//
-class StubHelperFile : public SimpleFile {
-public:
- StubHelperFile(const MachOLinkingContext &context)
- : SimpleFile("stub runtime", kindStubHelperObject),
- _undefBinder(*this, context.binderSymbolName()) {
- this->addAtom(_undefBinder);
- }
-
-private:
- SimpleUndefinedAtom _undefBinder;
-};
-
-
-//
-// MachHeaderAliasFile lazily instantiates the magic symbols that mark the start
-// of the mach_header for final linked images.
-//
-class MachHeaderAliasFile : public SimpleFile {
-public:
- MachHeaderAliasFile(const MachOLinkingContext &context)
- : SimpleFile("mach_header symbols", kindHeaderObject) {
- StringRef machHeaderSymbolName;
- DefinedAtom::Scope symbolScope = DefinedAtom::scopeLinkageUnit;
- StringRef dsoHandleName;
- switch (context.outputMachOType()) {
- case llvm::MachO::MH_OBJECT:
- machHeaderSymbolName = "__mh_object_header";
- break;
- case llvm::MachO::MH_EXECUTE:
- machHeaderSymbolName = "__mh_execute_header";
- symbolScope = DefinedAtom::scopeGlobal;
- dsoHandleName = "___dso_handle";
- break;
- case llvm::MachO::MH_FVMLIB:
- llvm_unreachable("no mach_header symbol for file type");
- case llvm::MachO::MH_CORE:
- llvm_unreachable("no mach_header symbol for file type");
- case llvm::MachO::MH_PRELOAD:
- llvm_unreachable("no mach_header symbol for file type");
- case llvm::MachO::MH_DYLIB:
- machHeaderSymbolName = "__mh_dylib_header";
- dsoHandleName = "___dso_handle";
- break;
- case llvm::MachO::MH_DYLINKER:
- machHeaderSymbolName = "__mh_dylinker_header";
- dsoHandleName = "___dso_handle";
- break;
- case llvm::MachO::MH_BUNDLE:
- machHeaderSymbolName = "__mh_bundle_header";
- dsoHandleName = "___dso_handle";
- break;
- case llvm::MachO::MH_DYLIB_STUB:
- llvm_unreachable("no mach_header symbol for file type");
- case llvm::MachO::MH_DSYM:
- llvm_unreachable("no mach_header symbol for file type");
- case llvm::MachO::MH_KEXT_BUNDLE:
- dsoHandleName = "___dso_handle";
- break;
- }
- if (!machHeaderSymbolName.empty())
- _definedAtoms.push_back(new (allocator()) MachODefinedAtom(
- *this, machHeaderSymbolName, symbolScope,
- DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false,
- true /* noDeadStrip */,
- ArrayRef<uint8_t>(), DefinedAtom::Alignment(4096)));
-
- if (!dsoHandleName.empty())
- _definedAtoms.push_back(new (allocator()) MachODefinedAtom(
- *this, dsoHandleName, DefinedAtom::scopeLinkageUnit,
- DefinedAtom::typeDSOHandle, DefinedAtom::mergeNo, false,
- true /* noDeadStrip */,
- ArrayRef<uint8_t>(), DefinedAtom::Alignment(1)));
- }
-
- const AtomRange<DefinedAtom> defined() const override {
- return _definedAtoms;
- }
- const AtomRange<UndefinedAtom> undefined() const override {
- return _noUndefinedAtoms;
- }
-
- const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
- return _noSharedLibraryAtoms;
- }
-
- const AtomRange<AbsoluteAtom> absolute() const override {
- return _noAbsoluteAtoms;
- }
-
- void clearAtoms() override {
- _definedAtoms.clear();
- _noUndefinedAtoms.clear();
- _noSharedLibraryAtoms.clear();
- _noAbsoluteAtoms.clear();
- }
-
-
-private:
- mutable AtomVector<DefinedAtom> _definedAtoms;
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
+++ /dev/null
-//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_FILE_H
-#define LLD_READER_WRITER_MACHO_FILE_H
-
-#include "Atoms.h"
-#include "DebugInfo.h"
-#include "MachONormalizedFile.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/Format.h"
-#include "llvm/TextAPI/InterfaceFile.h"
-#include "llvm/TextAPI/TextAPIReader.h"
-#include <unordered_map>
-
-namespace lld {
-namespace mach_o {
-
-using lld::mach_o::normalized::Section;
-
-class MachOFile : public SimpleFile {
-public:
-
- /// Real file constructor - for on-disk files.
- MachOFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
- : SimpleFile(mb->getBufferIdentifier(), File::kindMachObject),
- _mb(std::move(mb)), _ctx(ctx) {}
-
- /// Dummy file constructor - for virtual files.
- MachOFile(StringRef path)
- : SimpleFile(path, File::kindMachObject) {}
-
- void addDefinedAtom(StringRef name, Atom::Scope scope,
- DefinedAtom::ContentType type, DefinedAtom::Merge merge,
- uint64_t sectionOffset, uint64_t contentSize, bool thumb,
- bool noDeadStrip, bool copyRefs,
- const Section *inSection) {
- assert(sectionOffset+contentSize <= inSection->content.size());
- ArrayRef<uint8_t> content = inSection->content.slice(sectionOffset,
- contentSize);
- if (copyRefs) {
- // Make a copy of the atom's name and content that is owned by this file.
- name = name.copy(allocator());
- content = content.copy(allocator());
- }
- DefinedAtom::Alignment align(
- inSection->alignment,
- sectionOffset % inSection->alignment);
- auto *atom =
- new (allocator()) MachODefinedAtom(*this, name, scope, type, merge,
- thumb, noDeadStrip, content, align);
- addAtomForSection(inSection, atom, sectionOffset);
- }
-
- void addDefinedAtomInCustomSection(StringRef name, Atom::Scope scope,
- DefinedAtom::ContentType type, DefinedAtom::Merge merge,
- bool thumb, bool noDeadStrip, uint64_t sectionOffset,
- uint64_t contentSize, StringRef sectionName,
- bool copyRefs, const Section *inSection) {
- assert(sectionOffset+contentSize <= inSection->content.size());
- ArrayRef<uint8_t> content = inSection->content.slice(sectionOffset,
- contentSize);
- if (copyRefs) {
- // Make a copy of the atom's name and content that is owned by this file.
- name = name.copy(allocator());
- content = content.copy(allocator());
- sectionName = sectionName.copy(allocator());
- }
- DefinedAtom::Alignment align(
- inSection->alignment,
- sectionOffset % inSection->alignment);
- auto *atom =
- new (allocator()) MachODefinedCustomSectionAtom(*this, name, scope, type,
- merge, thumb,
- noDeadStrip, content,
- sectionName, align);
- addAtomForSection(inSection, atom, sectionOffset);
- }
-
- void addZeroFillDefinedAtom(StringRef name, Atom::Scope scope,
- uint64_t sectionOffset, uint64_t size,
- bool noDeadStrip, bool copyRefs,
- const Section *inSection) {
- if (copyRefs) {
- // Make a copy of the atom's name and content that is owned by this file.
- name = name.copy(allocator());
- }
- DefinedAtom::Alignment align(
- inSection->alignment,
- sectionOffset % inSection->alignment);
-
- DefinedAtom::ContentType type = DefinedAtom::typeUnknown;
- switch (inSection->type) {
- case llvm::MachO::S_ZEROFILL:
- type = DefinedAtom::typeZeroFill;
- break;
- case llvm::MachO::S_THREAD_LOCAL_ZEROFILL:
- type = DefinedAtom::typeTLVInitialZeroFill;
- break;
- default:
- llvm_unreachable("Unrecognized zero-fill section");
- }
-
- auto *atom =
- new (allocator()) MachODefinedAtom(*this, name, scope, type, size,
- noDeadStrip, align);
- addAtomForSection(inSection, atom, sectionOffset);
- }
-
- void addUndefinedAtom(StringRef name, bool copyRefs) {
- if (copyRefs) {
- // Make a copy of the atom's name that is owned by this file.
- name = name.copy(allocator());
- }
- auto *atom = new (allocator()) SimpleUndefinedAtom(*this, name);
- addAtom(*atom);
- _undefAtoms[name] = atom;
- }
-
- void addTentativeDefAtom(StringRef name, Atom::Scope scope, uint64_t size,
- DefinedAtom::Alignment align, bool copyRefs) {
- if (copyRefs) {
- // Make a copy of the atom's name that is owned by this file.
- name = name.copy(allocator());
- }
- auto *atom =
- new (allocator()) MachOTentativeDefAtom(*this, name, scope, size, align);
- addAtom(*atom);
- _undefAtoms[name] = atom;
- }
-
- /// Search this file for the atom from 'section' that covers
- /// 'offsetInSect'. Returns nullptr is no atom found.
- MachODefinedAtom *findAtomCoveringAddress(const Section §ion,
- uint64_t offsetInSect,
- uint32_t *foundOffsetAtom=nullptr) {
- const auto &pos = _sectionAtoms.find(§ion);
- if (pos == _sectionAtoms.end())
- return nullptr;
- const auto &vec = pos->second;
- assert(offsetInSect < section.content.size());
- // Vector of atoms for section are already sorted, so do binary search.
- const auto &atomPos = std::lower_bound(vec.begin(), vec.end(), offsetInSect,
- [offsetInSect](const SectionOffsetAndAtom &ao,
- uint64_t targetAddr) -> bool {
- // Each atom has a start offset of its slice of the
- // section's content. This compare function must return true
- // iff the atom's range is before the offset being searched for.
- uint64_t atomsEndOffset = ao.offset+ao.atom->rawContent().size();
- return (atomsEndOffset <= offsetInSect);
- });
- if (atomPos == vec.end())
- return nullptr;
- if (foundOffsetAtom)
- *foundOffsetAtom = offsetInSect - atomPos->offset;
- return atomPos->atom;
- }
-
- /// Searches this file for an UndefinedAtom named 'name'. Returns
- /// nullptr is no such atom found.
- const lld::Atom *findUndefAtom(StringRef name) {
- auto pos = _undefAtoms.find(name);
- if (pos == _undefAtoms.end())
- return nullptr;
- return pos->second;
- }
-
- typedef std::function<void (MachODefinedAtom* atom)> DefinedAtomVisitor;
-
- void eachDefinedAtom(DefinedAtomVisitor vistor) {
- for (auto §AndAtoms : _sectionAtoms) {
- for (auto &offAndAtom : sectAndAtoms.second) {
- vistor(offAndAtom.atom);
- }
- }
- }
-
- typedef std::function<void(MachODefinedAtom *atom, uint64_t offset)>
- SectionAtomVisitor;
-
- void eachAtomInSection(const Section §ion, SectionAtomVisitor visitor) {
- auto pos = _sectionAtoms.find(§ion);
- if (pos == _sectionAtoms.end())
- return;
- auto vec = pos->second;
-
- for (auto &offAndAtom : vec)
- visitor(offAndAtom.atom, offAndAtom.offset);
- }
-
- MachOLinkingContext::Arch arch() const { return _arch; }
- void setArch(MachOLinkingContext::Arch arch) { _arch = arch; }
-
- MachOLinkingContext::OS OS() const { return _os; }
- void setOS(MachOLinkingContext::OS os) { _os = os; }
-
- MachOLinkingContext::ObjCConstraint objcConstraint() const {
- return _objcConstraint;
- }
- void setObjcConstraint(MachOLinkingContext::ObjCConstraint v) {
- _objcConstraint = v;
- }
-
- uint32_t minVersion() const { return _minVersion; }
- void setMinVersion(uint32_t v) { _minVersion = v; }
-
- LoadCommandType minVersionLoadCommandKind() const {
- return _minVersionLoadCommandKind;
- }
- void setMinVersionLoadCommandKind(LoadCommandType v) {
- _minVersionLoadCommandKind = v;
- }
-
- uint32_t swiftVersion() const { return _swiftVersion; }
- void setSwiftVersion(uint32_t v) { _swiftVersion = v; }
-
- bool subsectionsViaSymbols() const {
- return _flags & llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
- }
- void setFlags(normalized::FileFlags v) { _flags = v; }
-
- /// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const File *F) {
- return F->kind() == File::kindMachObject;
- }
-
- void setDebugInfo(std::unique_ptr<DebugInfo> debugInfo) {
- _debugInfo = std::move(debugInfo);
- }
-
- DebugInfo* debugInfo() const { return _debugInfo.get(); }
- std::unique_ptr<DebugInfo> takeDebugInfo() { return std::move(_debugInfo); }
-
-protected:
- std::error_code doParse() override {
- // Convert binary file to normalized mach-o.
- auto normFile = normalized::readBinary(_mb, _ctx->arch());
- if (auto ec = normFile.takeError())
- return llvm::errorToErrorCode(std::move(ec));
- // Convert normalized mach-o to atoms.
- if (auto ec = normalized::normalizedObjectToAtoms(this, **normFile, false))
- return llvm::errorToErrorCode(std::move(ec));
- return std::error_code();
- }
-
-private:
- struct SectionOffsetAndAtom { uint64_t offset; MachODefinedAtom *atom; };
-
- void addAtomForSection(const Section *inSection, MachODefinedAtom* atom,
- uint64_t sectionOffset) {
- SectionOffsetAndAtom offAndAtom;
- offAndAtom.offset = sectionOffset;
- offAndAtom.atom = atom;
- _sectionAtoms[inSection].push_back(offAndAtom);
- addAtom(*atom);
- }
-
- typedef llvm::DenseMap<const normalized::Section *,
- std::vector<SectionOffsetAndAtom>> SectionToAtoms;
- typedef llvm::StringMap<const lld::Atom *> NameToAtom;
-
- std::unique_ptr<MemoryBuffer> _mb;
- MachOLinkingContext *_ctx;
- SectionToAtoms _sectionAtoms;
- NameToAtom _undefAtoms;
- MachOLinkingContext::Arch _arch = MachOLinkingContext::arch_unknown;
- MachOLinkingContext::OS _os = MachOLinkingContext::OS::unknown;
- uint32_t _minVersion = 0;
- LoadCommandType _minVersionLoadCommandKind = (LoadCommandType)0;
- MachOLinkingContext::ObjCConstraint _objcConstraint =
- MachOLinkingContext::objc_unknown;
- uint32_t _swiftVersion = 0;
- normalized::FileFlags _flags = llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
- std::unique_ptr<DebugInfo> _debugInfo;
-};
-
-class MachODylibFile : public SharedLibraryFile {
-public:
- MachODylibFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
- : SharedLibraryFile(mb->getBufferIdentifier()),
- _mb(std::move(mb)), _ctx(ctx) {}
-
- MachODylibFile(StringRef path) : SharedLibraryFile(path) {}
-
- OwningAtomPtr<SharedLibraryAtom> exports(StringRef name) const override {
- // Pass down _installName so that if this requested symbol
- // is re-exported through this dylib, the SharedLibraryAtom's loadName()
- // is this dylib installName and not the implementation dylib's.
- // NOTE: isData is not needed for dylibs (it matters for static libs).
- return exports(name, _installName);
- }
-
- /// Adds symbol name that this dylib exports. The corresponding
- /// SharedLibraryAtom is created lazily (since most symbols are not used).
- void addExportedSymbol(StringRef name, bool weakDef, bool copyRefs) {
- if (copyRefs) {
- name = name.copy(allocator());
- }
- AtomAndFlags info(weakDef);
- _nameToAtom[name] = info;
- }
-
- void addReExportedDylib(StringRef dylibPath) {
- _reExportedDylibs.emplace_back(dylibPath);
- }
-
- StringRef installName() const { return _installName; }
- uint32_t currentVersion() { return _currentVersion; }
- uint32_t compatVersion() { return _compatVersion; }
-
- void setInstallName(StringRef name) { _installName = name; }
- void setCompatVersion(uint32_t version) { _compatVersion = version; }
- void setCurrentVersion(uint32_t version) { _currentVersion = version; }
-
- typedef std::function<MachODylibFile *(StringRef)> FindDylib;
-
- void loadReExportedDylibs(FindDylib find) {
- for (ReExportedDylib &entry : _reExportedDylibs) {
- if (!entry.file)
- entry.file = find(entry.path);
- }
- }
-
- StringRef getDSOName() const override { return _installName; }
-
- std::error_code doParse() override {
- // Convert binary file to normalized mach-o.
- auto normFile = normalized::readBinary(_mb, _ctx->arch());
- if (auto ec = normFile.takeError())
- return llvm::errorToErrorCode(std::move(ec));
- // Convert normalized mach-o to atoms.
- if (auto ec = normalized::normalizedDylibToAtoms(this, **normFile, false))
- return llvm::errorToErrorCode(std::move(ec));
- return std::error_code();
- }
-
-protected:
- OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
- StringRef installName) const {
- // First, check if requested symbol is directly implemented by this dylib.
- auto entry = _nameToAtom.find(name);
- if (entry != _nameToAtom.end()) {
- // FIXME: Make this map a set and only used in assert builds.
- // Note, its safe to assert here as the resolver is the only client of
- // this API and it only requests exports for undefined symbols.
- // If we return from here we are no longer undefined so we should never
- // get here again.
- assert(!entry->second.atom && "Duplicate shared library export");
- bool weakDef = entry->second.weakDef;
- auto *atom = new (allocator()) MachOSharedLibraryAtom(*this, name,
- installName,
- weakDef);
- entry->second.atom = atom;
- return atom;
- }
-
- // Next, check if symbol is implemented in some re-exported dylib.
- for (const ReExportedDylib &dylib : _reExportedDylibs) {
- assert(dylib.file);
- auto atom = dylib.file->exports(name, installName);
- if (atom.get())
- return atom;
- }
-
- // Symbol not exported or re-exported by this dylib.
- return nullptr;
- }
-
- struct ReExportedDylib {
- ReExportedDylib(StringRef p) : path(p), file(nullptr) { }
- ReExportedDylib(StringRef p, MachODylibFile *file) : path(p), file(file) { }
- StringRef path;
- MachODylibFile *file;
- };
-
- struct AtomAndFlags {
- AtomAndFlags() : atom(nullptr), weakDef(false) { }
- AtomAndFlags(bool weak) : atom(nullptr), weakDef(weak) { }
- const SharedLibraryAtom *atom;
- bool weakDef;
- };
-
- std::unique_ptr<MemoryBuffer> _mb;
- MachOLinkingContext *_ctx;
- StringRef _installName;
- uint32_t _currentVersion;
- uint32_t _compatVersion;
- std::vector<ReExportedDylib> _reExportedDylibs;
- mutable std::unordered_map<StringRef, AtomAndFlags> _nameToAtom;
-};
-
-class TAPIFile : public MachODylibFile {
-public:
-
- TAPIFile(std::unique_ptr<MemoryBuffer> mb, MachOLinkingContext *ctx)
- : MachODylibFile(std::move(mb), ctx) {}
-
- std::error_code doParse() override {
-
- llvm::Expected<std::unique_ptr<llvm::MachO::InterfaceFile>> result =
- llvm::MachO::TextAPIReader::get(*_mb);
- if (!result)
- return std::make_error_code(std::errc::invalid_argument);
-
- std::unique_ptr<llvm::MachO::InterfaceFile> interface{std::move(*result)};
- return loadFromInterface(*interface);
- }
-
-private:
- std::error_code loadFromInterface(llvm::MachO::InterfaceFile &interface) {
- llvm::MachO::Architecture arch;
- switch(_ctx->arch()) {
- case MachOLinkingContext::arch_x86:
- arch = llvm::MachO::AK_i386;
- break;
- case MachOLinkingContext::arch_x86_64:
- arch = llvm::MachO::AK_x86_64;
- break;
- case MachOLinkingContext::arch_arm64:
- arch = llvm::MachO::AK_arm64;
- break;
- default:
- return std::make_error_code(std::errc::invalid_argument);
- }
-
- setInstallName(interface.getInstallName().copy(allocator()));
- // TODO(compnerd) filter out symbols based on the target platform
- for (const auto symbol : interface.symbols())
- if (symbol->getArchitectures().has(arch))
- addExportedSymbol(symbol->getName(), symbol->isWeakDefined(), true);
-
- for (const llvm::MachO::InterfaceFileRef &reexport :
- interface.reexportedLibraries())
- addReExportedDylib(reexport.getInstallName().copy(allocator()));
-
- for (const auto& document : interface.documents()) {
- for (auto& reexport : _reExportedDylibs) {
- if (reexport.path != document->getInstallName())
- continue;
- assert(!reexport.file);
- _ownedFiles.push_back(std::make_unique<TAPIFile>(
- MemoryBuffer::getMemBuffer("", _mb->getBufferIdentifier()), _ctx));
- reexport.file = _ownedFiles.back().get();
- std::error_code err = _ownedFiles.back()->loadFromInterface(*document);
- if (err)
- return err;
- }
- }
-
- return std::error_code();
- }
-
- std::vector<std::unique_ptr<TAPIFile>> _ownedFiles;
-};
-
-} // end namespace mach_o
-} // end namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_FILE_H
+++ /dev/null
-//===- lib/ReaderWriter/MachO/FlatNamespaceFile.h -------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H
-#define LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H
-
-#include "Atoms.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/Support/Debug.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-// A FlateNamespaceFile instance may be added as a resolution source of last
-// resort, depending on how -flat_namespace and -undefined are set.
-//
-class FlatNamespaceFile : public SharedLibraryFile {
-public:
- FlatNamespaceFile(const MachOLinkingContext &context)
- : SharedLibraryFile("flat namespace") { }
-
- OwningAtomPtr<SharedLibraryAtom> exports(StringRef name) const override {
- return new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
- false);
- }
-
- StringRef getDSOName() const override { return "flat-namespace"; }
-
- const AtomRange<DefinedAtom> defined() const override {
- return _noDefinedAtoms;
- }
- const AtomRange<UndefinedAtom> undefined() const override {
- return _noUndefinedAtoms;
- }
-
- const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
- return _noSharedLibraryAtoms;
- }
-
- const AtomRange<AbsoluteAtom> absolute() const override {
- return _noAbsoluteAtoms;
- }
-
- void clearAtoms() override {
- _noDefinedAtoms.clear();
- _noUndefinedAtoms.clear();
- _noSharedLibraryAtoms.clear();
- _noAbsoluteAtoms.clear();
- }
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H
+++ /dev/null
-//===- lib/ReaderWriter/MachO/GOTPass.cpp -----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This linker pass transforms all GOT kind references to real references.
-/// That is, in assembly you can write something like:
-/// movq foo@GOTPCREL(%rip), %rax
-/// which means you want to load a pointer to "foo" out of the GOT (global
-/// Offsets Table). In the object file, the Atom containing this instruction
-/// has a Reference whose target is an Atom named "foo" and the Reference
-/// kind is a GOT load. The linker needs to instantiate a pointer sized
-/// GOT entry. This is done be creating a GOT Atom to represent that pointer
-/// sized data in this pass, and altering the Atom graph so the Reference now
-/// points to the GOT Atom entry (corresponding to "foo") and changing the
-/// Reference Kind to reflect it is now pointing to a GOT entry (rather
-/// then needing a GOT entry).
-///
-/// There is one optimization the linker can do here. If the target of the GOT
-/// 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
-/// 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 method isGOTAccess() should
-/// only return true for "canBypassGOT" if this optimization is supported.
-///
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-// GOT Entry Atom created by the GOT pass.
-//
-class GOTEntryAtom : public SimpleDefinedAtom {
-public:
- GOTEntryAtom(const File &file, bool is64, StringRef name)
- : SimpleDefinedAtom(file), _is64(is64), _name(name) { }
-
- ~GOTEntryAtom() override = default;
-
- ContentType contentType() const override {
- return DefinedAtom::typeGOT;
- }
-
- Alignment alignment() const override {
- return _is64 ? 8 : 4;
- }
-
- uint64_t size() const override {
- return _is64 ? 8 : 4;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permRW_;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- static const uint8_t zeros[] =
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- return llvm::makeArrayRef(zeros, size());
- }
-
- StringRef slotName() const {
- return _name;
- }
-
-private:
- const bool _is64;
- StringRef _name;
-};
-
-/// Pass for instantiating and optimizing GOT slots.
-///
-class GOTPass : public Pass {
-public:
- GOTPass(const MachOLinkingContext &context)
- : _ctx(context), _archHandler(_ctx.archHandler()),
- _file(*_ctx.make_file<MachOFile>("<mach-o GOT Pass>")) {
- _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
- }
-
-private:
- llvm::Error perform(SimpleFile &mergedFile) override {
- // Scan all references in all atoms.
- for (const DefinedAtom *atom : mergedFile.defined()) {
- for (const Reference *ref : *atom) {
- // Look at instructions accessing the GOT.
- bool canBypassGOT;
- if (!_archHandler.isGOTAccess(*ref, canBypassGOT))
- continue;
- const Atom *target = ref->target();
- assert(target != nullptr);
-
- if (!shouldReplaceTargetWithGOTAtom(target, canBypassGOT)) {
- // Update reference kind to reflect that target is a direct access.
- _archHandler.updateReferenceToGOT(ref, false);
- } else {
- // Replace the target with a reference to a GOT entry.
- const DefinedAtom *gotEntry = makeGOTEntry(target);
- const_cast<Reference *>(ref)->setTarget(gotEntry);
- // Update reference kind to reflect that target is now a GOT entry.
- _archHandler.updateReferenceToGOT(ref, true);
- }
- }
- }
-
- // Sort and add all created GOT Atoms to merged file
- std::vector<const GOTEntryAtom *> entries;
- entries.reserve(_targetToGOT.size());
- for (auto &it : _targetToGOT)
- entries.push_back(it.second);
- std::sort(entries.begin(), entries.end(),
- [](const GOTEntryAtom *left, const GOTEntryAtom *right) {
- return (left->slotName().compare(right->slotName()) < 0);
- });
- for (const GOTEntryAtom *slot : entries)
- mergedFile.addAtom(*slot);
-
- return llvm::Error::success();
- }
-
- bool shouldReplaceTargetWithGOTAtom(const Atom *target, bool canBypassGOT) {
- // Accesses to shared library symbols must go through GOT.
- if (isa<SharedLibraryAtom>(target))
- return true;
- // Accesses to interposable symbols in same linkage unit must also go
- // through GOT.
- const DefinedAtom *defTarget = dyn_cast<DefinedAtom>(target);
- if (defTarget != nullptr &&
- defTarget->interposable() != DefinedAtom::interposeNo) {
- assert(defTarget->scope() != DefinedAtom::scopeTranslationUnit);
- return true;
- }
- // Target does not require indirection. So, if instruction allows GOT to be
- // by-passed, do that optimization and don't create GOT entry.
- return !canBypassGOT;
- }
-
- const DefinedAtom *makeGOTEntry(const Atom *target) {
- auto pos = _targetToGOT.find(target);
- if (pos == _targetToGOT.end()) {
- auto *gotEntry = new (_file.allocator())
- GOTEntryAtom(_file, _ctx.is64Bit(), target->name());
- _targetToGOT[target] = gotEntry;
- const ArchHandler::ReferenceInfo &nlInfo = _archHandler.stubInfo().
- nonLazyPointerReferenceToBinder;
- gotEntry->addReference(Reference::KindNamespace::mach_o, nlInfo.arch,
- nlInfo.kind, 0, target, 0);
- return gotEntry;
- }
- return pos->second;
- }
-
- const MachOLinkingContext &_ctx;
- mach_o::ArchHandler &_archHandler;
- MachOFile &_file;
- llvm::DenseMap<const Atom*, const GOTEntryAtom*> _targetToGOT;
-};
-
-void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx) {
- assert(ctx.needsGOTPass());
- pm.add(std::make_unique<GOTPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
+++ /dev/null
-//===-- ReaderWriter/MachO/LayoutPass.cpp - Layout atoms ------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "LayoutPass.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/PassManager.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Parallel.h"
-#include <algorithm>
-#include <set>
-#include <utility>
-
-using namespace lld;
-
-#define DEBUG_TYPE "LayoutPass"
-
-namespace lld {
-namespace mach_o {
-
-static bool compareAtoms(const LayoutPass::SortKey &,
- const LayoutPass::SortKey &,
- LayoutPass::SortOverride customSorter);
-
-#ifndef NDEBUG
-// Return "reason (leftval, rightval)"
-static std::string formatReason(StringRef reason, int leftVal, int rightVal) {
- return (Twine(reason) + " (" + Twine(leftVal) + ", " + Twine(rightVal) + ")")
- .str();
-}
-
-// Less-than relationship of two atoms must be transitive, which is, if a < b
-// and b < c, a < c must be true. This function checks the transitivity by
-// checking the sort results.
-static void checkTransitivity(std::vector<LayoutPass::SortKey> &vec,
- LayoutPass::SortOverride customSorter) {
- for (auto i = vec.begin(), e = vec.end(); (i + 1) != e; ++i) {
- for (auto j = i + 1; j != e; ++j) {
- assert(compareAtoms(*i, *j, customSorter));
- assert(!compareAtoms(*j, *i, customSorter));
- }
- }
-}
-
-// Helper functions to check follow-on graph.
-typedef llvm::DenseMap<const DefinedAtom *, const DefinedAtom *> AtomToAtomT;
-
-static std::string atomToDebugString(const Atom *atom) {
- const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom);
- std::string str;
- llvm::raw_string_ostream s(str);
- if (definedAtom->name().empty())
- s << "<anonymous " << definedAtom << ">";
- else
- s << definedAtom->name();
- s << " in ";
- if (definedAtom->customSectionName().empty())
- s << "<anonymous>";
- else
- s << definedAtom->customSectionName();
- s.flush();
- return str;
-}
-
-static void showCycleDetectedError(const Registry ®istry,
- AtomToAtomT &followOnNexts,
- const DefinedAtom *atom) {
- const DefinedAtom *start = atom;
- llvm::dbgs() << "There's a cycle in a follow-on chain!\n";
- do {
- llvm::dbgs() << " " << atomToDebugString(atom) << "\n";
- for (const Reference *ref : *atom) {
- StringRef kindValStr;
- if (!registry.referenceKindToString(ref->kindNamespace(), ref->kindArch(),
- ref->kindValue(), kindValStr)) {
- kindValStr = "<unknown>";
- }
- llvm::dbgs() << " " << kindValStr
- << ": " << atomToDebugString(ref->target()) << "\n";
- }
- atom = followOnNexts[atom];
- } while (atom != start);
- llvm::report_fatal_error("Cycle detected");
-}
-
-/// Exit if there's a cycle in a followon chain reachable from the
-/// given root atom. Uses the tortoise and hare algorithm to detect a
-/// cycle.
-static void checkNoCycleInFollowonChain(const Registry ®istry,
- AtomToAtomT &followOnNexts,
- const DefinedAtom *root) {
- const DefinedAtom *tortoise = root;
- const DefinedAtom *hare = followOnNexts[root];
- while (true) {
- if (!tortoise || !hare)
- return;
- if (tortoise == hare)
- showCycleDetectedError(registry, followOnNexts, tortoise);
- tortoise = followOnNexts[tortoise];
- hare = followOnNexts[followOnNexts[hare]];
- }
-}
-
-static void checkReachabilityFromRoot(AtomToAtomT &followOnRoots,
- const DefinedAtom *atom) {
- if (!atom) return;
- auto i = followOnRoots.find(atom);
- if (i == followOnRoots.end()) {
- llvm_unreachable(((Twine("Atom <") + atomToDebugString(atom) +
- "> has no follow-on root!"))
- .str()
- .c_str());
- }
- const DefinedAtom *ap = i->second;
- while (true) {
- const DefinedAtom *next = followOnRoots[ap];
- if (!next) {
- llvm_unreachable((Twine("Atom <" + atomToDebugString(atom) +
- "> is not reachable from its root!"))
- .str()
- .c_str());
- }
- if (next == ap)
- return;
- ap = next;
- }
-}
-
-static void printDefinedAtoms(const File::AtomRange<DefinedAtom> &atomRange) {
- for (const DefinedAtom *atom : atomRange) {
- llvm::dbgs() << " file=" << atom->file().path()
- << ", name=" << atom->name()
- << ", size=" << atom->size()
- << ", type=" << atom->contentType()
- << ", ordinal=" << atom->ordinal()
- << "\n";
- }
-}
-
-/// Verify that the followon chain is sane. Should not be called in
-/// release binary.
-void LayoutPass::checkFollowonChain(const File::AtomRange<DefinedAtom> &range) {
- ScopedTask task(getDefaultDomain(), "LayoutPass::checkFollowonChain");
-
- // Verify that there's no cycle in follow-on chain.
- std::set<const DefinedAtom *> roots;
- for (const auto &ai : _followOnRoots)
- roots.insert(ai.second);
- for (const DefinedAtom *root : roots)
- checkNoCycleInFollowonChain(_registry, _followOnNexts, root);
-
- // Verify that all the atoms in followOnNexts have references to
- // their roots.
- for (const auto &ai : _followOnNexts) {
- checkReachabilityFromRoot(_followOnRoots, ai.first);
- checkReachabilityFromRoot(_followOnRoots, ai.second);
- }
-}
-#endif // #ifndef NDEBUG
-
-/// The function compares atoms by sorting atoms in the following order
-/// a) Sorts atoms by their ordinal overrides (layout-after/ingroup)
-/// b) Sorts atoms by their permissions
-/// c) Sorts atoms by their content
-/// d) Sorts atoms by custom sorter
-/// e) Sorts atoms on how they appear using File Ordinality
-/// f) Sorts atoms on how they appear within the File
-static bool compareAtomsSub(const LayoutPass::SortKey &lc,
- const LayoutPass::SortKey &rc,
- LayoutPass::SortOverride customSorter,
- std::string &reason) {
- const DefinedAtom *left = lc._atom.get();
- const DefinedAtom *right = rc._atom.get();
- if (left == right) {
- reason = "same";
- return false;
- }
-
- // Find the root of the chain if it is a part of a follow-on chain.
- const DefinedAtom *leftRoot = lc._root;
- const DefinedAtom *rightRoot = rc._root;
-
- // Sort atoms by their ordinal overrides only if they fall in the same
- // chain.
- if (leftRoot == rightRoot) {
- LLVM_DEBUG(reason = formatReason("override", lc._override, rc._override));
- return lc._override < rc._override;
- }
-
- // Sort same permissions together.
- DefinedAtom::ContentPermissions leftPerms = leftRoot->permissions();
- DefinedAtom::ContentPermissions rightPerms = rightRoot->permissions();
-
- if (leftPerms != rightPerms) {
- LLVM_DEBUG(
- reason = formatReason("contentPerms", (int)leftPerms, (int)rightPerms));
- return leftPerms < rightPerms;
- }
-
- // Sort same content types together.
- DefinedAtom::ContentType leftType = leftRoot->contentType();
- DefinedAtom::ContentType rightType = rightRoot->contentType();
-
- if (leftType != rightType) {
- LLVM_DEBUG(reason =
- formatReason("contentType", (int)leftType, (int)rightType));
- return leftType < rightType;
- }
-
- // Use custom sorter if supplied.
- if (customSorter) {
- bool leftBeforeRight;
- if (customSorter(leftRoot, rightRoot, leftBeforeRight))
- return leftBeforeRight;
- }
-
- // Sort by .o order.
- const File *leftFile = &leftRoot->file();
- const File *rightFile = &rightRoot->file();
-
- if (leftFile != rightFile) {
- LLVM_DEBUG(reason = formatReason(".o order", (int)leftFile->ordinal(),
- (int)rightFile->ordinal()));
- return leftFile->ordinal() < rightFile->ordinal();
- }
-
- // Sort by atom order with .o file.
- uint64_t leftOrdinal = leftRoot->ordinal();
- uint64_t rightOrdinal = rightRoot->ordinal();
-
- if (leftOrdinal != rightOrdinal) {
- LLVM_DEBUG(reason = formatReason("ordinal", (int)leftRoot->ordinal(),
- (int)rightRoot->ordinal()));
- return leftOrdinal < rightOrdinal;
- }
-
- llvm::errs() << "Unordered: <" << left->name() << "> <" << right->name()
- << ">\n";
- llvm_unreachable("Atoms with Same Ordinal!");
-}
-
-static bool compareAtoms(const LayoutPass::SortKey &lc,
- const LayoutPass::SortKey &rc,
- LayoutPass::SortOverride customSorter) {
- std::string reason;
- bool result = compareAtomsSub(lc, rc, customSorter, reason);
- LLVM_DEBUG({
- StringRef comp = result ? "<" : ">=";
- llvm::dbgs() << "Layout: '" << lc._atom.get()->name()
- << "' " << comp << " '"
- << rc._atom.get()->name() << "' (" << reason << ")\n";
- });
- return result;
-}
-
-LayoutPass::LayoutPass(const Registry ®istry, SortOverride sorter)
- : _registry(registry), _customSorter(std::move(sorter)) {}
-
-// Returns the atom immediately followed by the given atom in the followon
-// chain.
-const DefinedAtom *LayoutPass::findAtomFollowedBy(
- const DefinedAtom *targetAtom) {
- // Start from the beginning of the chain and follow the chain until
- // we find the targetChain.
- const DefinedAtom *atom = _followOnRoots[targetAtom];
- while (true) {
- const DefinedAtom *prevAtom = atom;
- AtomToAtomT::iterator targetFollowOnAtomsIter = _followOnNexts.find(atom);
- // The target atom must be in the chain of its root.
- assert(targetFollowOnAtomsIter != _followOnNexts.end());
- atom = targetFollowOnAtomsIter->second;
- if (atom == targetAtom)
- return prevAtom;
- }
-}
-
-// Check if all the atoms followed by the given target atom are of size zero.
-// When this method is called, an atom being added is not of size zero and
-// will be added to the head of the followon chain. All the atoms between the
-// atom and the targetAtom (specified by layout-after) need to be of size zero
-// in this case. Otherwise the desired layout is impossible.
-bool LayoutPass::checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom) {
- const DefinedAtom *atom = _followOnRoots[targetAtom];
- while (true) {
- if (atom == targetAtom)
- return true;
- if (atom->size() != 0)
- // TODO: print warning that an impossible layout is being desired by the
- // user.
- return false;
- AtomToAtomT::iterator targetFollowOnAtomsIter = _followOnNexts.find(atom);
- // The target atom must be in the chain of its root.
- assert(targetFollowOnAtomsIter != _followOnNexts.end());
- atom = targetFollowOnAtomsIter->second;
- }
-}
-
-// Set the root of all atoms in targetAtom's chain to the given root.
-void LayoutPass::setChainRoot(const DefinedAtom *targetAtom,
- const DefinedAtom *root) {
- // Walk through the followon chain and override each node's root.
- while (true) {
- _followOnRoots[targetAtom] = root;
- AtomToAtomT::iterator targetFollowOnAtomsIter =
- _followOnNexts.find(targetAtom);
- if (targetFollowOnAtomsIter == _followOnNexts.end())
- return;
- targetAtom = targetFollowOnAtomsIter->second;
- }
-}
-
-/// This pass builds the followon tables described by two DenseMaps
-/// followOnRoots and followonNexts.
-/// The followOnRoots map contains a mapping of a DefinedAtom to its root
-/// The followOnNexts map contains a mapping of what DefinedAtom follows the
-/// current Atom
-/// The algorithm follows a very simple approach
-/// a) If the atom is first seen, then make that as the root atom
-/// b) The targetAtom which this Atom contains, has the root thats set to the
-/// root of the current atom
-/// c) If the targetAtom is part of a different tree and the root of the
-/// targetAtom is itself, Chain all the atoms that are contained in the tree
-/// to the current Tree
-/// d) If the targetAtom is part of a different chain and the root of the
-/// targetAtom until the targetAtom has all atoms of size 0, then chain the
-/// targetAtoms and its tree to the current chain
-void LayoutPass::buildFollowOnTable(const File::AtomRange<DefinedAtom> &range) {
- ScopedTask task(getDefaultDomain(), "LayoutPass::buildFollowOnTable");
- // Set the initial size of the followon and the followonNext hash to the
- // number of atoms that we have.
- _followOnRoots.reserve(range.size());
- _followOnNexts.reserve(range.size());
- for (const DefinedAtom *ai : range) {
- for (const Reference *r : *ai) {
- if (r->kindNamespace() != lld::Reference::KindNamespace::all ||
- r->kindValue() != lld::Reference::kindLayoutAfter)
- continue;
- const DefinedAtom *targetAtom = dyn_cast<DefinedAtom>(r->target());
- _followOnNexts[ai] = targetAtom;
-
- // If we find a followon for the first time, let's make that atom as the
- // root atom.
- if (_followOnRoots.count(ai) == 0)
- _followOnRoots[ai] = ai;
-
- auto iter = _followOnRoots.find(targetAtom);
- if (iter == _followOnRoots.end()) {
- // If the targetAtom is not a root of any chain, let's make the root of
- // the targetAtom to the root of the current chain.
-
- // The expression m[i] = m[j] where m is a DenseMap and i != j is not
- // safe. m[j] returns a reference, which would be invalidated when a
- // rehashing occurs. If rehashing occurs to make room for m[i], m[j]
- // becomes invalid, and that invalid reference would be used as the RHS
- // value of the expression.
- // Copy the value to workaround.
- const DefinedAtom *tmp = _followOnRoots[ai];
- _followOnRoots[targetAtom] = tmp;
- continue;
- }
- if (iter->second == targetAtom) {
- // If the targetAtom is the root of a chain, the chain becomes part of
- // the current chain. Rewrite the subchain's root to the current
- // chain's root.
- setChainRoot(targetAtom, _followOnRoots[ai]);
- continue;
- }
- // The targetAtom is already a part of a chain. If the current atom is
- // of size zero, we can insert it in the middle of the chain just
- // before the target atom, while not breaking other atom's followon
- // relationships. If it's not, we can only insert the current atom at
- // the beginning of the chain. All the atoms followed by the target
- // atom must be of size zero in that case to satisfy the followon
- // relationships.
- size_t currentAtomSize = ai->size();
- if (currentAtomSize == 0) {
- const DefinedAtom *targetPrevAtom = findAtomFollowedBy(targetAtom);
- _followOnNexts[targetPrevAtom] = ai;
- const DefinedAtom *tmp = _followOnRoots[targetPrevAtom];
- _followOnRoots[ai] = tmp;
- continue;
- }
- if (!checkAllPrevAtomsZeroSize(targetAtom))
- break;
- _followOnNexts[ai] = _followOnRoots[targetAtom];
- setChainRoot(_followOnRoots[targetAtom], _followOnRoots[ai]);
- }
- }
-}
-
-/// Build an ordinal override map by traversing the followon chain, and
-/// assigning ordinals to each atom, if the atoms have their ordinals
-/// already assigned skip the atom and move to the next. This is the
-/// main map thats used to sort the atoms while comparing two atoms together
-void
-LayoutPass::buildOrdinalOverrideMap(const File::AtomRange<DefinedAtom> &range) {
- ScopedTask task(getDefaultDomain(), "LayoutPass::buildOrdinalOverrideMap");
- uint64_t index = 0;
- for (const DefinedAtom *ai : range) {
- const DefinedAtom *atom = ai;
- if (_ordinalOverrideMap.find(atom) != _ordinalOverrideMap.end())
- continue;
- AtomToAtomT::iterator start = _followOnRoots.find(atom);
- if (start == _followOnRoots.end())
- continue;
- for (const DefinedAtom *nextAtom = start->second; nextAtom;
- nextAtom = _followOnNexts[nextAtom]) {
- AtomToOrdinalT::iterator pos = _ordinalOverrideMap.find(nextAtom);
- if (pos == _ordinalOverrideMap.end())
- _ordinalOverrideMap[nextAtom] = index++;
- }
- }
-}
-
-std::vector<LayoutPass::SortKey>
-LayoutPass::decorate(File::AtomRange<DefinedAtom> &atomRange) const {
- std::vector<SortKey> ret;
- for (OwningAtomPtr<DefinedAtom> &atom : atomRange.owning_ptrs()) {
- auto ri = _followOnRoots.find(atom.get());
- auto oi = _ordinalOverrideMap.find(atom.get());
- const auto *root = (ri == _followOnRoots.end()) ? atom.get() : ri->second;
- uint64_t override = (oi == _ordinalOverrideMap.end()) ? 0 : oi->second;
- ret.push_back(SortKey(std::move(atom), root, override));
- }
- return ret;
-}
-
-void LayoutPass::undecorate(File::AtomRange<DefinedAtom> &atomRange,
- std::vector<SortKey> &keys) const {
- size_t i = 0;
- for (SortKey &k : keys)
- atomRange[i++] = std::move(k._atom);
-}
-
-/// Perform the actual pass
-llvm::Error LayoutPass::perform(SimpleFile &mergedFile) {
- LLVM_DEBUG(llvm::dbgs() << "******** Laying out atoms:\n");
- // sort the atoms
- ScopedTask task(getDefaultDomain(), "LayoutPass");
- File::AtomRange<DefinedAtom> atomRange = mergedFile.defined();
-
- // Build follow on tables
- buildFollowOnTable(atomRange);
-
- // Check the structure of followon graph if running in debug mode.
- LLVM_DEBUG(checkFollowonChain(atomRange));
-
- // Build override maps
- buildOrdinalOverrideMap(atomRange);
-
- LLVM_DEBUG({
- llvm::dbgs() << "unsorted atoms:\n";
- printDefinedAtoms(atomRange);
- });
-
- std::vector<LayoutPass::SortKey> vec = decorate(atomRange);
- llvm::parallelSort(
- vec,
- [&](const LayoutPass::SortKey &l, const LayoutPass::SortKey &r) -> bool {
- return compareAtoms(l, r, _customSorter);
- });
- LLVM_DEBUG(checkTransitivity(vec, _customSorter));
- undecorate(atomRange, vec);
-
- LLVM_DEBUG({
- llvm::dbgs() << "sorted atoms:\n";
- printDefinedAtoms(atomRange);
- });
-
- LLVM_DEBUG(llvm::dbgs() << "******** Finished laying out atoms\n");
- return llvm::Error::success();
-}
-
-void addLayoutPass(PassManager &pm, const MachOLinkingContext &ctx) {
- pm.add(std::make_unique<LayoutPass>(
- ctx.registry(), [&](const DefinedAtom * left, const DefinedAtom * right,
- bool & leftBeforeRight) ->bool {
- return ctx.customAtomOrderer(left, right, leftBeforeRight);
- }));
-}
-
-} // namespace mach_o
-} // namespace lld
+++ /dev/null
-//===------ lib/ReaderWriter/MachO/LayoutPass.h - Handles Layout of atoms -===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_LAYOUT_PASS_H
-#define LLD_READER_WRITER_MACHO_LAYOUT_PASS_H
-
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
-#include <map>
-#include <string>
-#include <vector>
-
-namespace lld {
-class DefinedAtom;
-class SimpleFile;
-
-namespace mach_o {
-
-/// This linker pass does the layout of the atoms. The pass is done after the
-/// order their .o files were found on the command line, then by order of the
-/// atoms (address) in the .o file. But some atoms have a preferred location
-/// in their section (such as pinned to the start or end of the section), so
-/// the sort must take that into account too.
-class LayoutPass : public Pass {
-public:
- struct SortKey {
- SortKey(OwningAtomPtr<DefinedAtom> &&atom,
- const DefinedAtom *root, uint64_t override)
- : _atom(std::move(atom)), _root(root), _override(override) {}
- OwningAtomPtr<DefinedAtom> _atom;
- const DefinedAtom *_root;
- uint64_t _override;
-
- // Note, these are only here to appease MSVC bots which didn't like
- // the same methods being implemented/deleted in OwningAtomPtr.
- SortKey(SortKey &&key) : _atom(std::move(key._atom)), _root(key._root),
- _override(key._override) {
- key._root = nullptr;
- }
-
- SortKey &operator=(SortKey &&key) {
- _atom = std::move(key._atom);
- _root = key._root;
- key._root = nullptr;
- _override = key._override;
- return *this;
- }
-
- private:
- SortKey(const SortKey &) = delete;
- void operator=(const SortKey&) = delete;
- };
-
- typedef std::function<bool (const DefinedAtom *left, const DefinedAtom *right,
- bool &leftBeforeRight)> SortOverride;
-
- LayoutPass(const Registry ®istry, SortOverride sorter);
-
- /// Sorts atoms in mergedFile by content type then by command line order.
- llvm::Error perform(SimpleFile &mergedFile) override;
-
- ~LayoutPass() override = default;
-
-private:
- // Build the followOn atoms chain as specified by the kindLayoutAfter
- // reference type
- void buildFollowOnTable(const File::AtomRange<DefinedAtom> &range);
-
- // Build a map of Atoms to ordinals for sorting the atoms
- void buildOrdinalOverrideMap(const File::AtomRange<DefinedAtom> &range);
-
- const Registry &_registry;
- SortOverride _customSorter;
-
- typedef llvm::DenseMap<const DefinedAtom *, const DefinedAtom *> AtomToAtomT;
- typedef llvm::DenseMap<const DefinedAtom *, uint64_t> AtomToOrdinalT;
-
- // A map to be used to sort atoms. It represents the order of atoms in the
- // result; if Atom X is mapped to atom Y in this map, X will be located
- // immediately before Y in the output file. Y might be mapped to another
- // atom, constructing a follow-on chain. An atom cannot be mapped to more
- // than one atom unless all but one atom are of size zero.
- AtomToAtomT _followOnNexts;
-
- // A map to be used to sort atoms. It's a map from an atom to its root of
- // follow-on chain. A root atom is mapped to itself. If an atom is not in
- // _followOnNexts, the atom is not in this map, and vice versa.
- AtomToAtomT _followOnRoots;
-
- AtomToOrdinalT _ordinalOverrideMap;
-
- // Helper methods for buildFollowOnTable().
- const DefinedAtom *findAtomFollowedBy(const DefinedAtom *targetAtom);
- bool checkAllPrevAtomsZeroSize(const DefinedAtom *targetAtom);
-
- void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);
-
- std::vector<SortKey> decorate(File::AtomRange<DefinedAtom> &atomRange) const;
-
- void undecorate(File::AtomRange<DefinedAtom> &atomRange,
- std::vector<SortKey> &keys) const;
-
- // Check if the follow-on graph is a correct structure. For debugging only.
- void checkFollowonChain(const File::AtomRange<DefinedAtom> &range);
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_LAYOUT_PASS_H
+++ /dev/null
-//===- lib/ReaderWriter/MachO/MachOLinkingContext.cpp ---------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Common/ErrorHandler.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "ArchHandler.h"
-#include "File.h"
-#include "FlatNamespaceFile.h"
-#include "MachONormalizedFile.h"
-#include "MachOPasses.h"
-#include "SectCreateFile.h"
-#include "lld/Common/Driver.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Demangle/Demangle.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/Path.h"
-#include <algorithm>
-
-using lld::mach_o::ArchHandler;
-using lld::mach_o::MachOFile;
-using lld::mach_o::MachODylibFile;
-using namespace llvm::MachO;
-
-namespace lld {
-
-bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
- result = 0;
-
- if (str.empty())
- return false;
-
- SmallVector<StringRef, 3> parts;
- llvm::SplitString(str, parts, ".");
-
- unsigned long long num;
- if (llvm::getAsUnsignedInteger(parts[0], 10, num))
- return true;
- if (num > 65535)
- return true;
- result = num << 16;
-
- if (parts.size() > 1) {
- if (llvm::getAsUnsignedInteger(parts[1], 10, num))
- return true;
- if (num > 255)
- return true;
- result |= (num << 8);
- }
-
- if (parts.size() > 2) {
- if (llvm::getAsUnsignedInteger(parts[2], 10, num))
- return true;
- if (num > 255)
- return true;
- result |= num;
- }
-
- return false;
-}
-
-bool MachOLinkingContext::parsePackedVersion(StringRef str, uint64_t &result) {
- result = 0;
-
- if (str.empty())
- return false;
-
- SmallVector<StringRef, 5> parts;
- llvm::SplitString(str, parts, ".");
-
- unsigned long long num;
- if (llvm::getAsUnsignedInteger(parts[0], 10, num))
- return true;
- if (num > 0xFFFFFF)
- return true;
- result = num << 40;
-
- unsigned Shift = 30;
- for (StringRef str : llvm::makeArrayRef(parts).slice(1)) {
- if (llvm::getAsUnsignedInteger(str, 10, num))
- return true;
- if (num > 0x3FF)
- return true;
- result |= (num << Shift);
- Shift -= 10;
- }
-
- return false;
-}
-
-MachOLinkingContext::ArchInfo MachOLinkingContext::_s_archInfos[] = {
- { "x86_64", arch_x86_64, true, CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL },
- { "i386", arch_x86, true, CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL },
- { "ppc", arch_ppc, false, CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL },
- { "armv6", arch_armv6, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6 },
- { "armv7", arch_armv7, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7 },
- { "armv7s", arch_armv7s, true, CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S },
- { "arm64", arch_arm64, true, CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL },
- { "", arch_unknown,false, 0, 0 }
-};
-
-MachOLinkingContext::Arch
-MachOLinkingContext::archFromCpuType(uint32_t cputype, uint32_t cpusubtype) {
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if ((info->cputype == cputype) && (info->cpusubtype == cpusubtype))
- return info->arch;
- }
- return arch_unknown;
-}
-
-MachOLinkingContext::Arch
-MachOLinkingContext::archFromName(StringRef archName) {
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->archName.equals(archName))
- return info->arch;
- }
- return arch_unknown;
-}
-
-StringRef MachOLinkingContext::nameFromArch(Arch arch) {
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch)
- return info->archName;
- }
- return "<unknown>";
-}
-
-uint32_t MachOLinkingContext::cpuTypeFromArch(Arch arch) {
- assert(arch != arch_unknown);
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch)
- return info->cputype;
- }
- llvm_unreachable("Unknown arch type");
-}
-
-uint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
- assert(arch != arch_unknown);
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch)
- return info->cpusubtype;
- }
- llvm_unreachable("Unknown arch type");
-}
-
-bool MachOLinkingContext::isThinObjectFile(StringRef path, Arch &arch) {
- return mach_o::normalized::isThinObjectFile(path, arch);
-}
-
-bool MachOLinkingContext::sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset,
- uint32_t &size) {
- return mach_o::normalized::sliceFromFatFile(mb, _arch, offset, size);
-}
-
-MachOLinkingContext::MachOLinkingContext() {}
-
-MachOLinkingContext::~MachOLinkingContext() {
- // Atoms are allocated on BumpPtrAllocator's on File's.
- // As we transfer atoms from one file to another, we need to clear all of the
- // atoms before we remove any of the BumpPtrAllocator's.
- auto &nodes = getNodes();
- for (unsigned i = 0, e = nodes.size(); i != e; ++i) {
- FileNode *node = dyn_cast<FileNode>(nodes[i].get());
- if (!node)
- continue;
- File *file = node->getFile();
- file->clearAtoms();
- }
-}
-
-void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
- uint32_t minOSVersion,
- bool exportDynamicSymbols) {
- _outputMachOType = type;
- _arch = arch;
- _os = os;
- _osMinVersion = minOSVersion;
-
- // If min OS not specified on command line, use reasonable defaults.
- // Note that we only do sensible defaults when emitting something other than
- // object and preload.
- if (_outputMachOType != llvm::MachO::MH_OBJECT &&
- _outputMachOType != llvm::MachO::MH_PRELOAD) {
- if (minOSVersion == 0) {
- switch (_arch) {
- case arch_x86_64:
- case arch_x86:
- parsePackedVersion("10.8", _osMinVersion);
- _os = MachOLinkingContext::OS::macOSX;
- break;
- case arch_armv6:
- case arch_armv7:
- case arch_armv7s:
- case arch_arm64:
- parsePackedVersion("7.0", _osMinVersion);
- _os = MachOLinkingContext::OS::iOS;
- break;
- default:
- break;
- }
- }
- }
-
- switch (_outputMachOType) {
- case llvm::MachO::MH_EXECUTE:
- // If targeting newer OS, use _main
- if (minOS("10.8", "6.0")) {
- _entrySymbolName = "_main";
- } else {
- // If targeting older OS, use start (in crt1.o)
- _entrySymbolName = "start";
- }
-
- // __PAGEZERO defaults to 4GB on 64-bit (except for PP64 which lld does not
- // support) and 4KB on 32-bit.
- if (is64Bit(_arch)) {
- _pageZeroSize = 0x100000000;
- } else {
- _pageZeroSize = 0x1000;
- }
-
- // Initial base address is __PAGEZERO size.
- _baseAddress = _pageZeroSize;
-
- // Make PIE by default when targetting newer OSs.
- switch (os) {
- case OS::macOSX:
- if (minOSVersion >= 0x000A0700) // MacOSX 10.7
- _pie = true;
- break;
- case OS::iOS:
- if (minOSVersion >= 0x00040300) // iOS 4.3
- _pie = true;
- break;
- case OS::iOS_simulator:
- _pie = true;
- break;
- case OS::unknown:
- break;
- }
- setGlobalsAreDeadStripRoots(exportDynamicSymbols);
- break;
- case llvm::MachO::MH_DYLIB:
- setGlobalsAreDeadStripRoots(exportDynamicSymbols);
- break;
- case llvm::MachO::MH_BUNDLE:
- break;
- case llvm::MachO::MH_OBJECT:
- _printRemainingUndefines = false;
- _allowRemainingUndefines = true;
- break;
- default:
- break;
- }
-
- // Set default segment page sizes based on arch.
- if (arch == arch_arm64)
- _pageSize = 4*4096;
-}
-
-uint32_t MachOLinkingContext::getCPUType() const {
- return cpuTypeFromArch(_arch);
-}
-
-uint32_t MachOLinkingContext::getCPUSubType() const {
- return cpuSubtypeFromArch(_arch);
-}
-
-bool MachOLinkingContext::is64Bit(Arch arch) {
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch) {
- return (info->cputype & CPU_ARCH_ABI64);
- }
- }
- // unknown archs are not 64-bit.
- return false;
-}
-
-bool MachOLinkingContext::isHostEndian(Arch arch) {
- assert(arch != arch_unknown);
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch) {
- return (info->littleEndian == llvm::sys::IsLittleEndianHost);
- }
- }
- llvm_unreachable("Unknown arch type");
-}
-
-bool MachOLinkingContext::isBigEndian(Arch arch) {
- assert(arch != arch_unknown);
- for (ArchInfo *info = _s_archInfos; !info->archName.empty(); ++info) {
- if (info->arch == arch) {
- return ! info->littleEndian;
- }
- }
- llvm_unreachable("Unknown arch type");
-}
-
-bool MachOLinkingContext::is64Bit() const {
- return is64Bit(_arch);
-}
-
-bool MachOLinkingContext::outputTypeHasEntry() const {
- switch (_outputMachOType) {
- case MH_EXECUTE:
- case MH_DYLINKER:
- case MH_PRELOAD:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsStubsPass() const {
- switch (_outputMachOType) {
- case MH_EXECUTE:
- return !_outputMachOTypeStatic;
- case MH_DYLIB:
- case MH_BUNDLE:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsGOTPass() const {
- // GOT pass not used in -r mode.
- if (_outputMachOType == MH_OBJECT)
- return false;
- // Only some arches use GOT pass.
- switch (_arch) {
- case arch_x86_64:
- case arch_arm64:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsCompactUnwindPass() const {
- switch (_outputMachOType) {
- case MH_EXECUTE:
- case MH_DYLIB:
- case MH_BUNDLE:
- return archHandler().needsCompactUnwind();
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsObjCPass() const {
- // ObjC pass is only needed if any of the inputs were ObjC.
- return _objcConstraint != objc_unknown;
-}
-
-bool MachOLinkingContext::needsShimPass() const {
- // Shim pass only used in final executables.
- if (_outputMachOType == MH_OBJECT)
- return false;
- // Only 32-bit arm arches use Shim pass.
- switch (_arch) {
- case arch_armv6:
- case arch_armv7:
- case arch_armv7s:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::needsTLVPass() const {
- switch (_outputMachOType) {
- case MH_BUNDLE:
- case MH_EXECUTE:
- case MH_DYLIB:
- return true;
- default:
- return false;
- }
-}
-
-StringRef MachOLinkingContext::binderSymbolName() const {
- return archHandler().stubInfo().binderSymbolName;
-}
-
-bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
- uint32_t parsedVersion;
- switch (_os) {
- case OS::macOSX:
- if (parsePackedVersion(mac, parsedVersion))
- return false;
- return _osMinVersion >= parsedVersion;
- case OS::iOS:
- case OS::iOS_simulator:
- if (parsePackedVersion(iOS, parsedVersion))
- return false;
- return _osMinVersion >= parsedVersion;
- case OS::unknown:
- // If we don't know the target, then assume that we don't meet the min OS.
- // This matches the ld64 behaviour
- return false;
- }
- llvm_unreachable("invalid OS enum");
-}
-
-bool MachOLinkingContext::addEntryPointLoadCommand() const {
- if ((_outputMachOType == MH_EXECUTE) && !_outputMachOTypeStatic) {
- return minOS("10.8", "6.0");
- }
- return false;
-}
-
-bool MachOLinkingContext::addUnixThreadLoadCommand() const {
- switch (_outputMachOType) {
- case MH_EXECUTE:
- if (_outputMachOTypeStatic)
- return true;
- else
- return !minOS("10.8", "6.0");
- break;
- case MH_DYLINKER:
- case MH_PRELOAD:
- return true;
- default:
- return false;
- }
-}
-
-bool MachOLinkingContext::pathExists(StringRef path) const {
- if (!_testingFileUsage)
- return llvm::sys::fs::exists(path.str());
-
- // Otherwise, we're in test mode: only files explicitly provided on the
- // command-line exist.
- std::string key = path.str();
- std::replace(key.begin(), key.end(), '\\', '/');
- return _existingPaths.find(key) != _existingPaths.end();
-}
-
-bool MachOLinkingContext::fileExists(StringRef path) const {
- bool found = pathExists(path);
- // Log search misses.
- if (!found)
- addInputFileNotFound(path);
-
- // When testing, file is never opened, so logging is done here.
- if (_testingFileUsage && found)
- addInputFileDependency(path);
-
- return found;
-}
-
-void MachOLinkingContext::setSysLibRoots(const StringRefVector &paths) {
- _syslibRoots = paths;
-}
-
-void MachOLinkingContext::addRpath(StringRef rpath) {
- _rpaths.push_back(rpath);
-}
-
-void MachOLinkingContext::addModifiedSearchDir(StringRef libPath,
- bool isSystemPath) {
- bool addedModifiedPath = false;
-
- // -syslibroot only applies to absolute paths.
- if (libPath.startswith("/")) {
- for (auto syslibRoot : _syslibRoots) {
- SmallString<256> path(syslibRoot);
- llvm::sys::path::append(path, libPath);
- if (pathExists(path)) {
- _searchDirs.push_back(path.str().copy(_allocator));
- addedModifiedPath = true;
- }
- }
- }
-
- if (addedModifiedPath)
- return;
-
- // Finally, if only one -syslibroot is given, system paths which aren't in it
- // get suppressed.
- if (_syslibRoots.size() != 1 || !isSystemPath) {
- if (pathExists(libPath)) {
- _searchDirs.push_back(libPath);
- }
- }
-}
-
-void MachOLinkingContext::addFrameworkSearchDir(StringRef fwPath,
- bool isSystemPath) {
- bool pathAdded = false;
-
- // -syslibroot only used with to absolute framework search paths.
- if (fwPath.startswith("/")) {
- for (auto syslibRoot : _syslibRoots) {
- SmallString<256> path(syslibRoot);
- llvm::sys::path::append(path, fwPath);
- if (pathExists(path)) {
- _frameworkDirs.push_back(path.str().copy(_allocator));
- pathAdded = true;
- }
- }
- }
- // If fwPath found in any -syslibroot, then done.
- if (pathAdded)
- return;
-
- // If only one -syslibroot, system paths not in that SDK are suppressed.
- if (isSystemPath && (_syslibRoots.size() == 1))
- return;
-
- // Only use raw fwPath if that directory exists.
- if (pathExists(fwPath))
- _frameworkDirs.push_back(fwPath);
-}
-
-llvm::Optional<StringRef>
-MachOLinkingContext::searchDirForLibrary(StringRef path,
- StringRef libName) const {
- SmallString<256> fullPath;
- if (libName.endswith(".o")) {
- // A request ending in .o is special: just search for the file directly.
- fullPath.assign(path);
- llvm::sys::path::append(fullPath, libName);
- if (fileExists(fullPath))
- return fullPath.str().copy(_allocator);
- return llvm::None;
- }
-
- // Search for stub library
- fullPath.assign(path);
- llvm::sys::path::append(fullPath, Twine("lib") + libName + ".tbd");
- if (fileExists(fullPath))
- return fullPath.str().copy(_allocator);
-
- // Search for dynamic library
- fullPath.assign(path);
- llvm::sys::path::append(fullPath, Twine("lib") + libName + ".dylib");
- if (fileExists(fullPath))
- return fullPath.str().copy(_allocator);
-
- // If not, try for a static library
- fullPath.assign(path);
- llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
- if (fileExists(fullPath))
- return fullPath.str().copy(_allocator);
-
- return llvm::None;
-}
-
-llvm::Optional<StringRef>
-MachOLinkingContext::searchLibrary(StringRef libName) const {
- SmallString<256> path;
- for (StringRef dir : searchDirs()) {
- llvm::Optional<StringRef> searchDir = searchDirForLibrary(dir, libName);
- if (searchDir)
- return searchDir;
- }
-
- return llvm::None;
-}
-
-llvm::Optional<StringRef>
-MachOLinkingContext::findPathForFramework(StringRef fwName) const{
- SmallString<256> fullPath;
- for (StringRef dir : frameworkDirs()) {
- fullPath.assign(dir);
- llvm::sys::path::append(fullPath, Twine(fwName) + ".framework", fwName);
- if (fileExists(fullPath))
- return fullPath.str().copy(_allocator);
- }
-
- return llvm::None;
-}
-
-bool MachOLinkingContext::validateImpl() {
- // TODO: if -arch not specified, look at arch of first .o file.
-
- if (_currentVersion && _outputMachOType != MH_DYLIB) {
- error("-current_version can only be used with dylibs");
- return false;
- }
-
- if (_compatibilityVersion && _outputMachOType != MH_DYLIB) {
- error("-compatibility_version can only be used with dylibs");
- return false;
- }
-
- if (_deadStrippableDylib && _outputMachOType != MH_DYLIB) {
- error("-mark_dead_strippable_dylib can only be used with dylibs");
- return false;
- }
-
- if (!_bundleLoader.empty() && outputMachOType() != MH_BUNDLE) {
- error("-bundle_loader can only be used with Mach-O bundles");
- return false;
- }
-
- // If -exported_symbols_list used, all exported symbols must be defined.
- if (_exportMode == ExportMode::exported) {
- for (const auto &symbol : _exportedSymbols)
- addInitialUndefinedSymbol(symbol.getKey());
- }
-
- // If -dead_strip, set up initial live symbols.
- if (deadStrip()) {
- // Entry point is live.
- if (outputTypeHasEntry())
- addDeadStripRoot(entrySymbolName());
- // Lazy binding helper is live.
- if (needsStubsPass())
- addDeadStripRoot(binderSymbolName());
- // If using -exported_symbols_list, make all exported symbols live.
- if (_exportMode == ExportMode::exported) {
- setGlobalsAreDeadStripRoots(false);
- for (const auto &symbol : _exportedSymbols)
- addDeadStripRoot(symbol.getKey());
- }
- }
-
- addOutputFileDependency(outputPath());
-
- return true;
-}
-
-void MachOLinkingContext::addPasses(PassManager &pm) {
- // objc pass should be before layout pass. Otherwise test cases may contain
- // no atoms which confuses the layout pass.
- if (needsObjCPass())
- mach_o::addObjCPass(pm, *this);
- mach_o::addLayoutPass(pm, *this);
- if (needsStubsPass())
- mach_o::addStubsPass(pm, *this);
- if (needsCompactUnwindPass())
- mach_o::addCompactUnwindPass(pm, *this);
- if (needsGOTPass())
- mach_o::addGOTPass(pm, *this);
- if (needsTLVPass())
- mach_o::addTLVPass(pm, *this);
- if (needsShimPass())
- mach_o::addShimPass(pm, *this); // Shim pass must run after stubs pass.
-}
-
-Writer &MachOLinkingContext::writer() const {
- if (!_writer)
- _writer = createWriterMachO(*this);
- return *_writer;
-}
-
-ErrorOr<std::unique_ptr<MemoryBuffer>>
-MachOLinkingContext::getMemoryBuffer(StringRef path) {
- addInputFileDependency(path);
-
- ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
- MemoryBuffer::getFileOrSTDIN(path);
- if (std::error_code ec = mbOrErr.getError())
- return ec;
- std::unique_ptr<MemoryBuffer> mb = std::move(mbOrErr.get());
-
- // If buffer contains a fat file, find required arch in fat buffer
- // and switch buffer to point to just that required slice.
- uint32_t offset;
- uint32_t size;
- if (sliceFromFatFile(mb->getMemBufferRef(), offset, size))
- return MemoryBuffer::getFileSlice(path, size, offset);
- return std::move(mb);
-}
-
-MachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = getMemoryBuffer(path);
- if (mbOrErr.getError())
- return nullptr;
-
- ErrorOr<std::unique_ptr<File>> fileOrErr =
- registry().loadFile(std::move(mbOrErr.get()));
- if (!fileOrErr)
- return nullptr;
- std::unique_ptr<File> &file = fileOrErr.get();
- file->parse();
- MachODylibFile *result = reinterpret_cast<MachODylibFile *>(file.get());
- // Node object now owned by _indirectDylibs vector.
- _indirectDylibs.push_back(std::move(file));
- return result;
-}
-
-MachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) {
- // See if already loaded.
- auto pos = _pathToDylibMap.find(path);
- if (pos != _pathToDylibMap.end())
- return pos->second;
-
- // Search -L paths if of the form "libXXX.dylib"
- std::pair<StringRef, StringRef> split = path.rsplit('/');
- StringRef leafName = split.second;
- if (leafName.startswith("lib") && leafName.endswith(".dylib")) {
- // FIXME: Need to enhance searchLibrary() to only look for .dylib
- auto libPath = searchLibrary(leafName);
- if (libPath)
- return loadIndirectDylib(libPath.getValue());
- }
-
- // Try full path with sysroot.
- for (StringRef sysPath : _syslibRoots) {
- SmallString<256> fullPath;
- fullPath.assign(sysPath);
- llvm::sys::path::append(fullPath, path);
- if (pathExists(fullPath))
- return loadIndirectDylib(fullPath);
- }
-
- // Try full path.
- if (pathExists(path)) {
- return loadIndirectDylib(path);
- }
-
- return nullptr;
-}
-
-uint32_t MachOLinkingContext::dylibCurrentVersion(StringRef installName) const {
- auto pos = _pathToDylibMap.find(installName);
- if (pos != _pathToDylibMap.end())
- return pos->second->currentVersion();
- else
- return 0x10000; // 1.0
-}
-
-uint32_t MachOLinkingContext::dylibCompatVersion(StringRef installName) const {
- auto pos = _pathToDylibMap.find(installName);
- if (pos != _pathToDylibMap.end())
- return pos->second->compatVersion();
- else
- return 0x10000; // 1.0
-}
-
-void MachOLinkingContext::createImplicitFiles(
- std::vector<std::unique_ptr<File> > &result) {
- // Add indirect dylibs by asking each linked dylib to add its indirects.
- // Iterate until no more dylibs get loaded.
- size_t dylibCount = 0;
- while (dylibCount != _allDylibs.size()) {
- dylibCount = _allDylibs.size();
- for (MachODylibFile *dylib : _allDylibs) {
- dylib->loadReExportedDylibs([this] (StringRef path) -> MachODylibFile* {
- return findIndirectDylib(path); });
- }
- }
-
- // Let writer add output type specific extras.
- writer().createImplicitFiles(result);
-
- // If undefinedMode is != error, add a FlatNamespaceFile instance. This will
- // provide a SharedLibraryAtom for symbols that aren't defined elsewhere.
- if (undefinedMode() != UndefinedMode::error) {
- result.emplace_back(new mach_o::FlatNamespaceFile(*this));
- _flatNamespaceFile = result.back().get();
- }
-}
-
-void MachOLinkingContext::registerDylib(MachODylibFile *dylib,
- bool upward) const {
- std::lock_guard<std::mutex> lock(_dylibsMutex);
-
- if (!llvm::count(_allDylibs, dylib))
- _allDylibs.push_back(dylib);
- _pathToDylibMap[dylib->installName()] = dylib;
- // If path is different than install name, register path too.
- if (!dylib->path().equals(dylib->installName()))
- _pathToDylibMap[dylib->path()] = dylib;
- if (upward)
- _upwardDylibs.insert(dylib);
-}
-
-bool MachOLinkingContext::isUpwardDylib(StringRef installName) const {
- for (MachODylibFile *dylib : _upwardDylibs) {
- if (dylib->installName().equals(installName))
- return true;
- }
- return false;
-}
-
-ArchHandler &MachOLinkingContext::archHandler() const {
- if (!_archHandler)
- _archHandler = ArchHandler::create(_arch);
- return *_archHandler;
-}
-
-void MachOLinkingContext::addSectionAlignment(StringRef seg, StringRef sect,
- uint16_t align) {
- SectionAlign entry = { seg, sect, align };
- _sectAligns.push_back(entry);
-}
-
-void MachOLinkingContext::addSectCreateSection(
- StringRef seg, StringRef sect,
- std::unique_ptr<MemoryBuffer> content) {
-
- if (!_sectCreateFile) {
- auto sectCreateFile = std::make_unique<mach_o::SectCreateFile>();
- _sectCreateFile = sectCreateFile.get();
- getNodes().push_back(std::make_unique<FileNode>(std::move(sectCreateFile)));
- }
-
- assert(_sectCreateFile && "sectcreate file does not exist.");
- _sectCreateFile->addSection(seg, sect, std::move(content));
-}
-
-bool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect,
- uint16_t &align) const {
- for (const SectionAlign &entry : _sectAligns) {
- if (seg.equals(entry.segmentName) && sect.equals(entry.sectionName)) {
- align = entry.align;
- return true;
- }
- }
- return false;
-}
-
-void MachOLinkingContext::addExportSymbol(StringRef sym) {
- // Support old crufty export lists with bogus entries.
- if (sym.endswith(".eh") || sym.startswith(".objc_category_name_")) {
- llvm::errs() << "warning: ignoring " << sym << " in export list\n";
- return;
- }
- // Only i386 MacOSX uses old ABI, so don't change those.
- if ((_os != OS::macOSX) || (_arch != arch_x86)) {
- // ObjC has two different ABIs. Be nice and allow one export list work for
- // both ABIs by renaming symbols.
- if (sym.startswith(".objc_class_name_")) {
- std::string abi2className("_OBJC_CLASS_$_");
- abi2className += sym.substr(17);
- _exportedSymbols.insert(copy(abi2className));
- std::string abi2metaclassName("_OBJC_METACLASS_$_");
- abi2metaclassName += sym.substr(17);
- _exportedSymbols.insert(copy(abi2metaclassName));
- return;
- }
- }
-
- // FIXME: Support wildcards.
- _exportedSymbols.insert(sym);
-}
-
-bool MachOLinkingContext::exportSymbolNamed(StringRef sym) const {
- switch (_exportMode) {
- case ExportMode::globals:
- llvm_unreachable("exportSymbolNamed() should not be called in this mode");
- break;
- case ExportMode::exported:
- return _exportedSymbols.count(sym);
- case ExportMode::unexported:
- return !_exportedSymbols.count(sym);
- }
- llvm_unreachable("_exportMode unknown enum value");
-}
-
-std::string MachOLinkingContext::demangle(StringRef symbolName) const {
- // Only try to demangle symbols if -demangle on command line
- if (!demangleSymbols())
- return std::string(symbolName);
-
- // Only try to demangle symbols that look like C++ symbols
- if (!symbolName.startswith("__Z"))
- return std::string(symbolName);
-
- SmallString<256> symBuff;
- StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
- // Mach-O has extra leading underscore that needs to be removed.
- const char *cstr = nullTermSym.data() + 1;
- int status;
- char *demangled = llvm::itaniumDemangle(cstr, nullptr, nullptr, &status);
- if (demangled) {
- std::string result(demangled);
- // __cxa_demangle() always uses a malloc'ed buffer to return the result.
- free(demangled);
- return result;
- }
-
- return std::string(symbolName);
-}
-
-static void addDependencyInfoHelper(llvm::raw_fd_ostream *DepInfo,
- char Opcode, StringRef Path) {
- if (!DepInfo)
- return;
-
- *DepInfo << Opcode;
- *DepInfo << Path;
- *DepInfo << '\0';
-}
-
-std::error_code MachOLinkingContext::createDependencyFile(StringRef path) {
- std::error_code ec;
- _dependencyInfo = std::unique_ptr<llvm::raw_fd_ostream>(
- new llvm::raw_fd_ostream(path, ec, llvm::sys::fs::OF_None));
- if (ec) {
- _dependencyInfo.reset();
- return ec;
- }
-
- addDependencyInfoHelper(_dependencyInfo.get(), 0x00, "lld" /*FIXME*/);
- return std::error_code();
-}
-
-void MachOLinkingContext::addInputFileDependency(StringRef path) const {
- addDependencyInfoHelper(_dependencyInfo.get(), 0x10, path);
-}
-
-void MachOLinkingContext::addInputFileNotFound(StringRef path) const {
- addDependencyInfoHelper(_dependencyInfo.get(), 0x11, path);
-}
-
-void MachOLinkingContext::addOutputFileDependency(StringRef path) const {
- addDependencyInfoHelper(_dependencyInfo.get(), 0x40, path);
-}
-
-void MachOLinkingContext::appendOrderedSymbol(StringRef symbol,
- StringRef filename) {
- // To support sorting static functions which may have the same name in
- // multiple .o files, _orderFiles maps the symbol name to a vector
- // of OrderFileNode each of which can specify a file prefix.
- OrderFileNode info;
- if (!filename.empty())
- info.fileFilter = copy(filename);
- info.order = _orderFileEntries++;
- _orderFiles[symbol].push_back(info);
-}
-
-bool
-MachOLinkingContext::findOrderOrdinal(const std::vector<OrderFileNode> &nodes,
- const DefinedAtom *atom,
- unsigned &ordinal) {
- const File *objFile = &atom->file();
- assert(objFile);
- StringRef objName = objFile->path();
- std::pair<StringRef, StringRef> dirAndLeaf = objName.rsplit('/');
- if (!dirAndLeaf.second.empty())
- objName = dirAndLeaf.second;
- for (const OrderFileNode &info : nodes) {
- if (info.fileFilter.empty()) {
- // Have unprefixed symbol name in order file that matches this atom.
- ordinal = info.order;
- return true;
- }
- if (info.fileFilter.equals(objName)) {
- // Have prefixed symbol name in order file that matches atom's path.
- ordinal = info.order;
- return true;
- }
- }
- return false;
-}
-
-bool MachOLinkingContext::customAtomOrderer(const DefinedAtom *left,
- const DefinedAtom *right,
- bool &leftBeforeRight) const {
- // No custom sorting if no order file entries.
- if (!_orderFileEntries)
- return false;
-
- // Order files can only order named atoms.
- StringRef leftName = left->name();
- StringRef rightName = right->name();
- if (leftName.empty() || rightName.empty())
- return false;
-
- // If neither is in order file list, no custom sorter.
- auto leftPos = _orderFiles.find(leftName);
- auto rightPos = _orderFiles.find(rightName);
- bool leftIsOrdered = (leftPos != _orderFiles.end());
- bool rightIsOrdered = (rightPos != _orderFiles.end());
- if (!leftIsOrdered && !rightIsOrdered)
- return false;
-
- // There could be multiple symbols with same name but different file prefixes.
- unsigned leftOrder;
- unsigned rightOrder;
- bool foundLeft =
- leftIsOrdered && findOrderOrdinal(leftPos->getValue(), left, leftOrder);
- bool foundRight = rightIsOrdered &&
- findOrderOrdinal(rightPos->getValue(), right, rightOrder);
- if (!foundLeft && !foundRight)
- return false;
-
- // If only one is in order file list, ordered one goes first.
- if (foundLeft != foundRight)
- leftBeforeRight = foundLeft;
- else
- leftBeforeRight = (leftOrder < rightOrder);
-
- return true;
-}
-
-static bool isLibrary(const std::unique_ptr<Node> &elem) {
- if (FileNode *node = dyn_cast<FileNode>(const_cast<Node *>(elem.get()))) {
- File *file = node->getFile();
- return isa<SharedLibraryFile>(file) || isa<ArchiveLibraryFile>(file);
- }
- return false;
-}
-
-// The darwin linker processes input files in two phases. The first phase
-// links in all object (.o) files in command line order. The second phase
-// links in libraries in command line order.
-// In this function we reorder the input files so that all the object files
-// comes before any library file. We also make a group for the library files
-// so that the Resolver will reiterate over the libraries as long as we find
-// new undefines from libraries.
-void MachOLinkingContext::finalizeInputFiles() {
- std::vector<std::unique_ptr<Node>> &elements = getNodes();
- llvm::stable_sort(elements, [](const std::unique_ptr<Node> &a,
- const std::unique_ptr<Node> &b) {
- return !isLibrary(a) && isLibrary(b);
- });
- size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary);
- elements.push_back(std::make_unique<GroupEnd>(numLibs));
-}
-
-llvm::Error MachOLinkingContext::handleLoadedFile(File &file) {
- auto *machoFile = dyn_cast<MachOFile>(&file);
- if (!machoFile)
- return llvm::Error::success();
-
- // Check that the arch of the context matches that of the file.
- // Also set the arch of the context if it didn't have one.
- if (_arch == arch_unknown) {
- _arch = machoFile->arch();
- } else if (machoFile->arch() != arch_unknown && machoFile->arch() != _arch) {
- // Archs are different.
- return llvm::make_error<GenericError>(file.path() +
- Twine(" cannot be linked due to incompatible architecture"));
- }
-
- // Check that the OS of the context matches that of the file.
- // Also set the OS of the context if it didn't have one.
- if (_os == OS::unknown) {
- _os = machoFile->OS();
- } else if (machoFile->OS() != OS::unknown && machoFile->OS() != _os) {
- // OSes are different.
- return llvm::make_error<GenericError>(file.path() +
- Twine(" cannot be linked due to incompatible operating systems"));
- }
-
- // Check that if the objc info exists, that it is compatible with the target
- // OS.
- switch (machoFile->objcConstraint()) {
- case objc_unknown:
- // The file is not compiled with objc, so skip the checks.
- break;
- case objc_gc_only:
- case objc_supports_gc:
- llvm_unreachable("GC support should already have thrown an error");
- case objc_retainReleaseForSimulator:
- // The file is built with simulator objc, so make sure that the context
- // is also building with simulator support.
- if (_os != OS::iOS_simulator)
- return llvm::make_error<GenericError>(file.path() +
- Twine(" cannot be linked. It contains ObjC built for the simulator"
- " while we are linking a non-simulator target"));
- assert((_objcConstraint == objc_unknown ||
- _objcConstraint == objc_retainReleaseForSimulator) &&
- "Must be linking with retain/release for the simulator");
- _objcConstraint = objc_retainReleaseForSimulator;
- break;
- case objc_retainRelease:
- // The file is built without simulator objc, so make sure that the
- // context is also building without simulator support.
- if (_os == OS::iOS_simulator)
- return llvm::make_error<GenericError>(file.path() +
- Twine(" cannot be linked. It contains ObjC built for a non-simulator"
- " target while we are linking a simulator target"));
- assert((_objcConstraint == objc_unknown ||
- _objcConstraint == objc_retainRelease) &&
- "Must be linking with retain/release for a non-simulator target");
- _objcConstraint = objc_retainRelease;
- break;
- }
-
- // Check that the swift version of the context matches that of the file.
- // Also set the swift version of the context if it didn't have one.
- if (!_swiftVersion) {
- _swiftVersion = machoFile->swiftVersion();
- } else if (machoFile->swiftVersion() &&
- machoFile->swiftVersion() != _swiftVersion) {
- // Swift versions are different.
- return llvm::make_error<GenericError>("different swift versions");
- }
-
- return llvm::Error::success();
-}
-
-} // end namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/MachONormalizedFile.h -----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file These data structures comprise the "normalized" view of
-/// mach-o object files. The normalized view is an in-memory only data structure
-/// which is always in native endianness and pointer size.
-///
-/// The normalized view easily converts to and from YAML using YAML I/O.
-///
-/// The normalized view converts to and from binary mach-o object files using
-/// the writeBinary() and readBinary() functions.
-///
-/// The normalized view converts to and from lld::Atoms using the
-/// normalizedToAtoms() and normalizedFromAtoms().
-///
-/// Overall, the conversion paths available look like:
-///
-/// +---------------+
-/// | binary mach-o |
-/// +---------------+
-/// ^
-/// |
-/// v
-/// +------------+ +------+
-/// | normalized | <-> | yaml |
-/// +------------+ +------+
-/// ^
-/// |
-/// v
-/// +-------+
-/// | Atoms |
-/// +-------+
-///
-
-#ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
-#define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
-
-#include "DebugInfo.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/YAMLTraits.h"
-
-using llvm::BumpPtrAllocator;
-using llvm::yaml::Hex64;
-using llvm::yaml::Hex32;
-using llvm::yaml::Hex16;
-using llvm::yaml::Hex8;
-using llvm::yaml::SequenceTraits;
-using llvm::MachO::HeaderFileType;
-using llvm::MachO::BindType;
-using llvm::MachO::RebaseType;
-using llvm::MachO::NListType;
-using llvm::MachO::RelocationInfoType;
-using llvm::MachO::SectionType;
-using llvm::MachO::LoadCommandType;
-using llvm::MachO::ExportSymbolKind;
-using llvm::MachO::DataRegionType;
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-
-/// The real mach-o relocation record is 8-bytes on disk and is
-/// encoded in one of two different bit-field patterns. This
-/// normalized form has the union of all possible fields.
-struct Relocation {
- Relocation() : offset(0), scattered(false),
- type(llvm::MachO::GENERIC_RELOC_VANILLA),
- length(0), pcRel(false), isExtern(false), value(0),
- symbol(0) { }
-
- Hex32 offset;
- bool scattered;
- RelocationInfoType type;
- uint8_t length;
- bool pcRel;
- bool isExtern;
- Hex32 value;
- uint32_t symbol;
-};
-
-/// A typedef so that YAML I/O can treat this vector as a sequence.
-typedef std::vector<Relocation> Relocations;
-
-/// A typedef so that YAML I/O can process the raw bytes in a section.
-typedef std::vector<Hex8> ContentBytes;
-
-/// A typedef so that YAML I/O can treat indirect symbols as a flow sequence.
-typedef std::vector<uint32_t> IndirectSymbols;
-
-/// A typedef so that YAML I/O can encode/decode section attributes.
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionAttr)
-
-/// A typedef so that YAML I/O can encode/decode section alignment.
-LLVM_YAML_STRONG_TYPEDEF(uint16_t, SectionAlignment)
-
-/// Mach-O has a 32-bit and 64-bit section record. This normalized form
-/// can support either kind.
-struct Section {
- Section() : type(llvm::MachO::S_REGULAR),
- attributes(0), alignment(1), address(0) { }
-
- StringRef segmentName;
- StringRef sectionName;
- SectionType type;
- SectionAttr attributes;
- SectionAlignment alignment;
- Hex64 address;
- ArrayRef<uint8_t> content;
- Relocations relocations;
- IndirectSymbols indirectSymbols;
-};
-
-
-/// A typedef so that YAML I/O can encode/decode the scope bits of an nlist.
-LLVM_YAML_STRONG_TYPEDEF(uint8_t, SymbolScope)
-
-/// A typedef so that YAML I/O can encode/decode the desc bits of an nlist.
-LLVM_YAML_STRONG_TYPEDEF(uint16_t, SymbolDesc)
-
-/// Mach-O has a 32-bit and 64-bit symbol table entry (nlist), and the symbol
-/// type and scope and mixed in the same n_type field. This normalized form
-/// works for any pointer size and separates out the type and scope.
-struct Symbol {
- Symbol() : type(llvm::MachO::N_UNDF), scope(0), sect(0), desc(0), value(0) { }
-
- StringRef name;
- NListType type;
- SymbolScope scope;
- uint8_t sect;
- SymbolDesc desc;
- Hex64 value;
-};
-
-/// Check whether the given section type indicates a zero-filled section.
-// FIXME: Utility functions of this kind should probably be moved into
-// llvm/Support.
-inline bool isZeroFillSection(SectionType T) {
- return (T == llvm::MachO::S_ZEROFILL ||
- T == llvm::MachO::S_THREAD_LOCAL_ZEROFILL);
-}
-
-/// A typedef so that YAML I/O can (de/en)code the protection bits of a segment.
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, VMProtect)
-
-/// A typedef to hold verions X.Y.X packed into 32-bit xxxx.yy.zz
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, PackedVersion)
-
-/// Segments are only used in normalized final linked images (not in relocatable
-/// object files). They specify how a range of the file is loaded.
-struct Segment {
- StringRef name;
- Hex64 address;
- Hex64 size;
- VMProtect init_access;
- VMProtect max_access;
-};
-
-/// Only used in normalized final linked images to specify on which dylibs
-/// it depends.
-struct DependentDylib {
- StringRef path;
- LoadCommandType kind;
- PackedVersion compatVersion;
- PackedVersion currentVersion;
-};
-
-/// A normalized rebasing entry. Only used in normalized final linked images.
-struct RebaseLocation {
- Hex32 segOffset;
- uint8_t segIndex;
- RebaseType kind;
-};
-
-/// A normalized binding entry. Only used in normalized final linked images.
-struct BindLocation {
- Hex32 segOffset;
- uint8_t segIndex;
- BindType kind;
- bool canBeNull;
- int ordinal;
- StringRef symbolName;
- Hex64 addend;
-};
-
-/// A typedef so that YAML I/O can encode/decode export flags.
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportFlags)
-
-/// A normalized export entry. Only used in normalized final linked images.
-struct Export {
- StringRef name;
- Hex64 offset;
- ExportSymbolKind kind;
- ExportFlags flags;
- Hex32 otherOffset;
- StringRef otherName;
-};
-
-/// A normalized data-in-code entry.
-struct DataInCode {
- Hex32 offset;
- Hex16 length;
- DataRegionType kind;
-};
-
-/// A typedef so that YAML I/O can encode/decode mach_header.flags.
-LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags)
-
-///
-struct NormalizedFile {
- MachOLinkingContext::Arch arch = MachOLinkingContext::arch_unknown;
- HeaderFileType fileType = llvm::MachO::MH_OBJECT;
- FileFlags flags = 0;
- std::vector<Segment> segments; // Not used in object files.
- std::vector<Section> sections;
-
- // Symbols sorted by kind.
- std::vector<Symbol> localSymbols;
- std::vector<Symbol> globalSymbols;
- std::vector<Symbol> undefinedSymbols;
- std::vector<Symbol> stabsSymbols;
-
- // Maps to load commands with no LINKEDIT content (final linked images only).
- std::vector<DependentDylib> dependentDylibs;
- StringRef installName; // dylibs only
- PackedVersion compatVersion = 0; // dylibs only
- PackedVersion currentVersion = 0; // dylibs only
- bool hasUUID = false;
- bool hasMinVersionLoadCommand = false;
- bool generateDataInCodeLoadCommand = false;
- std::vector<StringRef> rpaths;
- Hex64 entryAddress = 0;
- Hex64 stackSize = 0;
- MachOLinkingContext::OS os = MachOLinkingContext::OS::unknown;
- Hex64 sourceVersion = 0;
- PackedVersion minOSverson = 0;
- PackedVersion sdkVersion = 0;
- LoadCommandType minOSVersionKind = (LoadCommandType)0;
-
- // Maps to load commands with LINKEDIT content (final linked images only).
- Hex32 pageSize = 0;
- std::vector<RebaseLocation> rebasingInfo;
- std::vector<BindLocation> bindingInfo;
- std::vector<BindLocation> weakBindingInfo;
- std::vector<BindLocation> lazyBindingInfo;
- std::vector<Export> exportInfo;
- std::vector<uint8_t> functionStarts;
- std::vector<DataInCode> dataInCode;
-
- // TODO:
- // code-signature
- // split-seg-info
- // function-starts
-
- // For any allocations in this struct which need to be owned by this struct.
- BumpPtrAllocator ownedAllocations;
-};
-
-/// Tests if a file is a non-fat mach-o object file.
-bool isThinObjectFile(StringRef path, MachOLinkingContext::Arch &arch);
-
-/// If the buffer is a fat file with the request arch, then this function
-/// returns true with 'offset' and 'size' set to location of the arch slice
-/// within the buffer. Otherwise returns false;
-bool sliceFromFatFile(MemoryBufferRef mb, MachOLinkingContext::Arch arch,
- uint32_t &offset, uint32_t &size);
-
-/// Reads a mach-o file and produces an in-memory normalized view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-readBinary(std::unique_ptr<MemoryBuffer> &mb,
- const MachOLinkingContext::Arch arch);
-
-/// Takes in-memory normalized view and writes a mach-o object file.
-llvm::Error writeBinary(const NormalizedFile &file, StringRef path);
-
-size_t headerAndLoadCommandsSize(const NormalizedFile &file,
- bool includeFunctionStarts);
-
-
-/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-readYaml(std::unique_ptr<MemoryBuffer> &mb);
-
-/// Writes a yaml encoded mach-o files given an in-memory normalized view.
-std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out);
-
-llvm::Error
-normalizedObjectToAtoms(MachOFile *file,
- const NormalizedFile &normalizedFile,
- bool copyRefs);
-
-llvm::Error
-normalizedDylibToAtoms(MachODylibFile *file,
- const NormalizedFile &normalizedFile,
- bool copyRefs);
-
-/// Takes in-memory normalized dylib or object and parses it into lld::File
-llvm::Expected<std::unique_ptr<lld::File>>
-normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
- bool copyRefs);
-
-/// Takes atoms and generates a normalized macho-o view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext &ctxt);
-
-
-} // namespace normalized
-
-/// Class for interfacing mach-o yaml files into generic yaml parsing
-class MachOYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
-public:
- MachOYamlIOTaggedDocumentHandler(MachOLinkingContext::Arch arch)
- : _arch(arch) { }
- bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override;
-private:
- const MachOLinkingContext::Arch _arch;
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
+++ /dev/null
-//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp ---------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file For mach-o object files, this implementation converts from
-/// mach-o on-disk binary format to in-memory normalized mach-o.
-///
-/// +---------------+
-/// | binary mach-o |
-/// +---------------+
-/// |
-/// |
-/// v
-/// +------------+
-/// | normalized |
-/// +------------+
-
-#include "ArchHandler.h"
-#include "MachONormalizedFile.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/Object/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <functional>
-#include <system_error>
-
-using namespace llvm::MachO;
-using llvm::object::ExportEntry;
-using llvm::file_magic;
-using llvm::object::MachOObjectFile;
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-// Utility to call a lambda expression on each load command.
-static llvm::Error forEachLoadCommand(
- StringRef lcRange, unsigned lcCount, bool isBig, bool is64,
- std::function<bool(uint32_t cmd, uint32_t size, const char *lc)> func) {
- const char* p = lcRange.begin();
- for (unsigned i=0; i < lcCount; ++i) {
- const load_command *lc = reinterpret_cast<const load_command*>(p);
- load_command lcCopy;
- const load_command *slc = lc;
- if (isBig != llvm::sys::IsBigEndianHost) {
- memcpy(&lcCopy, lc, sizeof(load_command));
- swapStruct(lcCopy);
- slc = &lcCopy;
- }
- if ( (p + slc->cmdsize) > lcRange.end() )
- return llvm::make_error<GenericError>("Load command exceeds range");
-
- if (func(slc->cmd, slc->cmdsize, p))
- return llvm::Error::success();
-
- p += slc->cmdsize;
- }
-
- return llvm::Error::success();
-}
-
-static std::error_code appendRelocations(Relocations &relocs, StringRef buffer,
- bool bigEndian,
- uint32_t reloff, uint32_t nreloc) {
- if ((reloff + nreloc*8) > buffer.size())
- return make_error_code(llvm::errc::executable_format_error);
- const any_relocation_info* relocsArray =
- reinterpret_cast<const any_relocation_info*>(buffer.begin()+reloff);
-
- for(uint32_t i=0; i < nreloc; ++i) {
- relocs.push_back(unpackRelocation(relocsArray[i], bigEndian));
- }
- return std::error_code();
-}
-
-static std::error_code
-appendIndirectSymbols(IndirectSymbols &isyms, StringRef buffer, bool isBig,
- uint32_t istOffset, uint32_t istCount,
- uint32_t startIndex, uint32_t count) {
- if ((istOffset + istCount*4) > buffer.size())
- return make_error_code(llvm::errc::executable_format_error);
- if (startIndex+count > istCount)
- return make_error_code(llvm::errc::executable_format_error);
- const uint8_t *indirectSymbolArray = (const uint8_t *)buffer.data();
-
- for(uint32_t i=0; i < count; ++i) {
- isyms.push_back(read32(
- indirectSymbolArray + (startIndex + i) * sizeof(uint32_t), isBig));
- }
- return std::error_code();
-}
-
-
-template <typename T> static T readBigEndian(T t) {
- if (llvm::sys::IsLittleEndianHost)
- llvm::sys::swapByteOrder(t);
- return t;
-}
-
-
-static bool isMachOHeader(const mach_header *mh, bool &is64, bool &isBig) {
- switch (read32(&mh->magic, false)) {
- case llvm::MachO::MH_MAGIC:
- is64 = false;
- isBig = false;
- return true;
- case llvm::MachO::MH_MAGIC_64:
- is64 = true;
- isBig = false;
- return true;
- case llvm::MachO::MH_CIGAM:
- is64 = false;
- isBig = true;
- return true;
- case llvm::MachO::MH_CIGAM_64:
- is64 = true;
- isBig = true;
- return true;
- default:
- return false;
- }
-}
-
-
-bool isThinObjectFile(StringRef path, MachOLinkingContext::Arch &arch) {
- // Try opening and mapping file at path.
- ErrorOr<std::unique_ptr<MemoryBuffer>> b = MemoryBuffer::getFileOrSTDIN(path);
- if (b.getError())
- return false;
-
- // If file length < 32 it is too small to be mach-o object file.
- StringRef fileBuffer = b->get()->getBuffer();
- if (fileBuffer.size() < 32)
- return false;
-
- // If file buffer does not start with MH_MAGIC (and variants), not obj file.
- const mach_header *mh = reinterpret_cast<const mach_header *>(
- fileBuffer.begin());
- bool is64, isBig;
- if (!isMachOHeader(mh, is64, isBig))
- return false;
-
- // If not MH_OBJECT, not object file.
- if (read32(&mh->filetype, isBig) != MH_OBJECT)
- return false;
-
- // Lookup up arch from cpu/subtype pair.
- arch = MachOLinkingContext::archFromCpuType(
- read32(&mh->cputype, isBig),
- read32(&mh->cpusubtype, isBig));
- return true;
-}
-
-bool sliceFromFatFile(MemoryBufferRef mb, MachOLinkingContext::Arch arch,
- uint32_t &offset, uint32_t &size) {
- const char *start = mb.getBufferStart();
- const llvm::MachO::fat_header *fh =
- reinterpret_cast<const llvm::MachO::fat_header *>(start);
- if (readBigEndian(fh->magic) != llvm::MachO::FAT_MAGIC)
- return false;
- uint32_t nfat_arch = readBigEndian(fh->nfat_arch);
- const fat_arch *fstart =
- reinterpret_cast<const fat_arch *>(start + sizeof(fat_header));
- const fat_arch *fend =
- reinterpret_cast<const fat_arch *>(start + sizeof(fat_header) +
- sizeof(fat_arch) * nfat_arch);
- const uint32_t reqCpuType = MachOLinkingContext::cpuTypeFromArch(arch);
- const uint32_t reqCpuSubtype = MachOLinkingContext::cpuSubtypeFromArch(arch);
- for (const fat_arch *fa = fstart; fa < fend; ++fa) {
- if ((readBigEndian(fa->cputype) == reqCpuType) &&
- (readBigEndian(fa->cpusubtype) == reqCpuSubtype)) {
- offset = readBigEndian(fa->offset);
- size = readBigEndian(fa->size);
- if ((offset + size) > mb.getBufferSize())
- return false;
- return true;
- }
- }
- return false;
-}
-
-/// Reads a mach-o file and produces an in-memory normalized view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-readBinary(std::unique_ptr<MemoryBuffer> &mb,
- const MachOLinkingContext::Arch arch) {
- // Make empty NormalizedFile.
- std::unique_ptr<NormalizedFile> f(new NormalizedFile());
-
- const char *start = mb->getBufferStart();
- size_t objSize = mb->getBufferSize();
- const mach_header *mh = reinterpret_cast<const mach_header *>(start);
-
- uint32_t sliceOffset;
- uint32_t sliceSize;
- if (sliceFromFatFile(mb->getMemBufferRef(), arch, sliceOffset, sliceSize)) {
- start = &start[sliceOffset];
- objSize = sliceSize;
- mh = reinterpret_cast<const mach_header *>(start);
- }
-
- // Determine endianness and pointer size for mach-o file.
- bool is64, isBig;
- if (!isMachOHeader(mh, is64, isBig))
- return llvm::make_error<GenericError>("File is not a mach-o");
-
- // Endian swap header, if needed.
- mach_header headerCopy;
- const mach_header *smh = mh;
- if (isBig != llvm::sys::IsBigEndianHost) {
- memcpy(&headerCopy, mh, sizeof(mach_header));
- swapStruct(headerCopy);
- smh = &headerCopy;
- }
-
- // Validate head and load commands fit in buffer.
- const uint32_t lcCount = smh->ncmds;
- const char *lcStart =
- start + (is64 ? sizeof(mach_header_64) : sizeof(mach_header));
- StringRef lcRange(lcStart, smh->sizeofcmds);
- if (lcRange.end() > (start + objSize))
- return llvm::make_error<GenericError>("Load commands exceed file size");
-
- // Get architecture from mach_header.
- f->arch = MachOLinkingContext::archFromCpuType(smh->cputype, smh->cpusubtype);
- if (f->arch != arch) {
- return llvm::make_error<GenericError>(
- Twine("file is wrong architecture. Expected "
- "(" + MachOLinkingContext::nameFromArch(arch)
- + ") found ("
- + MachOLinkingContext::nameFromArch(f->arch)
- + ")" ));
- }
- // Copy file type and flags
- f->fileType = HeaderFileType(smh->filetype);
- f->flags = smh->flags;
-
-
- // Pre-scan load commands looking for indirect symbol table.
- uint32_t indirectSymbolTableOffset = 0;
- uint32_t indirectSymbolTableCount = 0;
- auto ec = forEachLoadCommand(lcRange, lcCount, isBig, is64,
- [&](uint32_t cmd, uint32_t size,
- const char *lc) -> bool {
- if (cmd == LC_DYSYMTAB) {
- const dysymtab_command *d = reinterpret_cast<const dysymtab_command*>(lc);
- indirectSymbolTableOffset = read32(&d->indirectsymoff, isBig);
- indirectSymbolTableCount = read32(&d->nindirectsyms, isBig);
- return true;
- }
- return false;
- });
- if (ec)
- return std::move(ec);
-
- // Walk load commands looking for segments/sections and the symbol table.
- const data_in_code_entry *dataInCode = nullptr;
- const dyld_info_command *dyldInfo = nullptr;
- uint32_t dataInCodeSize = 0;
- ec = forEachLoadCommand(lcRange, lcCount, isBig, is64,
- [&] (uint32_t cmd, uint32_t size, const char* lc) -> bool {
- switch(cmd) {
- case LC_SEGMENT_64:
- if (is64) {
- const segment_command_64 *seg =
- reinterpret_cast<const segment_command_64*>(lc);
- const unsigned sectionCount = read32(&seg->nsects, isBig);
- const section_64 *sects = reinterpret_cast<const section_64*>
- (lc + sizeof(segment_command_64));
- const unsigned lcSize = sizeof(segment_command_64)
- + sectionCount*sizeof(section_64);
- // Verify sections don't extend beyond end of segment load command.
- if (lcSize > size)
- return true;
- for (unsigned i=0; i < sectionCount; ++i) {
- const section_64 *sect = §s[i];
- Section section;
- section.segmentName = getString16(sect->segname);
- section.sectionName = getString16(sect->sectname);
- section.type = (SectionType)(read32(§->flags, isBig) &
- SECTION_TYPE);
- section.attributes = read32(§->flags, isBig) & SECTION_ATTRIBUTES;
- section.alignment = 1 << read32(§->align, isBig);
- section.address = read64(§->addr, isBig);
- const uint8_t *content =
- (const uint8_t *)start + read32(§->offset, isBig);
- size_t contentSize = read64(§->size, isBig);
- // Note: this assign() is copying the content bytes. Ideally,
- // we can use a custom allocator for vector to avoid the copy.
- section.content = llvm::makeArrayRef(content, contentSize);
- appendRelocations(section.relocations, mb->getBuffer(), isBig,
- read32(§->reloff, isBig),
- read32(§->nreloc, isBig));
- if (section.type == S_NON_LAZY_SYMBOL_POINTERS) {
- appendIndirectSymbols(section.indirectSymbols, mb->getBuffer(),
- isBig,
- indirectSymbolTableOffset,
- indirectSymbolTableCount,
- read32(§->reserved1, isBig),
- contentSize/4);
- }
- f->sections.push_back(section);
- }
- }
- break;
- case LC_SEGMENT:
- if (!is64) {
- const segment_command *seg =
- reinterpret_cast<const segment_command*>(lc);
- const unsigned sectionCount = read32(&seg->nsects, isBig);
- const section *sects = reinterpret_cast<const section*>
- (lc + sizeof(segment_command));
- const unsigned lcSize = sizeof(segment_command)
- + sectionCount*sizeof(section);
- // Verify sections don't extend beyond end of segment load command.
- if (lcSize > size)
- return true;
- for (unsigned i=0; i < sectionCount; ++i) {
- const section *sect = §s[i];
- Section section;
- section.segmentName = getString16(sect->segname);
- section.sectionName = getString16(sect->sectname);
- section.type = (SectionType)(read32(§->flags, isBig) &
- SECTION_TYPE);
- section.attributes =
- read32((const uint8_t *)§->flags, isBig) & SECTION_ATTRIBUTES;
- section.alignment = 1 << read32(§->align, isBig);
- section.address = read32(§->addr, isBig);
- const uint8_t *content =
- (const uint8_t *)start + read32(§->offset, isBig);
- size_t contentSize = read32(§->size, isBig);
- // Note: this assign() is copying the content bytes. Ideally,
- // we can use a custom allocator for vector to avoid the copy.
- section.content = llvm::makeArrayRef(content, contentSize);
- appendRelocations(section.relocations, mb->getBuffer(), isBig,
- read32(§->reloff, isBig),
- read32(§->nreloc, isBig));
- if (section.type == S_NON_LAZY_SYMBOL_POINTERS) {
- appendIndirectSymbols(
- section.indirectSymbols, mb->getBuffer(), isBig,
- indirectSymbolTableOffset, indirectSymbolTableCount,
- read32(§->reserved1, isBig), contentSize / 4);
- }
- f->sections.push_back(section);
- }
- }
- break;
- case LC_SYMTAB: {
- const symtab_command *st = reinterpret_cast<const symtab_command*>(lc);
- const char *strings = start + read32(&st->stroff, isBig);
- const uint32_t strSize = read32(&st->strsize, isBig);
- // Validate string pool and symbol table all in buffer.
- if (read32((const uint8_t *)&st->stroff, isBig) +
- read32((const uint8_t *)&st->strsize, isBig) >
- objSize)
- return true;
- if (is64) {
- const uint32_t symOffset = read32(&st->symoff, isBig);
- const uint32_t symCount = read32(&st->nsyms, isBig);
- if ( symOffset+(symCount*sizeof(nlist_64)) > objSize)
- return true;
- const nlist_64 *symbols =
- reinterpret_cast<const nlist_64 *>(start + symOffset);
- // Convert each nlist_64 to a lld::mach_o::normalized::Symbol.
- for(uint32_t i=0; i < symCount; ++i) {
- nlist_64 tempSym;
- memcpy(&tempSym, &symbols[i], sizeof(nlist_64));
- const nlist_64 *sin = &tempSym;
- if (isBig != llvm::sys::IsBigEndianHost)
- swapStruct(tempSym);
- Symbol sout;
- if (sin->n_strx > strSize)
- return true;
- sout.name = &strings[sin->n_strx];
- sout.type = static_cast<NListType>(sin->n_type & (N_STAB|N_TYPE));
- sout.scope = (sin->n_type & (N_PEXT|N_EXT));
- sout.sect = sin->n_sect;
- sout.desc = sin->n_desc;
- sout.value = sin->n_value;
- if (sin->n_type & N_STAB)
- f->stabsSymbols.push_back(sout);
- else if (sout.type == N_UNDF)
- f->undefinedSymbols.push_back(sout);
- else if (sin->n_type & N_EXT)
- f->globalSymbols.push_back(sout);
- else
- f->localSymbols.push_back(sout);
- }
- } else {
- const uint32_t symOffset = read32(&st->symoff, isBig);
- const uint32_t symCount = read32(&st->nsyms, isBig);
- if ( symOffset+(symCount*sizeof(nlist)) > objSize)
- return true;
- const nlist *symbols =
- reinterpret_cast<const nlist *>(start + symOffset);
- // Convert each nlist to a lld::mach_o::normalized::Symbol.
- for(uint32_t i=0; i < symCount; ++i) {
- const nlist *sin = &symbols[i];
- nlist tempSym;
- if (isBig != llvm::sys::IsBigEndianHost) {
- tempSym = *sin; swapStruct(tempSym); sin = &tempSym;
- }
- Symbol sout;
- if (sin->n_strx > strSize)
- return true;
- sout.name = &strings[sin->n_strx];
- sout.type = (NListType)(sin->n_type & N_TYPE);
- sout.scope = (sin->n_type & (N_PEXT|N_EXT));
- sout.sect = sin->n_sect;
- sout.desc = sin->n_desc;
- sout.value = sin->n_value;
- if (sout.type == N_UNDF)
- f->undefinedSymbols.push_back(sout);
- else if (sout.scope == (SymbolScope)N_EXT)
- f->globalSymbols.push_back(sout);
- else if (sin->n_type & N_STAB)
- f->stabsSymbols.push_back(sout);
- else
- f->localSymbols.push_back(sout);
- }
- }
- }
- break;
- case LC_ID_DYLIB: {
- const dylib_command *dl = reinterpret_cast<const dylib_command*>(lc);
- f->installName = lc + read32(&dl->dylib.name, isBig);
- f->currentVersion = read32(&dl->dylib.current_version, isBig);
- f->compatVersion = read32(&dl->dylib.compatibility_version, isBig);
- }
- break;
- case LC_DATA_IN_CODE: {
- const linkedit_data_command *ldc =
- reinterpret_cast<const linkedit_data_command*>(lc);
- dataInCode = reinterpret_cast<const data_in_code_entry *>(
- start + read32(&ldc->dataoff, isBig));
- dataInCodeSize = read32(&ldc->datasize, isBig);
- }
- break;
- case LC_LOAD_DYLIB:
- case LC_LOAD_WEAK_DYLIB:
- case LC_REEXPORT_DYLIB:
- case LC_LOAD_UPWARD_DYLIB: {
- const dylib_command *dl = reinterpret_cast<const dylib_command*>(lc);
- DependentDylib entry;
- entry.path = lc + read32(&dl->dylib.name, isBig);
- entry.kind = LoadCommandType(cmd);
- entry.compatVersion = read32(&dl->dylib.compatibility_version, isBig);
- entry.currentVersion = read32(&dl->dylib.current_version, isBig);
- f->dependentDylibs.push_back(entry);
- }
- break;
- case LC_RPATH: {
- const rpath_command *rpc = reinterpret_cast<const rpath_command *>(lc);
- f->rpaths.push_back(lc + read32(&rpc->path, isBig));
- }
- break;
- case LC_DYLD_INFO:
- case LC_DYLD_INFO_ONLY:
- dyldInfo = reinterpret_cast<const dyld_info_command*>(lc);
- break;
- case LC_VERSION_MIN_MACOSX:
- case LC_VERSION_MIN_IPHONEOS:
- case LC_VERSION_MIN_WATCHOS:
- case LC_VERSION_MIN_TVOS:
- // If we are emitting an object file, then we may take the load command
- // kind from these commands and pass it on to the output
- // file.
- f->minOSVersionKind = (LoadCommandType)cmd;
- break;
- }
- return false;
- });
- if (ec)
- return std::move(ec);
-
- if (dataInCode) {
- // Convert on-disk data_in_code_entry array to DataInCode vector.
- for (unsigned i=0; i < dataInCodeSize/sizeof(data_in_code_entry); ++i) {
- DataInCode entry;
- entry.offset = read32(&dataInCode[i].offset, isBig);
- entry.length = read16(&dataInCode[i].length, isBig);
- entry.kind =
- (DataRegionType)read16((const uint8_t *)&dataInCode[i].kind, isBig);
- f->dataInCode.push_back(entry);
- }
- }
-
- if (dyldInfo) {
- // If any exports, extract and add to normalized exportInfo vector.
- if (dyldInfo->export_size) {
- const uint8_t *trieStart = reinterpret_cast<const uint8_t *>(
- start + read32(&dyldInfo->export_off, isBig));
- ArrayRef<uint8_t> trie(trieStart, read32(&dyldInfo->export_size, isBig));
- Error Err = Error::success();
- for (const ExportEntry &trieExport : MachOObjectFile::exports(Err, trie)) {
- Export normExport;
- normExport.name = trieExport.name().copy(f->ownedAllocations);
- normExport.offset = trieExport.address();
- normExport.kind = ExportSymbolKind(trieExport.flags() & EXPORT_SYMBOL_FLAGS_KIND_MASK);
- normExport.flags = trieExport.flags() & ~EXPORT_SYMBOL_FLAGS_KIND_MASK;
- normExport.otherOffset = trieExport.other();
- if (!trieExport.otherName().empty())
- normExport.otherName = trieExport.otherName().copy(f->ownedAllocations);
- f->exportInfo.push_back(normExport);
- }
- if (Err)
- return std::move(Err);
- }
- }
-
- return std::move(f);
-}
-
-class MachOObjectReader : public Reader {
-public:
- MachOObjectReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
-
- bool canParse(file_magic magic, MemoryBufferRef mb) const override {
- return (magic == file_magic::macho_object && mb.getBufferSize() > 32);
- }
-
- ErrorOr<std::unique_ptr<File>>
- loadFile(std::unique_ptr<MemoryBuffer> mb,
- const Registry ®istry) const override {
- std::unique_ptr<File> ret =
- std::make_unique<MachOFile>(std::move(mb), &_ctx);
- return std::move(ret);
- }
-
-private:
- MachOLinkingContext &_ctx;
-};
-
-class MachODylibReader : public Reader {
-public:
- MachODylibReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
-
- bool canParse(file_magic magic, MemoryBufferRef mb) const override {
- switch (magic) {
- case file_magic::macho_dynamically_linked_shared_lib:
- case file_magic::macho_dynamically_linked_shared_lib_stub:
- return mb.getBufferSize() > 32;
- default:
- return false;
- }
- }
-
- ErrorOr<std::unique_ptr<File>>
- loadFile(std::unique_ptr<MemoryBuffer> mb,
- const Registry ®istry) const override {
- std::unique_ptr<File> ret =
- std::make_unique<MachODylibFile>(std::move(mb), &_ctx);
- return std::move(ret);
- }
-
-private:
- MachOLinkingContext &_ctx;
-};
-
-class MachOTAPIReader : public Reader {
-public:
- MachOTAPIReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
-
- bool canParse(file_magic magic, MemoryBufferRef mb) const override {
- return magic == file_magic::tapi_file;
- }
-
- ErrorOr<std::unique_ptr<File>>
- loadFile(std::unique_ptr<MemoryBuffer> mb,
- const Registry ®istry) const override {
- std::unique_ptr<File> ret =
- std::make_unique<TAPIFile>(std::move(mb), &_ctx);
- return std::move(ret);
- }
-
-private:
- MachOLinkingContext &_ctx;
-};
-
-} // namespace normalized
-} // namespace mach_o
-
-void Registry::addSupportMachOObjects(MachOLinkingContext &ctx) {
- MachOLinkingContext::Arch arch = ctx.arch();
- add(std::unique_ptr<Reader>(new mach_o::normalized::MachOObjectReader(ctx)));
- add(std::unique_ptr<Reader>(new mach_o::normalized::MachODylibReader(ctx)));
- add(std::unique_ptr<Reader>(new mach_o::normalized::MachOTAPIReader(ctx)));
- addKindTable(Reference::KindNamespace::mach_o, ctx.archHandler().kindArch(),
- ctx.archHandler().kindStrings());
- add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
- new mach_o::MachOYamlIOTaggedDocumentHandler(arch)));
-}
-
-
-} // namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h ------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
-#define LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
-
-#include "MachONormalizedFile.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/LEB128.h"
-#include <system_error>
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-class ByteBuffer {
-public:
- ByteBuffer() : _ostream(_bytes) { }
-
- void append_byte(uint8_t b) {
- _ostream << b;
- }
- void append_uleb128(uint64_t value) {
- llvm::encodeULEB128(value, _ostream);
- }
- void append_uleb128Fixed(uint64_t value, unsigned byteCount) {
- unsigned min = llvm::getULEB128Size(value);
- assert(min <= byteCount);
- unsigned pad = byteCount - min;
- llvm::encodeULEB128(value, _ostream, pad);
- }
- void append_sleb128(int64_t value) {
- llvm::encodeSLEB128(value, _ostream);
- }
- void append_string(StringRef str) {
- _ostream << str;
- append_byte(0);
- }
- void align(unsigned alignment) {
- while ( (_ostream.tell() % alignment) != 0 )
- append_byte(0);
- }
- size_t size() {
- return _ostream.tell();
- }
- const uint8_t *bytes() {
- return reinterpret_cast<const uint8_t*>(_ostream.str().data());
- }
-
-private:
- SmallVector<char, 128> _bytes;
- // Stream ivar must be after SmallVector ivar to construct properly.
- llvm::raw_svector_ostream _ostream;
-};
-
-using namespace llvm::support::endian;
-using llvm::sys::getSwappedBytes;
-
-template<typename T>
-static inline uint16_t read16(const T *loc, bool isBig) {
- assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
- return isBig ? read16be(loc) : read16le(loc);
-}
-
-template<typename T>
-static inline uint32_t read32(const T *loc, bool isBig) {
- assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
- return isBig ? read32be(loc) : read32le(loc);
-}
-
-template<typename T>
-static inline uint64_t read64(const T *loc, bool isBig) {
- assert((uint64_t)loc % alignof(T) == 0 && "invalid pointer alignment");
- return isBig ? read64be(loc) : read64le(loc);
-}
-
-inline void write16(uint8_t *loc, uint16_t value, bool isBig) {
- if (isBig)
- write16be(loc, value);
- else
- write16le(loc, value);
-}
-
-inline void write32(uint8_t *loc, uint32_t value, bool isBig) {
- if (isBig)
- write32be(loc, value);
- else
- write32le(loc, value);
-}
-
-inline void write64(uint8_t *loc, uint64_t value, bool isBig) {
- if (isBig)
- write64be(loc, value);
- else
- write64le(loc, value);
-}
-
-inline uint32_t
-bitFieldExtract(uint32_t value, bool isBigEndianBigField, uint8_t firstBit,
- uint8_t bitCount) {
- const uint32_t mask = ((1<<bitCount)-1);
- const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
- return (value >> shift) & mask;
-}
-
-inline void
-bitFieldSet(uint32_t &bits, bool isBigEndianBigField, uint32_t newBits,
- uint8_t firstBit, uint8_t bitCount) {
- const uint32_t mask = ((1<<bitCount)-1);
- assert((newBits & mask) == newBits);
- const uint8_t shift = isBigEndianBigField ? (32-firstBit-bitCount) : firstBit;
- bits &= ~(mask << shift);
- bits |= (newBits << shift);
-}
-
-inline Relocation unpackRelocation(const llvm::MachO::any_relocation_info &r,
- bool isBigEndian) {
- uint32_t r0 = read32(&r.r_word0, isBigEndian);
- uint32_t r1 = read32(&r.r_word1, isBigEndian);
-
- Relocation result;
- if (r0 & llvm::MachO::R_SCATTERED) {
- // scattered relocation record always laid out like big endian bit field
- result.offset = bitFieldExtract(r0, true, 8, 24);
- result.scattered = true;
- result.type = (RelocationInfoType)
- bitFieldExtract(r0, true, 4, 4);
- result.length = bitFieldExtract(r0, true, 2, 2);
- result.pcRel = bitFieldExtract(r0, true, 1, 1);
- result.isExtern = false;
- result.value = r1;
- result.symbol = 0;
- } else {
- result.offset = r0;
- result.scattered = false;
- result.type = (RelocationInfoType)
- bitFieldExtract(r1, isBigEndian, 28, 4);
- result.length = bitFieldExtract(r1, isBigEndian, 25, 2);
- result.pcRel = bitFieldExtract(r1, isBigEndian, 24, 1);
- result.isExtern = bitFieldExtract(r1, isBigEndian, 27, 1);
- result.value = 0;
- result.symbol = bitFieldExtract(r1, isBigEndian, 0, 24);
- }
- return result;
-}
-
-
-inline llvm::MachO::any_relocation_info
-packRelocation(const Relocation &r, bool swap, bool isBigEndian) {
- uint32_t r0 = 0;
- uint32_t r1 = 0;
-
- if (r.scattered) {
- r1 = r.value;
- bitFieldSet(r0, true, r.offset, 8, 24);
- bitFieldSet(r0, true, r.type, 4, 4);
- bitFieldSet(r0, true, r.length, 2, 2);
- bitFieldSet(r0, true, r.pcRel, 1, 1);
- bitFieldSet(r0, true, r.scattered, 0, 1); // R_SCATTERED
- } else {
- r0 = r.offset;
- bitFieldSet(r1, isBigEndian, r.type, 28, 4);
- bitFieldSet(r1, isBigEndian, r.isExtern, 27, 1);
- bitFieldSet(r1, isBigEndian, r.length, 25, 2);
- bitFieldSet(r1, isBigEndian, r.pcRel, 24, 1);
- bitFieldSet(r1, isBigEndian, r.symbol, 0, 24);
- }
-
- llvm::MachO::any_relocation_info result;
- result.r_word0 = swap ? getSwappedBytes(r0) : r0;
- result.r_word1 = swap ? getSwappedBytes(r1) : r1;
- return result;
-}
-
-inline StringRef getString16(const char s[16]) {
- // The StringRef(const char *) constructor passes the const char * to
- // strlen(), so we can't use this constructor here, because if there is no
- // null terminator in s, then strlen() will read past the end of the array.
- return StringRef(s, strnlen(s, 16));
-}
-
-inline void setString16(StringRef str, char s[16]) {
- memset(s, 0, 16);
- memcpy(s, str.begin(), (str.size() > 16) ? 16: str.size());
-}
-
-// Implemented in normalizedToAtoms() and used by normalizedFromAtoms() so
-// that the same table can be used to map mach-o sections to and from
-// DefinedAtom::ContentType.
-void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
- StringRef &segmentName,
- StringRef §ionName,
- SectionType §ionType,
- SectionAttr §ionAttrs,
- bool &relocsToDefinedCanBeImplicit);
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_NORMALIZED_FILE_BINARY_UTILS_H
+++ /dev/null
-//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp ---------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file For mach-o object files, this implementation converts normalized
-/// mach-o in memory to mach-o binary on disk.
-///
-/// +---------------+
-/// | binary mach-o |
-/// +---------------+
-/// ^
-/// |
-/// |
-/// +------------+
-/// | normalized |
-/// +------------+
-
-#include "MachONormalizedFile.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <functional>
-#include <list>
-#include <map>
-#include <system_error>
-
-using namespace llvm::MachO;
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-struct TrieNode; // Forward declaration.
-
-struct TrieEdge : public llvm::ilist_node<TrieEdge> {
- TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
-
- StringRef _subString;
- struct TrieNode *_child;
-};
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
-
-
-namespace llvm {
-using lld::mach_o::normalized::TrieEdge;
-template <>
-struct ilist_alloc_traits<TrieEdge> : ilist_noalloc_traits<TrieEdge> {};
-} // namespace llvm
-
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-struct TrieNode {
- typedef llvm::ilist<TrieEdge> TrieEdgeList;
-
- TrieNode(StringRef s)
- : _cummulativeString(s), _address(0), _flags(0), _other(0),
- _trieOffset(0), _hasExportInfo(false) {}
- ~TrieNode() = default;
-
- void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
- std::vector<TrieNode *> &allNodes);
-
- void addOrderedNodes(const Export &entry,
- std::vector<TrieNode *> &allNodes);
- bool updateOffset(uint32_t &offset);
- void appendToByteBuffer(ByteBuffer &out);
-
-private:
- StringRef _cummulativeString;
- TrieEdgeList _children;
- uint64_t _address;
- uint64_t _flags;
- uint64_t _other;
- StringRef _importedName;
- uint32_t _trieOffset;
- bool _hasExportInfo;
- bool _ordered = false;
-};
-
-/// Utility class for writing a mach-o binary file given an in-memory
-/// normalized file.
-class MachOFileLayout {
-public:
- /// All layout computation is done in the constructor.
- MachOFileLayout(const NormalizedFile &file, bool alwaysIncludeFunctionStarts);
-
- /// Returns the final file size as computed in the constructor.
- size_t size() const;
-
- // Returns size of the mach_header and load commands.
- size_t headerAndLoadCommandsSize() const;
-
- /// Writes the normalized file as a binary mach-o file to the specified
- /// path. This does not have a stream interface because the generated
- /// file may need the 'x' bit set.
- llvm::Error writeBinary(StringRef path);
-
-private:
- uint32_t loadCommandsSize(uint32_t &count,
- bool alwaysIncludeFunctionStarts);
- void buildFileOffsets();
- void writeMachHeader();
- llvm::Error writeLoadCommands();
- void writeSectionContent();
- void writeRelocations();
- void writeSymbolTable();
- void writeRebaseInfo();
- void writeBindingInfo();
- void writeLazyBindingInfo();
- void writeExportInfo();
- void writeFunctionStartsInfo();
- void writeDataInCodeInfo();
- void writeLinkEditContent();
- void buildLinkEditInfo();
- void buildRebaseInfo();
- void buildBindInfo();
- void buildLazyBindInfo();
- void buildExportTrie();
- void computeFunctionStartsSize();
- void computeDataInCodeSize();
- void computeSymbolTableSizes();
- void buildSectionRelocations();
- void appendSymbols(const std::vector<Symbol> &symbols,
- uint32_t &symOffset, uint32_t &strOffset);
- uint32_t indirectSymbolIndex(const Section §, uint32_t &index);
- uint32_t indirectSymbolElementSize(const Section §);
-
- // For use as template parameter to load command methods.
- struct MachO64Trait {
- typedef llvm::MachO::segment_command_64 command;
- typedef llvm::MachO::section_64 section;
- enum { LC = llvm::MachO::LC_SEGMENT_64 };
- };
-
- // For use as template parameter to load command methods.
- struct MachO32Trait {
- typedef llvm::MachO::segment_command command;
- typedef llvm::MachO::section section;
- enum { LC = llvm::MachO::LC_SEGMENT };
- };
-
- template <typename T>
- llvm::Error writeSingleSegmentLoadCommand(uint8_t *&lc);
- template <typename T> llvm::Error writeSegmentLoadCommands(uint8_t *&lc);
-
- uint32_t pointerAlign(uint32_t value);
- static StringRef dyldPath();
-
- struct SegExtraInfo {
- uint32_t fileOffset;
- uint32_t fileSize;
- std::vector<const Section*> sections;
- };
- typedef std::map<const Segment*, SegExtraInfo> SegMap;
- struct SectionExtraInfo {
- uint32_t fileOffset;
- };
- typedef std::map<const Section*, SectionExtraInfo> SectionMap;
-
- const NormalizedFile &_file;
- std::error_code _ec;
- uint8_t *_buffer;
- const bool _is64;
- const bool _swap;
- const bool _bigEndianArch;
- uint64_t _seg1addr;
- uint32_t _startOfLoadCommands;
- uint32_t _countOfLoadCommands;
- uint32_t _endOfLoadCommands;
- uint32_t _startOfRelocations;
- uint32_t _startOfFunctionStarts;
- uint32_t _startOfDataInCode;
- uint32_t _startOfSymbols;
- uint32_t _startOfIndirectSymbols;
- uint32_t _startOfSymbolStrings;
- uint32_t _endOfSymbolStrings;
- uint32_t _symbolTableLocalsStartIndex;
- uint32_t _symbolTableGlobalsStartIndex;
- uint32_t _symbolTableUndefinesStartIndex;
- uint32_t _symbolStringPoolSize;
- uint32_t _symbolTableSize;
- uint32_t _functionStartsSize;
- uint32_t _dataInCodeSize;
- uint32_t _indirectSymbolTableCount;
- // Used in object file creation only
- uint32_t _startOfSectionsContent;
- uint32_t _endOfSectionsContent;
- // Used in final linked image only
- uint32_t _startOfLinkEdit;
- uint32_t _startOfRebaseInfo;
- uint32_t _endOfRebaseInfo;
- uint32_t _startOfBindingInfo;
- uint32_t _endOfBindingInfo;
- uint32_t _startOfLazyBindingInfo;
- uint32_t _endOfLazyBindingInfo;
- uint32_t _startOfExportTrie;
- uint32_t _endOfExportTrie;
- uint32_t _endOfLinkEdit;
- uint64_t _addressOfLinkEdit;
- SegMap _segInfo;
- SectionMap _sectInfo;
- ByteBuffer _rebaseInfo;
- ByteBuffer _bindingInfo;
- ByteBuffer _lazyBindingInfo;
- ByteBuffer _weakBindingInfo;
- ByteBuffer _exportTrie;
-};
-
-size_t headerAndLoadCommandsSize(const NormalizedFile &file,
- bool includeFunctionStarts) {
- MachOFileLayout layout(file, includeFunctionStarts);
- return layout.headerAndLoadCommandsSize();
-}
-
-StringRef MachOFileLayout::dyldPath() {
- return "/usr/lib/dyld";
-}
-
-uint32_t MachOFileLayout::pointerAlign(uint32_t value) {
- return llvm::alignTo(value, _is64 ? 8 : 4);
-}
-
-
-size_t MachOFileLayout::headerAndLoadCommandsSize() const {
- return _endOfLoadCommands;
-}
-
-MachOFileLayout::MachOFileLayout(const NormalizedFile &file,
- bool alwaysIncludeFunctionStarts)
- : _file(file),
- _is64(MachOLinkingContext::is64Bit(file.arch)),
- _swap(!MachOLinkingContext::isHostEndian(file.arch)),
- _bigEndianArch(MachOLinkingContext::isBigEndian(file.arch)),
- _seg1addr(INT64_MAX) {
- _startOfLoadCommands = _is64 ? sizeof(mach_header_64) : sizeof(mach_header);
- const size_t segCommandBaseSize =
- (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
- const size_t sectsSize = (_is64 ? sizeof(section_64) : sizeof(section));
- if (file.fileType == llvm::MachO::MH_OBJECT) {
- // object files have just one segment load command containing all sections
- _endOfLoadCommands = _startOfLoadCommands
- + segCommandBaseSize
- + file.sections.size() * sectsSize
- + sizeof(symtab_command);
- _countOfLoadCommands = 2;
- if (file.hasMinVersionLoadCommand) {
- _endOfLoadCommands += sizeof(version_min_command);
- _countOfLoadCommands++;
- }
- if (!_file.functionStarts.empty() || alwaysIncludeFunctionStarts) {
- _endOfLoadCommands += sizeof(linkedit_data_command);
- _countOfLoadCommands++;
- }
- if (_file.generateDataInCodeLoadCommand) {
- _endOfLoadCommands += sizeof(linkedit_data_command);
- _countOfLoadCommands++;
- }
- // Assign file offsets to each section.
- _startOfSectionsContent = _endOfLoadCommands;
- unsigned relocCount = 0;
- uint64_t offset = _startOfSectionsContent;
- for (const Section § : file.sections) {
- if (isZeroFillSection(sect.type))
- _sectInfo[§].fileOffset = 0;
- else {
- offset = llvm::alignTo(offset, sect.alignment);
- _sectInfo[§].fileOffset = offset;
- offset += sect.content.size();
- }
- relocCount += sect.relocations.size();
- }
- _endOfSectionsContent = offset;
-
- computeSymbolTableSizes();
- computeFunctionStartsSize();
- computeDataInCodeSize();
-
- // Align start of relocations.
- _startOfRelocations = pointerAlign(_endOfSectionsContent);
- _startOfFunctionStarts = _startOfRelocations + relocCount * 8;
- _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
- _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
- // Add Indirect symbol table.
- _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
- // Align start of symbol table and symbol strings.
- _startOfSymbolStrings = _startOfIndirectSymbols
- + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
- _endOfSymbolStrings = _startOfSymbolStrings
- + pointerAlign(_symbolStringPoolSize);
- _endOfLinkEdit = _endOfSymbolStrings;
- DEBUG_WITH_TYPE("MachOFileLayout",
- llvm::dbgs() << "MachOFileLayout()\n"
- << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
- << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
- << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
- << " startOfRelocations=" << _startOfRelocations << "\n"
- << " startOfSymbols=" << _startOfSymbols << "\n"
- << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
- << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
- << " startOfSectionsContent=" << _startOfSectionsContent << "\n"
- << " endOfSectionsContent=" << _endOfSectionsContent << "\n");
- } else {
- // Final linked images have one load command per segment.
- _endOfLoadCommands = _startOfLoadCommands
- + loadCommandsSize(_countOfLoadCommands,
- alwaysIncludeFunctionStarts);
-
- // Assign section file offsets.
- buildFileOffsets();
- buildLinkEditInfo();
-
- // LINKEDIT of final linked images has in order:
- // rebase info, binding info, lazy binding info, weak binding info,
- // data-in-code, symbol table, indirect symbol table, symbol table strings.
- _startOfRebaseInfo = _startOfLinkEdit;
- _endOfRebaseInfo = _startOfRebaseInfo + _rebaseInfo.size();
- _startOfBindingInfo = _endOfRebaseInfo;
- _endOfBindingInfo = _startOfBindingInfo + _bindingInfo.size();
- _startOfLazyBindingInfo = _endOfBindingInfo;
- _endOfLazyBindingInfo = _startOfLazyBindingInfo + _lazyBindingInfo.size();
- _startOfExportTrie = _endOfLazyBindingInfo;
- _endOfExportTrie = _startOfExportTrie + _exportTrie.size();
- _startOfFunctionStarts = _endOfExportTrie;
- _startOfDataInCode = _startOfFunctionStarts + _functionStartsSize;
- _startOfSymbols = _startOfDataInCode + _dataInCodeSize;
- _startOfIndirectSymbols = _startOfSymbols + _symbolTableSize;
- _startOfSymbolStrings = _startOfIndirectSymbols
- + pointerAlign(_indirectSymbolTableCount * sizeof(uint32_t));
- _endOfSymbolStrings = _startOfSymbolStrings
- + pointerAlign(_symbolStringPoolSize);
- _endOfLinkEdit = _endOfSymbolStrings;
- DEBUG_WITH_TYPE("MachOFileLayout",
- llvm::dbgs() << "MachOFileLayout()\n"
- << " startOfLoadCommands=" << _startOfLoadCommands << "\n"
- << " countOfLoadCommands=" << _countOfLoadCommands << "\n"
- << " endOfLoadCommands=" << _endOfLoadCommands << "\n"
- << " startOfLinkEdit=" << _startOfLinkEdit << "\n"
- << " startOfRebaseInfo=" << _startOfRebaseInfo << "\n"
- << " endOfRebaseInfo=" << _endOfRebaseInfo << "\n"
- << " startOfBindingInfo=" << _startOfBindingInfo << "\n"
- << " endOfBindingInfo=" << _endOfBindingInfo << "\n"
- << " startOfLazyBindingInfo=" << _startOfLazyBindingInfo << "\n"
- << " endOfLazyBindingInfo=" << _endOfLazyBindingInfo << "\n"
- << " startOfExportTrie=" << _startOfExportTrie << "\n"
- << " endOfExportTrie=" << _endOfExportTrie << "\n"
- << " startOfFunctionStarts=" << _startOfFunctionStarts << "\n"
- << " startOfDataInCode=" << _startOfDataInCode << "\n"
- << " startOfSymbols=" << _startOfSymbols << "\n"
- << " startOfSymbolStrings=" << _startOfSymbolStrings << "\n"
- << " endOfSymbolStrings=" << _endOfSymbolStrings << "\n"
- << " addressOfLinkEdit=" << _addressOfLinkEdit << "\n");
- }
-}
-
-uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count,
- bool alwaysIncludeFunctionStarts) {
- uint32_t size = 0;
- count = 0;
-
- const size_t segCommandSize =
- (_is64 ? sizeof(segment_command_64) : sizeof(segment_command));
- const size_t sectionSize = (_is64 ? sizeof(section_64) : sizeof(section));
-
- // Add LC_SEGMENT for each segment.
- size += _file.segments.size() * segCommandSize;
- count += _file.segments.size();
- // Add section record for each section.
- size += _file.sections.size() * sectionSize;
-
- // If creating a dylib, add LC_ID_DYLIB.
- if (_file.fileType == llvm::MachO::MH_DYLIB) {
- size += sizeof(dylib_command) + pointerAlign(_file.installName.size() + 1);
- ++count;
- }
-
- // Add LC_DYLD_INFO
- size += sizeof(dyld_info_command);
- ++count;
-
- // Add LC_SYMTAB
- size += sizeof(symtab_command);
- ++count;
-
- // Add LC_DYSYMTAB
- if (_file.fileType != llvm::MachO::MH_PRELOAD) {
- size += sizeof(dysymtab_command);
- ++count;
- }
-
- // If main executable add LC_LOAD_DYLINKER
- if (_file.fileType == llvm::MachO::MH_EXECUTE) {
- size += pointerAlign(sizeof(dylinker_command) + dyldPath().size()+1);
- ++count;
- }
-
- // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
- // LC_VERSION_MIN_TVOS
- if (_file.hasMinVersionLoadCommand) {
- size += sizeof(version_min_command);
- ++count;
- }
-
- // Add LC_SOURCE_VERSION
- size += sizeof(source_version_command);
- ++count;
-
- // If main executable add LC_MAIN
- if (_file.fileType == llvm::MachO::MH_EXECUTE) {
- size += sizeof(entry_point_command);
- ++count;
- }
-
- // Add LC_LOAD_DYLIB for each dependent dylib.
- for (const DependentDylib &dep : _file.dependentDylibs) {
- size += sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
- ++count;
- }
-
- // Add LC_RPATH
- for (const StringRef &path : _file.rpaths) {
- size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
- ++count;
- }
-
- // Add LC_FUNCTION_STARTS if needed
- if (!_file.functionStarts.empty() || alwaysIncludeFunctionStarts) {
- size += sizeof(linkedit_data_command);
- ++count;
- }
-
- // Add LC_DATA_IN_CODE if requested. Note, we do encode zero length entries.
- // FIXME: Zero length entries is only to match ld64. Should we change this?
- if (_file.generateDataInCodeLoadCommand) {
- size += sizeof(linkedit_data_command);
- ++count;
- }
-
- return size;
-}
-
-static bool overlaps(const Segment &s1, const Segment &s2) {
- if (s2.address >= s1.address+s1.size)
- return false;
- if (s1.address >= s2.address+s2.size)
- return false;
- return true;
-}
-
-static bool overlaps(const Section &s1, const Section &s2) {
- if (s2.address >= s1.address+s1.content.size())
- return false;
- if (s1.address >= s2.address+s2.content.size())
- return false;
- return true;
-}
-
-void MachOFileLayout::buildFileOffsets() {
- // Verify no segments overlap
- for (const Segment &sg1 : _file.segments) {
- for (const Segment &sg2 : _file.segments) {
- if (&sg1 == &sg2)
- continue;
- if (overlaps(sg1,sg2)) {
- _ec = make_error_code(llvm::errc::executable_format_error);
- return;
- }
- }
- }
-
- // Verify no sections overlap
- for (const Section &s1 : _file.sections) {
- for (const Section &s2 : _file.sections) {
- if (&s1 == &s2)
- continue;
- if (overlaps(s1,s2)) {
- _ec = make_error_code(llvm::errc::executable_format_error);
- return;
- }
- }
- }
-
- // Build side table of extra info about segments and sections.
- SegExtraInfo t;
- t.fileOffset = 0;
- for (const Segment &sg : _file.segments) {
- _segInfo[&sg] = t;
- }
- SectionExtraInfo t2;
- t2.fileOffset = 0;
- // Assign sections to segments.
- for (const Section &s : _file.sections) {
- _sectInfo[&s] = t2;
- bool foundSegment = false;
- for (const Segment &sg : _file.segments) {
- if (sg.name.equals(s.segmentName)) {
- if ((s.address >= sg.address)
- && (s.address+s.content.size() <= sg.address+sg.size)) {
- _segInfo[&sg].sections.push_back(&s);
- foundSegment = true;
- break;
- }
- }
- }
- if (!foundSegment) {
- _ec = make_error_code(llvm::errc::executable_format_error);
- return;
- }
- }
-
- // Assign file offsets.
- uint32_t fileOffset = 0;
- DEBUG_WITH_TYPE("MachOFileLayout",
- llvm::dbgs() << "buildFileOffsets()\n");
- for (const Segment &sg : _file.segments) {
- _segInfo[&sg].fileOffset = fileOffset;
- if ((_seg1addr == INT64_MAX) && sg.init_access)
- _seg1addr = sg.address;
- DEBUG_WITH_TYPE("MachOFileLayout",
- llvm::dbgs() << " segment=" << sg.name
- << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
-
- uint32_t segFileSize = 0;
- // A segment that is not zero-fill must use a least one page of disk space.
- if (sg.init_access)
- segFileSize = _file.pageSize;
- for (const Section *s : _segInfo[&sg].sections) {
- uint32_t sectOffset = s->address - sg.address;
- uint32_t sectFileSize =
- isZeroFillSection(s->type) ? 0 : s->content.size();
- segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
-
- _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
- DEBUG_WITH_TYPE("MachOFileLayout",
- llvm::dbgs() << " section=" << s->sectionName
- << ", fileOffset=" << fileOffset << "\n");
- }
-
- // round up all segments to page aligned, except __LINKEDIT
- if (!sg.name.equals("__LINKEDIT")) {
- _segInfo[&sg].fileSize = llvm::alignTo(segFileSize, _file.pageSize);
- fileOffset = llvm::alignTo(fileOffset + segFileSize, _file.pageSize);
- }
- _addressOfLinkEdit = sg.address + sg.size;
- }
- _startOfLinkEdit = fileOffset;
-}
-
-size_t MachOFileLayout::size() const {
- return _endOfSymbolStrings;
-}
-
-void MachOFileLayout::writeMachHeader() {
- auto cpusubtype = MachOLinkingContext::cpuSubtypeFromArch(_file.arch);
- // dynamic x86 executables on newer OS version should also set the
- // CPU_SUBTYPE_LIB64 mask in the CPU subtype.
- // FIXME: Check that this is a dynamic executable, not a static one.
- if (_file.fileType == llvm::MachO::MH_EXECUTE &&
- cpusubtype == CPU_SUBTYPE_X86_64_ALL &&
- _file.os == MachOLinkingContext::OS::macOSX) {
- uint32_t version;
- bool failed = MachOLinkingContext::parsePackedVersion("10.5", version);
- if (!failed && _file.minOSverson >= version)
- cpusubtype |= CPU_SUBTYPE_LIB64;
- }
-
- mach_header *mh = reinterpret_cast<mach_header*>(_buffer);
- mh->magic = _is64 ? llvm::MachO::MH_MAGIC_64 : llvm::MachO::MH_MAGIC;
- mh->cputype = MachOLinkingContext::cpuTypeFromArch(_file.arch);
- mh->cpusubtype = cpusubtype;
- mh->filetype = _file.fileType;
- mh->ncmds = _countOfLoadCommands;
- mh->sizeofcmds = _endOfLoadCommands - _startOfLoadCommands;
- mh->flags = _file.flags;
- if (_swap)
- swapStruct(*mh);
-}
-
-uint32_t MachOFileLayout::indirectSymbolIndex(const Section §,
- uint32_t &index) {
- if (sect.indirectSymbols.empty())
- return 0;
- uint32_t result = index;
- index += sect.indirectSymbols.size();
- return result;
-}
-
-uint32_t MachOFileLayout::indirectSymbolElementSize(const Section §) {
- if (sect.indirectSymbols.empty())
- return 0;
- if (sect.type != S_SYMBOL_STUBS)
- return 0;
- return sect.content.size() / sect.indirectSymbols.size();
-}
-
-template <typename T>
-llvm::Error MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
- typename T::command* seg = reinterpret_cast<typename T::command*>(lc);
- seg->cmd = T::LC;
- seg->cmdsize = sizeof(typename T::command)
- + _file.sections.size() * sizeof(typename T::section);
- uint8_t *next = lc + seg->cmdsize;
- memset(seg->segname, 0, 16);
- seg->flags = 0;
- seg->vmaddr = 0;
- seg->fileoff = _endOfLoadCommands;
- seg->maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
- seg->initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
- seg->nsects = _file.sections.size();
- if (seg->nsects) {
- seg->vmsize = _file.sections.back().address
- + _file.sections.back().content.size();
- seg->filesize = _sectInfo[&_file.sections.back()].fileOffset +
- _file.sections.back().content.size() -
- _sectInfo[&_file.sections.front()].fileOffset;
- }
- if (_swap)
- swapStruct(*seg);
- typename T::section *sout = reinterpret_cast<typename T::section*>
- (lc+sizeof(typename T::command));
- uint32_t relOffset = _startOfRelocations;
- uint32_t indirectSymRunningIndex = 0;
- for (const Section &sin : _file.sections) {
- setString16(sin.sectionName, sout->sectname);
- setString16(sin.segmentName, sout->segname);
- sout->addr = sin.address;
- sout->size = sin.content.size();
- sout->offset = _sectInfo[&sin].fileOffset;
- sout->align = llvm::Log2_32(sin.alignment);
- sout->reloff = sin.relocations.empty() ? 0 : relOffset;
- sout->nreloc = sin.relocations.size();
- sout->flags = sin.type | sin.attributes;
- sout->reserved1 = indirectSymbolIndex(sin, indirectSymRunningIndex);
- sout->reserved2 = indirectSymbolElementSize(sin);
- relOffset += sin.relocations.size() * sizeof(any_relocation_info);
- if (_swap)
- swapStruct(*sout);
- ++sout;
- }
- lc = next;
- return llvm::Error::success();
-}
-
-template <typename T>
-llvm::Error MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
- uint32_t indirectSymRunningIndex = 0;
- for (const Segment &seg : _file.segments) {
- // Link edit has no sections and a custom range of address, so handle it
- // specially.
- SegExtraInfo &segInfo = _segInfo[&seg];
- if (seg.name.equals("__LINKEDIT")) {
- size_t linkeditSize = _endOfLinkEdit - _startOfLinkEdit;
- typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
- cmd->cmd = T::LC;
- cmd->cmdsize = sizeof(typename T::command);
- uint8_t *next = lc + cmd->cmdsize;
- setString16("__LINKEDIT", cmd->segname);
- cmd->vmaddr = _addressOfLinkEdit;
- cmd->vmsize = llvm::alignTo(linkeditSize, _file.pageSize);
- cmd->fileoff = _startOfLinkEdit;
- cmd->filesize = linkeditSize;
- cmd->initprot = seg.init_access;
- cmd->maxprot = seg.max_access;
- cmd->nsects = 0;
- cmd->flags = 0;
- if (_swap)
- swapStruct(*cmd);
- lc = next;
- continue;
- }
- // Write segment command with trailing sections.
- typename T::command* cmd = reinterpret_cast<typename T::command*>(lc);
- cmd->cmd = T::LC;
- cmd->cmdsize = sizeof(typename T::command)
- + segInfo.sections.size() * sizeof(typename T::section);
- uint8_t *next = lc + cmd->cmdsize;
- setString16(seg.name, cmd->segname);
- cmd->vmaddr = seg.address;
- cmd->vmsize = seg.size;
- cmd->fileoff = segInfo.fileOffset;
- cmd->filesize = segInfo.fileSize;
- cmd->initprot = seg.init_access;
- cmd->maxprot = seg.max_access;
- cmd->nsects = segInfo.sections.size();
- cmd->flags = 0;
- if (_swap)
- swapStruct(*cmd);
- typename T::section *sect = reinterpret_cast<typename T::section*>
- (lc+sizeof(typename T::command));
- for (const Section *section : segInfo.sections) {
- setString16(section->sectionName, sect->sectname);
- setString16(section->segmentName, sect->segname);
- sect->addr = section->address;
- sect->size = section->content.size();
- if (isZeroFillSection(section->type))
- sect->offset = 0;
- else
- sect->offset = section->address - seg.address + segInfo.fileOffset;
- sect->align = llvm::Log2_32(section->alignment);
- sect->reloff = 0;
- sect->nreloc = 0;
- sect->flags = section->type | section->attributes;
- sect->reserved1 = indirectSymbolIndex(*section, indirectSymRunningIndex);
- sect->reserved2 = indirectSymbolElementSize(*section);
- if (_swap)
- swapStruct(*sect);
- ++sect;
- }
- lc = reinterpret_cast<uint8_t*>(next);
- }
- return llvm::Error::success();
-}
-
-static void writeVersionMinLoadCommand(const NormalizedFile &_file,
- bool _swap,
- uint8_t *&lc) {
- if (!_file.hasMinVersionLoadCommand)
- return;
- version_min_command *vm = reinterpret_cast<version_min_command*>(lc);
- switch (_file.os) {
- case MachOLinkingContext::OS::unknown:
- vm->cmd = _file.minOSVersionKind;
- vm->cmdsize = sizeof(version_min_command);
- vm->version = _file.minOSverson;
- vm->sdk = 0;
- break;
- case MachOLinkingContext::OS::macOSX:
- vm->cmd = LC_VERSION_MIN_MACOSX;
- vm->cmdsize = sizeof(version_min_command);
- vm->version = _file.minOSverson;
- vm->sdk = _file.sdkVersion;
- break;
- case MachOLinkingContext::OS::iOS:
- case MachOLinkingContext::OS::iOS_simulator:
- vm->cmd = LC_VERSION_MIN_IPHONEOS;
- vm->cmdsize = sizeof(version_min_command);
- vm->version = _file.minOSverson;
- vm->sdk = _file.sdkVersion;
- break;
- }
- if (_swap)
- swapStruct(*vm);
- lc += sizeof(version_min_command);
-}
-
-llvm::Error MachOFileLayout::writeLoadCommands() {
- uint8_t *lc = &_buffer[_startOfLoadCommands];
- if (_file.fileType == llvm::MachO::MH_OBJECT) {
- // Object files have one unnamed segment which holds all sections.
- if (_is64) {
- if (auto ec = writeSingleSegmentLoadCommand<MachO64Trait>(lc))
- return ec;
- } else {
- if (auto ec = writeSingleSegmentLoadCommand<MachO32Trait>(lc))
- return ec;
- }
- // Add LC_SYMTAB with symbol table info
- symtab_command* st = reinterpret_cast<symtab_command*>(lc);
- st->cmd = LC_SYMTAB;
- st->cmdsize = sizeof(symtab_command);
- st->symoff = _startOfSymbols;
- st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
- _file.globalSymbols.size() + _file.undefinedSymbols.size();
- st->stroff = _startOfSymbolStrings;
- st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
- if (_swap)
- swapStruct(*st);
- lc += sizeof(symtab_command);
-
- // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS,
- // LC_VERSION_MIN_WATCHOS, LC_VERSION_MIN_TVOS
- writeVersionMinLoadCommand(_file, _swap, lc);
-
- // Add LC_FUNCTION_STARTS if needed.
- if (_functionStartsSize != 0) {
- linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
- dl->cmd = LC_FUNCTION_STARTS;
- dl->cmdsize = sizeof(linkedit_data_command);
- dl->dataoff = _startOfFunctionStarts;
- dl->datasize = _functionStartsSize;
- if (_swap)
- swapStruct(*dl);
- lc += sizeof(linkedit_data_command);
- }
-
- // Add LC_DATA_IN_CODE if requested.
- if (_file.generateDataInCodeLoadCommand) {
- linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
- dl->cmd = LC_DATA_IN_CODE;
- dl->cmdsize = sizeof(linkedit_data_command);
- dl->dataoff = _startOfDataInCode;
- dl->datasize = _dataInCodeSize;
- if (_swap)
- swapStruct(*dl);
- lc += sizeof(linkedit_data_command);
- }
- } else {
- // Final linked images have sections under segments.
- if (_is64) {
- if (auto ec = writeSegmentLoadCommands<MachO64Trait>(lc))
- return ec;
- } else {
- if (auto ec = writeSegmentLoadCommands<MachO32Trait>(lc))
- return ec;
- }
-
- // Add LC_ID_DYLIB command for dynamic libraries.
- if (_file.fileType == llvm::MachO::MH_DYLIB) {
- dylib_command *dc = reinterpret_cast<dylib_command*>(lc);
- StringRef path = _file.installName;
- uint32_t size = sizeof(dylib_command) + pointerAlign(path.size() + 1);
- dc->cmd = LC_ID_DYLIB;
- dc->cmdsize = size;
- dc->dylib.name = sizeof(dylib_command); // offset
- // needs to be some constant value different than the one in LC_LOAD_DYLIB
- dc->dylib.timestamp = 1;
- dc->dylib.current_version = _file.currentVersion;
- dc->dylib.compatibility_version = _file.compatVersion;
- if (_swap)
- swapStruct(*dc);
- memcpy(lc + sizeof(dylib_command), path.begin(), path.size());
- lc[sizeof(dylib_command) + path.size()] = '\0';
- lc += size;
- }
-
- // Add LC_DYLD_INFO_ONLY.
- dyld_info_command* di = reinterpret_cast<dyld_info_command*>(lc);
- di->cmd = LC_DYLD_INFO_ONLY;
- di->cmdsize = sizeof(dyld_info_command);
- di->rebase_off = _rebaseInfo.size() ? _startOfRebaseInfo : 0;
- di->rebase_size = _rebaseInfo.size();
- di->bind_off = _bindingInfo.size() ? _startOfBindingInfo : 0;
- di->bind_size = _bindingInfo.size();
- di->weak_bind_off = 0;
- di->weak_bind_size = 0;
- di->lazy_bind_off = _lazyBindingInfo.size() ? _startOfLazyBindingInfo : 0;
- di->lazy_bind_size = _lazyBindingInfo.size();
- di->export_off = _exportTrie.size() ? _startOfExportTrie : 0;
- di->export_size = _exportTrie.size();
- if (_swap)
- swapStruct(*di);
- lc += sizeof(dyld_info_command);
-
- // Add LC_SYMTAB with symbol table info.
- symtab_command* st = reinterpret_cast<symtab_command*>(lc);
- st->cmd = LC_SYMTAB;
- st->cmdsize = sizeof(symtab_command);
- st->symoff = _startOfSymbols;
- st->nsyms = _file.stabsSymbols.size() + _file.localSymbols.size() +
- _file.globalSymbols.size() + _file.undefinedSymbols.size();
- st->stroff = _startOfSymbolStrings;
- st->strsize = _endOfSymbolStrings - _startOfSymbolStrings;
- if (_swap)
- swapStruct(*st);
- lc += sizeof(symtab_command);
-
- // Add LC_DYSYMTAB
- if (_file.fileType != llvm::MachO::MH_PRELOAD) {
- dysymtab_command* dst = reinterpret_cast<dysymtab_command*>(lc);
- dst->cmd = LC_DYSYMTAB;
- dst->cmdsize = sizeof(dysymtab_command);
- dst->ilocalsym = _symbolTableLocalsStartIndex;
- dst->nlocalsym = _file.stabsSymbols.size() +
- _file.localSymbols.size();
- dst->iextdefsym = _symbolTableGlobalsStartIndex;
- dst->nextdefsym = _file.globalSymbols.size();
- dst->iundefsym = _symbolTableUndefinesStartIndex;
- dst->nundefsym = _file.undefinedSymbols.size();
- dst->tocoff = 0;
- dst->ntoc = 0;
- dst->modtaboff = 0;
- dst->nmodtab = 0;
- dst->extrefsymoff = 0;
- dst->nextrefsyms = 0;
- dst->indirectsymoff = _startOfIndirectSymbols;
- dst->nindirectsyms = _indirectSymbolTableCount;
- dst->extreloff = 0;
- dst->nextrel = 0;
- dst->locreloff = 0;
- dst->nlocrel = 0;
- if (_swap)
- swapStruct(*dst);
- lc += sizeof(dysymtab_command);
- }
-
- // If main executable, add LC_LOAD_DYLINKER
- if (_file.fileType == llvm::MachO::MH_EXECUTE) {
- // Build LC_LOAD_DYLINKER load command.
- uint32_t size=pointerAlign(sizeof(dylinker_command)+dyldPath().size()+1);
- dylinker_command* dl = reinterpret_cast<dylinker_command*>(lc);
- dl->cmd = LC_LOAD_DYLINKER;
- dl->cmdsize = size;
- dl->name = sizeof(dylinker_command); // offset
- if (_swap)
- swapStruct(*dl);
- memcpy(lc+sizeof(dylinker_command), dyldPath().data(), dyldPath().size());
- lc[sizeof(dylinker_command)+dyldPath().size()] = '\0';
- lc += size;
- }
-
- // Add LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS,
- // LC_VERSION_MIN_TVOS
- writeVersionMinLoadCommand(_file, _swap, lc);
-
- // Add LC_SOURCE_VERSION
- {
- // Note, using a temporary here to appease UB as we may not be aligned
- // enough for a struct containing a uint64_t when emitting a 32-bit binary
- source_version_command sv;
- sv.cmd = LC_SOURCE_VERSION;
- sv.cmdsize = sizeof(source_version_command);
- sv.version = _file.sourceVersion;
- if (_swap)
- swapStruct(sv);
- memcpy(lc, &sv, sizeof(source_version_command));
- lc += sizeof(source_version_command);
- }
-
- // If main executable, add LC_MAIN.
- if (_file.fileType == llvm::MachO::MH_EXECUTE) {
- // Build LC_MAIN load command.
- // Note, using a temporary here to appease UB as we may not be aligned
- // enough for a struct containing a uint64_t when emitting a 32-bit binary
- entry_point_command ep;
- ep.cmd = LC_MAIN;
- ep.cmdsize = sizeof(entry_point_command);
- ep.entryoff = _file.entryAddress - _seg1addr;
- ep.stacksize = _file.stackSize;
- if (_swap)
- swapStruct(ep);
- memcpy(lc, &ep, sizeof(entry_point_command));
- lc += sizeof(entry_point_command);
- }
-
- // Add LC_LOAD_DYLIB commands
- for (const DependentDylib &dep : _file.dependentDylibs) {
- dylib_command* dc = reinterpret_cast<dylib_command*>(lc);
- uint32_t size = sizeof(dylib_command) + pointerAlign(dep.path.size()+1);
- dc->cmd = dep.kind;
- dc->cmdsize = size;
- dc->dylib.name = sizeof(dylib_command); // offset
- // needs to be some constant value different than the one in LC_ID_DYLIB
- dc->dylib.timestamp = 2;
- dc->dylib.current_version = dep.currentVersion;
- dc->dylib.compatibility_version = dep.compatVersion;
- if (_swap)
- swapStruct(*dc);
- memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size());
- lc[sizeof(dylib_command)+dep.path.size()] = '\0';
- lc += size;
- }
-
- // Add LC_RPATH
- for (const StringRef &path : _file.rpaths) {
- rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
- uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
- rpc->cmd = LC_RPATH;
- rpc->cmdsize = size;
- rpc->path = sizeof(rpath_command); // offset
- if (_swap)
- swapStruct(*rpc);
- memcpy(lc+sizeof(rpath_command), path.begin(), path.size());
- lc[sizeof(rpath_command)+path.size()] = '\0';
- lc += size;
- }
-
- // Add LC_FUNCTION_STARTS if needed.
- if (_functionStartsSize != 0) {
- linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
- dl->cmd = LC_FUNCTION_STARTS;
- dl->cmdsize = sizeof(linkedit_data_command);
- dl->dataoff = _startOfFunctionStarts;
- dl->datasize = _functionStartsSize;
- if (_swap)
- swapStruct(*dl);
- lc += sizeof(linkedit_data_command);
- }
-
- // Add LC_DATA_IN_CODE if requested.
- if (_file.generateDataInCodeLoadCommand) {
- linkedit_data_command* dl = reinterpret_cast<linkedit_data_command*>(lc);
- dl->cmd = LC_DATA_IN_CODE;
- dl->cmdsize = sizeof(linkedit_data_command);
- dl->dataoff = _startOfDataInCode;
- dl->datasize = _dataInCodeSize;
- if (_swap)
- swapStruct(*dl);
- lc += sizeof(linkedit_data_command);
- }
- }
- assert(lc == &_buffer[_endOfLoadCommands]);
- return llvm::Error::success();
-}
-
-void MachOFileLayout::writeSectionContent() {
- for (const Section &s : _file.sections) {
- // Copy all section content to output buffer.
- if (isZeroFillSection(s.type))
- continue;
- if (s.content.empty())
- continue;
- uint32_t offset = _sectInfo[&s].fileOffset;
- assert(offset >= _endOfLoadCommands);
- uint8_t *p = &_buffer[offset];
- memcpy(p, &s.content[0], s.content.size());
- p += s.content.size();
- }
-}
-
-void MachOFileLayout::writeRelocations() {
- uint32_t relOffset = _startOfRelocations;
- for (Section sect : _file.sections) {
- for (Relocation r : sect.relocations) {
- any_relocation_info* rb = reinterpret_cast<any_relocation_info*>(
- &_buffer[relOffset]);
- *rb = packRelocation(r, _swap, _bigEndianArch);
- relOffset += sizeof(any_relocation_info);
- }
- }
-}
-
-void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
- uint32_t &symOffset, uint32_t &strOffset) {
- for (const Symbol &sym : symbols) {
- if (_is64) {
- nlist_64* nb = reinterpret_cast<nlist_64*>(&_buffer[symOffset]);
- nb->n_strx = strOffset - _startOfSymbolStrings;
- nb->n_type = sym.type | sym.scope;
- nb->n_sect = sym.sect;
- nb->n_desc = sym.desc;
- nb->n_value = sym.value;
- if (_swap)
- swapStruct(*nb);
- symOffset += sizeof(nlist_64);
- } else {
- nlist* nb = reinterpret_cast<nlist*>(&_buffer[symOffset]);
- nb->n_strx = strOffset - _startOfSymbolStrings;
- nb->n_type = sym.type | sym.scope;
- nb->n_sect = sym.sect;
- nb->n_desc = sym.desc;
- nb->n_value = sym.value;
- if (_swap)
- swapStruct(*nb);
- symOffset += sizeof(nlist);
- }
- memcpy(&_buffer[strOffset], sym.name.begin(), sym.name.size());
- strOffset += sym.name.size();
- _buffer[strOffset++] ='\0'; // Strings in table have nul terminator.
- }
-}
-
-void MachOFileLayout::writeFunctionStartsInfo() {
- if (!_functionStartsSize)
- return;
- memcpy(&_buffer[_startOfFunctionStarts], _file.functionStarts.data(),
- _functionStartsSize);
-}
-
-void MachOFileLayout::writeDataInCodeInfo() {
- uint32_t offset = _startOfDataInCode;
- for (const DataInCode &entry : _file.dataInCode) {
- data_in_code_entry *dst = reinterpret_cast<data_in_code_entry*>(
- &_buffer[offset]);
- dst->offset = entry.offset;
- dst->length = entry.length;
- dst->kind = entry.kind;
- if (_swap)
- swapStruct(*dst);
- offset += sizeof(data_in_code_entry);
- }
-}
-
-void MachOFileLayout::writeSymbolTable() {
- // Write symbol table and symbol strings in parallel.
- uint32_t symOffset = _startOfSymbols;
- uint32_t strOffset = _startOfSymbolStrings;
- // Reserve n_strx offset of zero to mean no name.
- _buffer[strOffset++] = ' ';
- _buffer[strOffset++] = '\0';
- appendSymbols(_file.stabsSymbols, symOffset, strOffset);
- appendSymbols(_file.localSymbols, symOffset, strOffset);
- appendSymbols(_file.globalSymbols, symOffset, strOffset);
- appendSymbols(_file.undefinedSymbols, symOffset, strOffset);
- // Write indirect symbol table array.
- uint32_t *indirects = reinterpret_cast<uint32_t*>
- (&_buffer[_startOfIndirectSymbols]);
- if (_file.fileType == llvm::MachO::MH_OBJECT) {
- // Object files have sections in same order as input normalized file.
- for (const Section §ion : _file.sections) {
- for (uint32_t index : section.indirectSymbols) {
- if (_swap)
- *indirects++ = llvm::sys::getSwappedBytes(index);
- else
- *indirects++ = index;
- }
- }
- } else {
- // Final linked images must sort sections from normalized file.
- for (const Segment &seg : _file.segments) {
- SegExtraInfo &segInfo = _segInfo[&seg];
- for (const Section *section : segInfo.sections) {
- for (uint32_t index : section->indirectSymbols) {
- if (_swap)
- *indirects++ = llvm::sys::getSwappedBytes(index);
- else
- *indirects++ = index;
- }
- }
- }
- }
-}
-
-void MachOFileLayout::writeRebaseInfo() {
- memcpy(&_buffer[_startOfRebaseInfo], _rebaseInfo.bytes(), _rebaseInfo.size());
-}
-
-void MachOFileLayout::writeBindingInfo() {
- memcpy(&_buffer[_startOfBindingInfo],
- _bindingInfo.bytes(), _bindingInfo.size());
-}
-
-void MachOFileLayout::writeLazyBindingInfo() {
- memcpy(&_buffer[_startOfLazyBindingInfo],
- _lazyBindingInfo.bytes(), _lazyBindingInfo.size());
-}
-
-void MachOFileLayout::writeExportInfo() {
- memcpy(&_buffer[_startOfExportTrie], _exportTrie.bytes(), _exportTrie.size());
-}
-
-void MachOFileLayout::buildLinkEditInfo() {
- buildRebaseInfo();
- buildBindInfo();
- buildLazyBindInfo();
- buildExportTrie();
- computeSymbolTableSizes();
- computeFunctionStartsSize();
- computeDataInCodeSize();
-}
-
-void MachOFileLayout::buildSectionRelocations() {
-
-}
-
-void MachOFileLayout::buildRebaseInfo() {
- // TODO: compress rebasing info.
- for (const RebaseLocation& entry : _file.rebasingInfo) {
- _rebaseInfo.append_byte(REBASE_OPCODE_SET_TYPE_IMM | entry.kind);
- _rebaseInfo.append_byte(REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
- | entry.segIndex);
- _rebaseInfo.append_uleb128(entry.segOffset);
- _rebaseInfo.append_uleb128(REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1);
- }
- _rebaseInfo.append_byte(REBASE_OPCODE_DONE);
- _rebaseInfo.align(_is64 ? 8 : 4);
-}
-
-void MachOFileLayout::buildBindInfo() {
- // TODO: compress bind info.
- uint64_t lastAddend = 0;
- int lastOrdinal = 0x80000000;
- StringRef lastSymbolName;
- BindType lastType = (BindType)0;
- Hex32 lastSegOffset = ~0U;
- uint8_t lastSegIndex = (uint8_t)~0U;
- for (const BindLocation& entry : _file.bindingInfo) {
- if (entry.ordinal != lastOrdinal) {
- if (entry.ordinal <= 0)
- _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
- (entry.ordinal & BIND_IMMEDIATE_MASK));
- else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
- _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
- entry.ordinal);
- else {
- _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
- _bindingInfo.append_uleb128(entry.ordinal);
- }
- lastOrdinal = entry.ordinal;
- }
-
- if (lastSymbolName != entry.symbolName) {
- _bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
- _bindingInfo.append_string(entry.symbolName);
- lastSymbolName = entry.symbolName;
- }
-
- if (lastType != entry.kind) {
- _bindingInfo.append_byte(BIND_OPCODE_SET_TYPE_IMM | entry.kind);
- lastType = entry.kind;
- }
-
- if (lastSegIndex != entry.segIndex || lastSegOffset != entry.segOffset) {
- _bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
- | entry.segIndex);
- _bindingInfo.append_uleb128(entry.segOffset);
- lastSegIndex = entry.segIndex;
- lastSegOffset = entry.segOffset;
- }
- if (entry.addend != lastAddend) {
- _bindingInfo.append_byte(BIND_OPCODE_SET_ADDEND_SLEB);
- _bindingInfo.append_sleb128(entry.addend);
- lastAddend = entry.addend;
- }
- _bindingInfo.append_byte(BIND_OPCODE_DO_BIND);
- }
- _bindingInfo.append_byte(BIND_OPCODE_DONE);
- _bindingInfo.align(_is64 ? 8 : 4);
-}
-
-void MachOFileLayout::buildLazyBindInfo() {
- for (const BindLocation& entry : _file.lazyBindingInfo) {
- _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
- | entry.segIndex);
- _lazyBindingInfo.append_uleb128(entry.segOffset);
- if (entry.ordinal <= 0)
- _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
- (entry.ordinal & BIND_IMMEDIATE_MASK));
- else if (entry.ordinal <= BIND_IMMEDIATE_MASK)
- _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
- entry.ordinal);
- else {
- _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB);
- _lazyBindingInfo.append_uleb128(entry.ordinal);
- }
- // FIXME: We need to | the opcode here with flags.
- _lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
- _lazyBindingInfo.append_string(entry.symbolName);
- _lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
- _lazyBindingInfo.append_byte(BIND_OPCODE_DONE);
- }
- _lazyBindingInfo.align(_is64 ? 8 : 4);
-}
-
-void TrieNode::addSymbol(const Export& entry,
- BumpPtrAllocator &allocator,
- std::vector<TrieNode*> &allNodes) {
- StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
- for (TrieEdge &edge : _children) {
- StringRef edgeStr = edge._subString;
- if (partialStr.startswith(edgeStr)) {
- // Already have matching edge, go down that path.
- edge._child->addSymbol(entry, allocator, allNodes);
- return;
- }
- // See if string has common prefix with existing edge.
- for (int n=edgeStr.size()-1; n > 0; --n) {
- if (partialStr.substr(0, n).equals(edgeStr.substr(0, n))) {
- // Splice in new node: was A -> C, now A -> B -> C
- StringRef bNodeStr = edge._child->_cummulativeString;
- bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
- auto *bNode = new (allocator) TrieNode(bNodeStr);
- allNodes.push_back(bNode);
- TrieNode* cNode = edge._child;
- StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
- StringRef bcEdgeStr = edgeStr.substr(n).copy(allocator);
- DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
- << "splice in TrieNode('" << bNodeStr
- << "') between edge '"
- << abEdgeStr << "' and edge='"
- << bcEdgeStr<< "'\n");
- TrieEdge& abEdge = edge;
- abEdge._subString = abEdgeStr;
- abEdge._child = bNode;
- auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
- bNode->_children.insert(bNode->_children.end(), bcEdge);
- bNode->addSymbol(entry, allocator, allNodes);
- return;
- }
- }
- }
- if (entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
- assert(entry.otherOffset != 0);
- }
- if (entry.flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
- assert(entry.otherOffset != 0);
- }
- // No commonality with any existing child, make a new edge.
- auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
- auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
- _children.insert(_children.end(), newEdge);
- DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
- << "new TrieNode('" << entry.name << "') with edge '"
- << partialStr << "' from node='"
- << _cummulativeString << "'\n");
- newNode->_address = entry.offset;
- newNode->_flags = entry.flags | entry.kind;
- newNode->_other = entry.otherOffset;
- if ((entry.flags & EXPORT_SYMBOL_FLAGS_REEXPORT) && !entry.otherName.empty())
- newNode->_importedName = entry.otherName.copy(allocator);
- newNode->_hasExportInfo = true;
- allNodes.push_back(newNode);
-}
-
-void TrieNode::addOrderedNodes(const Export& entry,
- std::vector<TrieNode*> &orderedNodes) {
- if (!_ordered) {
- orderedNodes.push_back(this);
- _ordered = true;
- }
-
- StringRef partialStr = entry.name.drop_front(_cummulativeString.size());
- for (TrieEdge &edge : _children) {
- StringRef edgeStr = edge._subString;
- if (partialStr.startswith(edgeStr)) {
- // Already have matching edge, go down that path.
- edge._child->addOrderedNodes(entry, orderedNodes);
- return;
- }
- }
-}
-
-bool TrieNode::updateOffset(uint32_t& offset) {
- uint32_t nodeSize = 1; // Length when no export info
- if (_hasExportInfo) {
- if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
- nodeSize = llvm::getULEB128Size(_flags);
- nodeSize += llvm::getULEB128Size(_other); // Other contains ordinal.
- nodeSize += _importedName.size();
- ++nodeSize; // Trailing zero in imported name.
- } else {
- nodeSize = llvm::getULEB128Size(_flags) + llvm::getULEB128Size(_address);
- if (_flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
- nodeSize += llvm::getULEB128Size(_other);
- }
- // Overall node size so far is uleb128 of export info + actual export info.
- nodeSize += llvm::getULEB128Size(nodeSize);
- }
- // Compute size of all child edges.
- ++nodeSize; // Byte for number of children.
- for (TrieEdge &edge : _children) {
- nodeSize += edge._subString.size() + 1 // String length.
- + llvm::getULEB128Size(edge._child->_trieOffset); // Offset len.
- }
- // On input, 'offset' is new prefered location for this node.
- bool result = (_trieOffset != offset);
- // Store new location in node object for use by parents.
- _trieOffset = offset;
- // Update offset for next iteration.
- offset += nodeSize;
- // Return true if _trieOffset was changed.
- return result;
-}
-
-void TrieNode::appendToByteBuffer(ByteBuffer &out) {
- if (_hasExportInfo) {
- if (_flags & EXPORT_SYMBOL_FLAGS_REEXPORT) {
- if (!_importedName.empty()) {
- // nodes with re-export info: size, flags, ordinal, import-name
- uint32_t nodeSize = llvm::getULEB128Size(_flags)
- + llvm::getULEB128Size(_other)
- + _importedName.size() + 1;
- assert(nodeSize < 256);
- out.append_byte(nodeSize);
- out.append_uleb128(_flags);
- out.append_uleb128(_other);
- out.append_string(_importedName);
- } else {
- // nodes without re-export info: size, flags, ordinal, empty-string
- uint32_t nodeSize = llvm::getULEB128Size(_flags)
- + llvm::getULEB128Size(_other) + 1;
- assert(nodeSize < 256);
- out.append_byte(nodeSize);
- out.append_uleb128(_flags);
- out.append_uleb128(_other);
- out.append_byte(0);
- }
- } else if ( _flags & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER ) {
- // Nodes with export info: size, flags, address, other
- uint32_t nodeSize = llvm::getULEB128Size(_flags)
- + llvm::getULEB128Size(_address)
- + llvm::getULEB128Size(_other);
- assert(nodeSize < 256);
- out.append_byte(nodeSize);
- out.append_uleb128(_flags);
- out.append_uleb128(_address);
- out.append_uleb128(_other);
- } else {
- // Nodes with export info: size, flags, address
- uint32_t nodeSize = llvm::getULEB128Size(_flags)
- + llvm::getULEB128Size(_address);
- assert(nodeSize < 256);
- out.append_byte(nodeSize);
- out.append_uleb128(_flags);
- out.append_uleb128(_address);
- }
- } else {
- // Node with no export info.
- uint32_t nodeSize = 0;
- out.append_byte(nodeSize);
- }
- // Add number of children.
- assert(_children.size() < 256);
- out.append_byte(_children.size());
- // Append each child edge substring and node offset.
- for (TrieEdge &edge : _children) {
- out.append_string(edge._subString);
- out.append_uleb128(edge._child->_trieOffset);
- }
-}
-
-void MachOFileLayout::buildExportTrie() {
- if (_file.exportInfo.empty())
- return;
-
- // For all temporary strings and objects used building trie.
- BumpPtrAllocator allocator;
-
- // Build trie of all exported symbols.
- auto *rootNode = new (allocator) TrieNode(StringRef());
- std::vector<TrieNode*> allNodes;
- allNodes.reserve(_file.exportInfo.size()*2);
- allNodes.push_back(rootNode);
- for (const Export& entry : _file.exportInfo) {
- rootNode->addSymbol(entry, allocator, allNodes);
- }
-
- std::vector<TrieNode*> orderedNodes;
- orderedNodes.reserve(allNodes.size());
-
- for (const Export& entry : _file.exportInfo)
- rootNode->addOrderedNodes(entry, orderedNodes);
-
- // Assign each node in the vector an offset in the trie stream, iterating
- // until all uleb128 sizes have stabilized.
- bool more;
- do {
- uint32_t offset = 0;
- more = false;
- for (TrieNode* node : orderedNodes) {
- if (node->updateOffset(offset))
- more = true;
- }
- } while (more);
-
- // Serialize trie to ByteBuffer.
- for (TrieNode* node : orderedNodes) {
- node->appendToByteBuffer(_exportTrie);
- }
- _exportTrie.align(_is64 ? 8 : 4);
-}
-
-void MachOFileLayout::computeSymbolTableSizes() {
- // MachO symbol tables have three ranges: locals, globals, and undefines
- const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
- _symbolTableSize = nlistSize * (_file.stabsSymbols.size()
- + _file.localSymbols.size()
- + _file.globalSymbols.size()
- + _file.undefinedSymbols.size());
- // Always reserve 1-byte for the empty string and 1-byte for its terminator.
- _symbolStringPoolSize = 2;
- for (const Symbol &sym : _file.stabsSymbols) {
- _symbolStringPoolSize += (sym.name.size()+1);
- }
- for (const Symbol &sym : _file.localSymbols) {
- _symbolStringPoolSize += (sym.name.size()+1);
- }
- for (const Symbol &sym : _file.globalSymbols) {
- _symbolStringPoolSize += (sym.name.size()+1);
- }
- for (const Symbol &sym : _file.undefinedSymbols) {
- _symbolStringPoolSize += (sym.name.size()+1);
- }
- _symbolTableLocalsStartIndex = 0;
- _symbolTableGlobalsStartIndex = _file.stabsSymbols.size() +
- _file.localSymbols.size();
- _symbolTableUndefinesStartIndex = _symbolTableGlobalsStartIndex
- + _file.globalSymbols.size();
-
- _indirectSymbolTableCount = 0;
- for (const Section § : _file.sections) {
- _indirectSymbolTableCount += sect.indirectSymbols.size();
- }
-}
-
-void MachOFileLayout::computeFunctionStartsSize() {
- _functionStartsSize = _file.functionStarts.size();
-}
-
-void MachOFileLayout::computeDataInCodeSize() {
- _dataInCodeSize = _file.dataInCode.size() * sizeof(data_in_code_entry);
-}
-
-void MachOFileLayout::writeLinkEditContent() {
- if (_file.fileType == llvm::MachO::MH_OBJECT) {
- writeRelocations();
- writeFunctionStartsInfo();
- writeDataInCodeInfo();
- writeSymbolTable();
- } else {
- writeRebaseInfo();
- writeBindingInfo();
- writeLazyBindingInfo();
- // TODO: add weak binding info
- writeExportInfo();
- writeFunctionStartsInfo();
- writeDataInCodeInfo();
- writeSymbolTable();
- }
-}
-
-llvm::Error MachOFileLayout::writeBinary(StringRef path) {
- // Check for pending error from constructor.
- if (_ec)
- return llvm::errorCodeToError(_ec);
- // Create FileOutputBuffer with calculated size.
- unsigned flags = 0;
- if (_file.fileType != llvm::MachO::MH_OBJECT)
- flags = llvm::FileOutputBuffer::F_executable;
- Expected<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
- llvm::FileOutputBuffer::create(path, size(), flags);
- if (Error E = fobOrErr.takeError())
- return E;
- std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
- // Write content.
- _buffer = fob->getBufferStart();
- writeMachHeader();
- if (auto ec = writeLoadCommands())
- return ec;
- writeSectionContent();
- writeLinkEditContent();
- if (Error E = fob->commit())
- return E;
-
- return llvm::Error::success();
-}
-
-/// Takes in-memory normalized view and writes a mach-o object file.
-llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {
- MachOFileLayout layout(file, false);
- return layout.writeBinary(path);
-}
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp ------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file Converts from in-memory Atoms to in-memory normalized mach-o.
-///
-/// +------------+
-/// | normalized |
-/// +------------+
-/// ^
-/// |
-/// |
-/// +-------+
-/// | Atoms |
-/// +-------+
-
-#include "ArchHandler.h"
-#include "DebugInfo.h"
-#include "MachONormalizedFile.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include <map>
-#include <system_error>
-#include <unordered_set>
-
-using llvm::StringRef;
-using llvm::isa;
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-using namespace lld;
-
-namespace {
-
-struct AtomInfo {
- const DefinedAtom *atom;
- uint64_t offsetInSection;
-};
-
-struct SectionInfo {
- SectionInfo(StringRef seg, StringRef sect, SectionType type,
- const MachOLinkingContext &ctxt, uint32_t attr,
- bool relocsToDefinedCanBeImplicit);
-
- StringRef segmentName;
- StringRef sectionName;
- SectionType type;
- uint32_t attributes;
- uint64_t address;
- uint64_t size;
- uint16_t alignment;
-
- /// If this is set, the any relocs in this section which point to defined
- /// addresses can be implicitly generated. This is the case for the
- /// __eh_frame section where references to the function can be implicit if the
- /// function is defined.
- bool relocsToDefinedCanBeImplicit;
-
-
- std::vector<AtomInfo> atomsAndOffsets;
- uint32_t normalizedSectionIndex;
- uint32_t finalSectionIndex;
-};
-
-SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t,
- const MachOLinkingContext &ctxt, uint32_t attrs,
- bool relocsToDefinedCanBeImplicit)
- : segmentName(sg), sectionName(sct), type(t), attributes(attrs),
- address(0), size(0), alignment(1),
- relocsToDefinedCanBeImplicit(relocsToDefinedCanBeImplicit),
- normalizedSectionIndex(0), finalSectionIndex(0) {
- uint16_t align = 1;
- if (ctxt.sectionAligned(segmentName, sectionName, align)) {
- alignment = align;
- }
-}
-
-struct SegmentInfo {
- SegmentInfo(StringRef name);
-
- StringRef name;
- uint64_t address;
- uint64_t size;
- uint32_t init_access;
- uint32_t max_access;
- std::vector<SectionInfo*> sections;
- uint32_t normalizedSegmentIndex;
-};
-
-SegmentInfo::SegmentInfo(StringRef n)
- : name(n), address(0), size(0), init_access(0), max_access(0),
- normalizedSegmentIndex(0) {
-}
-
-class Util {
-public:
- Util(const MachOLinkingContext &ctxt)
- : _ctx(ctxt), _archHandler(ctxt.archHandler()), _entryAtom(nullptr),
- _hasTLVDescriptors(false), _subsectionsViaSymbols(true) {}
- ~Util();
-
- void processDefinedAtoms(const lld::File &atomFile);
- void processAtomAttributes(const DefinedAtom *atom);
- void assignAtomToSection(const DefinedAtom *atom);
- void organizeSections();
- void assignAddressesToSections(const NormalizedFile &file);
- uint32_t fileFlags();
- void copySegmentInfo(NormalizedFile &file);
- void copySectionInfo(NormalizedFile &file);
- void updateSectionInfo(NormalizedFile &file);
- void buildAtomToAddressMap();
- llvm::Error synthesizeDebugNotes(NormalizedFile &file);
- llvm::Error addSymbols(const lld::File &atomFile, NormalizedFile &file);
- void addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file);
- void addRebaseAndBindingInfo(const lld::File &, NormalizedFile &file);
- void addExportInfo(const lld::File &, NormalizedFile &file);
- void addSectionRelocs(const lld::File &, NormalizedFile &file);
- void addFunctionStarts(const lld::File &, NormalizedFile &file);
- void buildDataInCodeArray(const lld::File &, NormalizedFile &file);
- void addDependentDylibs(const lld::File &, NormalizedFile &file);
- void copyEntryPointAddress(NormalizedFile &file);
- void copySectionContent(NormalizedFile &file);
-
- bool allSourceFilesHaveMinVersions() const {
- return _allSourceFilesHaveMinVersions;
- }
-
- uint32_t minVersion() const {
- return _minVersion;
- }
-
- LoadCommandType minVersionCommandType() const {
- return _minVersionCommandType;
- }
-
-private:
- typedef std::map<DefinedAtom::ContentType, SectionInfo*> TypeToSection;
- typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
-
- struct DylibInfo { int ordinal; bool hasWeak; bool hasNonWeak; };
- typedef llvm::StringMap<DylibInfo> DylibPathToInfo;
-
- SectionInfo *sectionForAtom(const DefinedAtom*);
- SectionInfo *getRelocatableSection(DefinedAtom::ContentType type);
- SectionInfo *getFinalSection(DefinedAtom::ContentType type);
- void appendAtom(SectionInfo *sect, const DefinedAtom *atom);
- SegmentInfo *segmentForName(StringRef segName);
- void layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr);
- void layoutSectionsInTextSegment(size_t, SegmentInfo *, uint64_t &);
- void copySectionContent(SectionInfo *si, ContentBytes &content);
- uint16_t descBits(const DefinedAtom* atom);
- int dylibOrdinal(const SharedLibraryAtom *sa);
- void segIndexForSection(const SectionInfo *sect,
- uint8_t &segmentIndex, uint64_t &segmentStartAddr);
- const Atom *targetOfLazyPointer(const DefinedAtom *lpAtom);
- const Atom *targetOfStub(const DefinedAtom *stubAtom);
- llvm::Error getSymbolTableRegion(const DefinedAtom* atom,
- bool &inGlobalsRegion,
- SymbolScope &symbolScope);
- void appendSection(SectionInfo *si, NormalizedFile &file);
- uint32_t sectionIndexForAtom(const Atom *atom);
- void fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
- NormalizedFile &file);
-
- typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
- struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; };
- struct AtomSorter {
- bool operator()(const AtomAndIndex &left, const AtomAndIndex &right);
- };
- struct SegmentSorter {
- bool operator()(const SegmentInfo *left, const SegmentInfo *right);
- static unsigned weight(const SegmentInfo *);
- };
- struct TextSectionSorter {
- bool operator()(const SectionInfo *left, const SectionInfo *right);
- static unsigned weight(const SectionInfo *);
- };
-
- const MachOLinkingContext &_ctx;
- mach_o::ArchHandler &_archHandler;
- llvm::BumpPtrAllocator _allocator;
- std::vector<SectionInfo*> _sectionInfos;
- std::vector<SegmentInfo*> _segmentInfos;
- TypeToSection _sectionMap;
- std::vector<SectionInfo*> _customSections;
- AtomToAddress _atomToAddress;
- DylibPathToInfo _dylibInfo;
- const DefinedAtom *_entryAtom;
- AtomToIndex _atomToSymbolIndex;
- std::vector<const Atom *> _machHeaderAliasAtoms;
- bool _hasTLVDescriptors;
- bool _subsectionsViaSymbols;
- bool _allSourceFilesHaveMinVersions = true;
- LoadCommandType _minVersionCommandType = (LoadCommandType)0;
- uint32_t _minVersion = 0;
- std::vector<lld::mach_o::Stab> _stabs;
-};
-
-Util::~Util() {
- // The SectionInfo structs are BumpPtr allocated, but atomsAndOffsets needs
- // to be deleted.
- for (SectionInfo *si : _sectionInfos) {
- // clear() destroys vector elements, but does not deallocate.
- // Instead use swap() to deallocate vector buffer.
- std::vector<AtomInfo> empty;
- si->atomsAndOffsets.swap(empty);
- }
- // The SegmentInfo structs are BumpPtr allocated, but sections needs
- // to be deleted.
- for (SegmentInfo *sgi : _segmentInfos) {
- std::vector<SectionInfo*> empty2;
- sgi->sections.swap(empty2);
- }
-}
-
-SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
- StringRef segmentName;
- StringRef sectionName;
- SectionType sectionType;
- SectionAttr sectionAttrs;
- bool relocsToDefinedCanBeImplicit;
-
- // Use same table used by when parsing .o files.
- relocatableSectionInfoForContentType(type, segmentName, sectionName,
- sectionType, sectionAttrs,
- relocsToDefinedCanBeImplicit);
- // If we already have a SectionInfo with this name, re-use it.
- // This can happen if two ContentType map to the same mach-o section.
- for (auto sect : _sectionMap) {
- if (sect.second->sectionName.equals(sectionName) &&
- sect.second->segmentName.equals(segmentName)) {
- return sect.second;
- }
- }
- // Otherwise allocate new SectionInfo object.
- auto *sect = new (_allocator)
- SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs,
- relocsToDefinedCanBeImplicit);
- _sectionInfos.push_back(sect);
- _sectionMap[type] = sect;
- return sect;
-}
-
-#define ENTRY(seg, sect, type, atomType) \
- {seg, sect, type, DefinedAtom::atomType }
-
-struct MachOFinalSectionFromAtomType {
- StringRef segmentName;
- StringRef sectionName;
- SectionType sectionType;
- DefinedAtom::ContentType atomType;
-};
-
-const MachOFinalSectionFromAtomType sectsToAtomType[] = {
- ENTRY("__TEXT", "__text", S_REGULAR, typeCode),
- ENTRY("__TEXT", "__text", S_REGULAR, typeMachHeader),
- ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString),
- ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String),
- ENTRY("__TEXT", "__const", S_REGULAR, typeConstant),
- ENTRY("__TEXT", "__const", S_4BYTE_LITERALS, typeLiteral4),
- ENTRY("__TEXT", "__const", S_8BYTE_LITERALS, typeLiteral8),
- ENTRY("__TEXT", "__const", S_16BYTE_LITERALS, typeLiteral16),
- ENTRY("__TEXT", "__stubs", S_SYMBOL_STUBS, typeStub),
- ENTRY("__TEXT", "__stub_helper", S_REGULAR, typeStubHelper),
- ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR, typeLSDA),
- ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI),
- ENTRY("__TEXT", "__unwind_info", S_REGULAR, typeProcessedUnwindInfo),
- ENTRY("__DATA", "__data", S_REGULAR, typeData),
- ENTRY("__DATA", "__const", S_REGULAR, typeConstData),
- ENTRY("__DATA", "__cfstring", S_REGULAR, typeCFString),
- ENTRY("__DATA", "__la_symbol_ptr", S_LAZY_SYMBOL_POINTERS,
- typeLazyPointer),
- ENTRY("__DATA", "__mod_init_func", S_MOD_INIT_FUNC_POINTERS,
- typeInitializerPtr),
- ENTRY("__DATA", "__mod_term_func", S_MOD_TERM_FUNC_POINTERS,
- typeTerminatorPtr),
- ENTRY("__DATA", "__got", S_NON_LAZY_SYMBOL_POINTERS,
- typeGOT),
- ENTRY("__DATA", "__nl_symbol_ptr", S_NON_LAZY_SYMBOL_POINTERS,
- typeNonLazyPointer),
- ENTRY("__DATA", "__thread_vars", S_THREAD_LOCAL_VARIABLES,
- typeThunkTLV),
- ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR,
- typeTLVInitialData),
- ENTRY("__DATA", "__thread_ptrs", S_THREAD_LOCAL_VARIABLE_POINTERS,
- typeTLVInitializerPtr),
- ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL,
- typeTLVInitialZeroFill),
- ENTRY("__DATA", "__bss", S_ZEROFILL, typeZeroFill),
- ENTRY("__DATA", "__interposing", S_INTERPOSING, typeInterposingTuples),
-};
-#undef ENTRY
-
-SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
- for (auto &p : sectsToAtomType) {
- if (p.atomType != atomType)
- continue;
- SectionAttr sectionAttrs = 0;
- switch (atomType) {
- case DefinedAtom::typeMachHeader:
- case DefinedAtom::typeCode:
- case DefinedAtom::typeStub:
- case DefinedAtom::typeStubHelper:
- sectionAttrs = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS;
- break;
- case DefinedAtom::typeThunkTLV:
- _hasTLVDescriptors = true;
- break;
- default:
- break;
- }
- // If we already have a SectionInfo with this name, re-use it.
- // This can happen if two ContentType map to the same mach-o section.
- for (auto sect : _sectionMap) {
- if (sect.second->sectionName.equals(p.sectionName) &&
- sect.second->segmentName.equals(p.segmentName)) {
- return sect.second;
- }
- }
- // Otherwise allocate new SectionInfo object.
- auto *sect = new (_allocator) SectionInfo(
- p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs,
- /* relocsToDefinedCanBeImplicit */ false);
- _sectionInfos.push_back(sect);
- _sectionMap[atomType] = sect;
- return sect;
- }
- llvm_unreachable("content type not yet supported");
-}
-
-SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
- if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
- // Section for this atom is derived from content type.
- DefinedAtom::ContentType type = atom->contentType();
- auto pos = _sectionMap.find(type);
- if ( pos != _sectionMap.end() )
- return pos->second;
- bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
- return rMode ? getRelocatableSection(type) : getFinalSection(type);
- } else {
- // This atom needs to be in a custom section.
- StringRef customName = atom->customSectionName();
- // Look to see if we have already allocated the needed custom section.
- for(SectionInfo *sect : _customSections) {
- const DefinedAtom *firstAtom = sect->atomsAndOffsets.front().atom;
- if (firstAtom->customSectionName().equals(customName)) {
- return sect;
- }
- }
- // Not found, so need to create a new custom section.
- size_t seperatorIndex = customName.find('/');
- assert(seperatorIndex != StringRef::npos);
- StringRef segName = customName.slice(0, seperatorIndex);
- StringRef sectName = customName.drop_front(seperatorIndex + 1);
- auto *sect =
- new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx,
- 0, /* relocsToDefinedCanBeImplicit */ false);
- _customSections.push_back(sect);
- _sectionInfos.push_back(sect);
- return sect;
- }
-}
-
-void Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) {
- // Figure out offset for atom in this section given alignment constraints.
- uint64_t offset = sect->size;
- DefinedAtom::Alignment atomAlign = atom->alignment();
- uint64_t align = atomAlign.value;
- uint64_t requiredModulus = atomAlign.modulus;
- uint64_t currentModulus = (offset % align);
- if ( currentModulus != requiredModulus ) {
- if ( requiredModulus > currentModulus )
- offset += requiredModulus-currentModulus;
- else
- offset += align+requiredModulus-currentModulus;
- }
- // Record max alignment of any atom in this section.
- if (align > sect->alignment)
- sect->alignment = atomAlign.value;
- // Assign atom to this section with this offset.
- AtomInfo ai = {atom, offset};
- sect->atomsAndOffsets.push_back(ai);
- // Update section size to include this atom.
- sect->size = offset + atom->size();
-}
-
-void Util::processDefinedAtoms(const lld::File &atomFile) {
- for (const DefinedAtom *atom : atomFile.defined()) {
- processAtomAttributes(atom);
- assignAtomToSection(atom);
- }
-}
-
-void Util::processAtomAttributes(const DefinedAtom *atom) {
- if (auto *machoFile = dyn_cast<mach_o::MachOFile>(&atom->file())) {
- // If the file doesn't use subsections via symbols, then make sure we don't
- // add that flag to the final output file if we have a relocatable file.
- if (!machoFile->subsectionsViaSymbols())
- _subsectionsViaSymbols = false;
-
- // All the source files must have min versions for us to output an object
- // file with a min version.
- if (auto v = machoFile->minVersion())
- _minVersion = std::max(_minVersion, v);
- else
- _allSourceFilesHaveMinVersions = false;
-
- // If we don't have a platform load command, but one of the source files
- // does, then take the one from the file.
- if (!_minVersionCommandType)
- if (auto v = machoFile->minVersionLoadCommandKind())
- _minVersionCommandType = v;
- }
-}
-
-void Util::assignAtomToSection(const DefinedAtom *atom) {
- if (atom->contentType() == DefinedAtom::typeMachHeader) {
- _machHeaderAliasAtoms.push_back(atom);
- // Assign atom to this section with this offset.
- AtomInfo ai = {atom, 0};
- sectionForAtom(atom)->atomsAndOffsets.push_back(ai);
- } else if (atom->contentType() == DefinedAtom::typeDSOHandle)
- _machHeaderAliasAtoms.push_back(atom);
- else
- appendAtom(sectionForAtom(atom), atom);
-}
-
-SegmentInfo *Util::segmentForName(StringRef segName) {
- for (SegmentInfo *si : _segmentInfos) {
- if ( si->name.equals(segName) )
- return si;
- }
- auto *info = new (_allocator) SegmentInfo(segName);
-
- // Set the initial segment protection.
- if (segName.equals("__TEXT"))
- info->init_access = VM_PROT_READ | VM_PROT_EXECUTE;
- else if (segName.equals("__PAGEZERO"))
- info->init_access = 0;
- else if (segName.equals("__LINKEDIT"))
- info->init_access = VM_PROT_READ;
- else {
- // All others default to read-write
- info->init_access = VM_PROT_READ | VM_PROT_WRITE;
- }
-
- // Set max segment protection
- // Note, its overkill to use a switch statement here, but makes it so much
- // easier to use switch coverage to catch new cases.
- switch (_ctx.os()) {
- case lld::MachOLinkingContext::OS::unknown:
- case lld::MachOLinkingContext::OS::macOSX:
- case lld::MachOLinkingContext::OS::iOS_simulator:
- if (segName.equals("__PAGEZERO")) {
- info->max_access = 0;
- break;
- }
- // All others default to all
- info->max_access = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
- break;
- case lld::MachOLinkingContext::OS::iOS:
- // iPhoneOS always uses same protection for max and initial
- info->max_access = info->init_access;
- break;
- }
- _segmentInfos.push_back(info);
- return info;
-}
-
-unsigned Util::SegmentSorter::weight(const SegmentInfo *seg) {
- return llvm::StringSwitch<unsigned>(seg->name)
- .Case("__PAGEZERO", 1)
- .Case("__TEXT", 2)
- .Case("__DATA", 3)
- .Default(100);
-}
-
-bool Util::SegmentSorter::operator()(const SegmentInfo *left,
- const SegmentInfo *right) {
- return (weight(left) < weight(right));
-}
-
-unsigned Util::TextSectionSorter::weight(const SectionInfo *sect) {
- return llvm::StringSwitch<unsigned>(sect->sectionName)
- .Case("__text", 1)
- .Case("__stubs", 2)
- .Case("__stub_helper", 3)
- .Case("__const", 4)
- .Case("__cstring", 5)
- .Case("__unwind_info", 98)
- .Case("__eh_frame", 99)
- .Default(10);
-}
-
-bool Util::TextSectionSorter::operator()(const SectionInfo *left,
- const SectionInfo *right) {
- return (weight(left) < weight(right));
-}
-
-void Util::organizeSections() {
- // NOTE!: Keep this in sync with assignAddressesToSections.
- switch (_ctx.outputMachOType()) {
- case llvm::MachO::MH_EXECUTE:
- // Main executables, need a zero-page segment
- segmentForName("__PAGEZERO");
- // Fall into next case.
- LLVM_FALLTHROUGH;
- case llvm::MachO::MH_DYLIB:
- case llvm::MachO::MH_BUNDLE:
- // All dynamic code needs TEXT segment to hold the load commands.
- segmentForName("__TEXT");
- break;
- default:
- break;
- }
- segmentForName("__LINKEDIT");
-
- // Group sections into segments.
- for (SectionInfo *si : _sectionInfos) {
- SegmentInfo *seg = segmentForName(si->segmentName);
- seg->sections.push_back(si);
- }
- // Sort segments.
- std::sort(_segmentInfos.begin(), _segmentInfos.end(), SegmentSorter());
-
- // Sort sections within segments.
- for (SegmentInfo *seg : _segmentInfos) {
- if (seg->name.equals("__TEXT")) {
- std::sort(seg->sections.begin(), seg->sections.end(),
- TextSectionSorter());
- }
- }
-
- // Record final section indexes.
- uint32_t segmentIndex = 0;
- uint32_t sectionIndex = 1;
- for (SegmentInfo *seg : _segmentInfos) {
- seg->normalizedSegmentIndex = segmentIndex++;
- for (SectionInfo *sect : seg->sections)
- sect->finalSectionIndex = sectionIndex++;
- }
-}
-
-void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) {
- seg->address = addr;
- for (SectionInfo *sect : seg->sections) {
- sect->address = llvm::alignTo(addr, sect->alignment);
- addr = sect->address + sect->size;
- }
- seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize());
-}
-
-// __TEXT segment lays out backwards so padding is at front after load commands.
-void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,
- uint64_t &addr) {
- seg->address = addr;
- // Walks sections starting at end to calculate padding for start.
- int64_t taddr = 0;
- for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) {
- SectionInfo *sect = *it;
- taddr -= sect->size;
- taddr = taddr & (0 - sect->alignment);
- }
- int64_t padding = taddr - hlcSize;
- while (padding < 0)
- padding += _ctx.pageSize();
- // Start assigning section address starting at padded offset.
- addr += (padding + hlcSize);
- for (SectionInfo *sect : seg->sections) {
- sect->address = llvm::alignTo(addr, sect->alignment);
- addr = sect->address + sect->size;
- }
- seg->size = llvm::alignTo(addr - seg->address, _ctx.pageSize());
-}
-
-void Util::assignAddressesToSections(const NormalizedFile &file) {
- // NOTE!: Keep this in sync with organizeSections.
- size_t hlcSize = headerAndLoadCommandsSize(file,
- _ctx.generateFunctionStartsLoadCommand());
- uint64_t address = 0;
- for (SegmentInfo *seg : _segmentInfos) {
- if (seg->name.equals("__PAGEZERO")) {
- seg->size = _ctx.pageZeroSize();
- address += seg->size;
- }
- else if (seg->name.equals("__TEXT")) {
- // _ctx.baseAddress() == 0 implies it was either unspecified or
- // pageZeroSize is also 0. In either case resetting address is safe.
- address = _ctx.baseAddress() ? _ctx.baseAddress() : address;
- layoutSectionsInTextSegment(hlcSize, seg, address);
- } else
- layoutSectionsInSegment(seg, address);
-
- address = llvm::alignTo(address, _ctx.pageSize());
- }
- DEBUG_WITH_TYPE("WriterMachO-norm",
- llvm::dbgs() << "assignAddressesToSections()\n";
- for (SegmentInfo *sgi : _segmentInfos) {
- llvm::dbgs() << " address=" << llvm::format("0x%08llX", sgi->address)
- << ", size=" << llvm::format("0x%08llX", sgi->size)
- << ", segment-name='" << sgi->name
- << "'\n";
- for (SectionInfo *si : sgi->sections) {
- llvm::dbgs()<< " addr=" << llvm::format("0x%08llX", si->address)
- << ", size=" << llvm::format("0x%08llX", si->size)
- << ", section-name='" << si->sectionName
- << "\n";
- }
- }
- );
-}
-
-void Util::copySegmentInfo(NormalizedFile &file) {
- for (SegmentInfo *sgi : _segmentInfos) {
- Segment seg;
- seg.name = sgi->name;
- seg.address = sgi->address;
- seg.size = sgi->size;
- seg.init_access = sgi->init_access;
- seg.max_access = sgi->max_access;
- file.segments.push_back(seg);
- }
-}
-
-void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
- // Add new empty section to end of file.sections.
- Section temp;
- file.sections.push_back(std::move(temp));
- Section* normSect = &file.sections.back();
- // Copy fields to normalized section.
- normSect->segmentName = si->segmentName;
- normSect->sectionName = si->sectionName;
- normSect->type = si->type;
- normSect->attributes = si->attributes;
- normSect->address = si->address;
- normSect->alignment = si->alignment;
- // Record where normalized section is.
- si->normalizedSectionIndex = file.sections.size()-1;
-}
-
-void Util::copySectionContent(NormalizedFile &file) {
- const bool r = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
-
- // Utility function for ArchHandler to find address of atom in output file.
- auto addrForAtom = [&] (const Atom &atom) -> uint64_t {
- auto pos = _atomToAddress.find(&atom);
- assert(pos != _atomToAddress.end());
- return pos->second;
- };
-
- auto sectionAddrForAtom = [&] (const Atom &atom) -> uint64_t {
- for (const SectionInfo *sectInfo : _sectionInfos)
- for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets)
- if (atomInfo.atom == &atom)
- return sectInfo->address;
- llvm_unreachable("atom not assigned to section");
- };
-
- for (SectionInfo *si : _sectionInfos) {
- Section *normSect = &file.sections[si->normalizedSectionIndex];
- if (isZeroFillSection(si->type)) {
- const uint8_t *empty = nullptr;
- normSect->content = llvm::makeArrayRef(empty, si->size);
- continue;
- }
- // Copy content from atoms to content buffer for section.
- llvm::MutableArrayRef<uint8_t> sectionContent;
- if (si->size) {
- uint8_t *sectContent = file.ownedAllocations.Allocate<uint8_t>(si->size);
- sectionContent = llvm::MutableArrayRef<uint8_t>(sectContent, si->size);
- normSect->content = sectionContent;
- }
- for (AtomInfo &ai : si->atomsAndOffsets) {
- if (!ai.atom->size()) {
- assert(ai.atom->begin() == ai.atom->end() &&
- "Cannot have references without content");
- continue;
- }
- auto atomContent = sectionContent.slice(ai.offsetInSection,
- ai.atom->size());
- _archHandler.generateAtomContent(*ai.atom, r, addrForAtom,
- sectionAddrForAtom, _ctx.baseAddress(),
- atomContent);
- }
- }
-}
-
-void Util::copySectionInfo(NormalizedFile &file) {
- file.sections.reserve(_sectionInfos.size());
- // Write sections grouped by segment.
- for (SegmentInfo *sgi : _segmentInfos) {
- for (SectionInfo *si : sgi->sections) {
- appendSection(si, file);
- }
- }
-}
-
-void Util::updateSectionInfo(NormalizedFile &file) {
- file.sections.reserve(_sectionInfos.size());
- // sections grouped by segment.
- for (SegmentInfo *sgi : _segmentInfos) {
- Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex];
- normSeg->address = sgi->address;
- normSeg->size = sgi->size;
- for (SectionInfo *si : sgi->sections) {
- Section *normSect = &file.sections[si->normalizedSectionIndex];
- normSect->address = si->address;
- }
- }
-}
-
-void Util::copyEntryPointAddress(NormalizedFile &nFile) {
- if (!_entryAtom) {
- nFile.entryAddress = 0;
- return;
- }
-
- if (_ctx.outputTypeHasEntry()) {
- if (_archHandler.isThumbFunction(*_entryAtom))
- nFile.entryAddress = (_atomToAddress[_entryAtom] | 1);
- else
- nFile.entryAddress = _atomToAddress[_entryAtom];
- }
-}
-
-void Util::buildAtomToAddressMap() {
- DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
- << "assign atom addresses:\n");
- const bool lookForEntry = _ctx.outputTypeHasEntry();
- for (SectionInfo *sect : _sectionInfos) {
- for (const AtomInfo &info : sect->atomsAndOffsets) {
- _atomToAddress[info.atom] = sect->address + info.offsetInSection;
- if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) &&
- (info.atom->size() != 0) &&
- info.atom->name() == _ctx.entrySymbolName()) {
- _entryAtom = info.atom;
- }
- DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
- << " address="
- << llvm::format("0x%016X", _atomToAddress[info.atom])
- << llvm::format(" 0x%09lX", info.atom)
- << ", file=#"
- << info.atom->file().ordinal()
- << ", atom=#"
- << info.atom->ordinal()
- << ", name="
- << info.atom->name()
- << ", type="
- << info.atom->contentType()
- << "\n");
- }
- }
- DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
- << "assign header alias atom addresses:\n");
- for (const Atom *atom : _machHeaderAliasAtoms) {
- _atomToAddress[atom] = _ctx.baseAddress();
-#ifndef NDEBUG
- if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) {
- DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
- << " address="
- << llvm::format("0x%016X", _atomToAddress[atom])
- << llvm::format(" 0x%09lX", atom)
- << ", file=#"
- << definedAtom->file().ordinal()
- << ", atom=#"
- << definedAtom->ordinal()
- << ", name="
- << definedAtom->name()
- << ", type="
- << definedAtom->contentType()
- << "\n");
- } else {
- DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
- << " address="
- << llvm::format("0x%016X", _atomToAddress[atom])
- << " atom=" << atom
- << " name=" << atom->name() << "\n");
- }
-#endif
- }
-}
-
-llvm::Error Util::synthesizeDebugNotes(NormalizedFile &file) {
-
- // Bail out early if we don't need to generate a debug map.
- if (_ctx.debugInfoMode() == MachOLinkingContext::DebugInfoMode::noDebugMap)
- return llvm::Error::success();
-
- std::vector<const DefinedAtom*> atomsNeedingDebugNotes;
- std::set<const mach_o::MachOFile*> filesWithStabs;
- bool objFileHasDwarf = false;
- const File *objFile = nullptr;
-
- for (SectionInfo *sect : _sectionInfos) {
- for (const AtomInfo &info : sect->atomsAndOffsets) {
- if (const DefinedAtom *atom = dyn_cast<DefinedAtom>(info.atom)) {
-
- // FIXME: No stabs/debug-notes for symbols that wouldn't be in the
- // symbol table.
- // FIXME: No stabs/debug-notes for kernel dtrace probes.
-
- if (atom->contentType() == DefinedAtom::typeCFI ||
- atom->contentType() == DefinedAtom::typeCString)
- continue;
-
- // Whenever we encounter a new file, update the 'objfileHasDwarf' flag.
- if (&info.atom->file() != objFile) {
- objFileHasDwarf = false;
- if (const mach_o::MachOFile *atomFile =
- dyn_cast<mach_o::MachOFile>(&info.atom->file())) {
- if (atomFile->debugInfo()) {
- if (isa<mach_o::DwarfDebugInfo>(atomFile->debugInfo()))
- objFileHasDwarf = true;
- else if (isa<mach_o::StabsDebugInfo>(atomFile->debugInfo()))
- filesWithStabs.insert(atomFile);
- }
- }
- }
-
- // If this atom is from a file that needs dwarf, add it to the list.
- if (objFileHasDwarf)
- atomsNeedingDebugNotes.push_back(info.atom);
- }
- }
- }
-
- // Sort atoms needing debug notes by file ordinal, then atom ordinal.
- std::sort(atomsNeedingDebugNotes.begin(), atomsNeedingDebugNotes.end(),
- [](const DefinedAtom *lhs, const DefinedAtom *rhs) {
- if (lhs->file().ordinal() != rhs->file().ordinal())
- return (lhs->file().ordinal() < rhs->file().ordinal());
- return (lhs->ordinal() < rhs->ordinal());
- });
-
- // FIXME: Handle <rdar://problem/17689030>: Add -add_ast_path option to \
- // linker which add N_AST stab entry to output
- // See OutputFile::synthesizeDebugNotes in ObjectFile.cpp in ld64.
-
- StringRef oldFileName = "";
- StringRef oldDirPath = "";
- bool wroteStartSO = false;
- std::unordered_set<std::string> seenFiles;
- for (const DefinedAtom *atom : atomsNeedingDebugNotes) {
- const auto &atomFile = cast<mach_o::MachOFile>(atom->file());
- assert(dyn_cast_or_null<lld::mach_o::DwarfDebugInfo>(atomFile.debugInfo())
- && "file for atom needing debug notes does not contain dwarf");
- auto &dwarf = cast<lld::mach_o::DwarfDebugInfo>(*atomFile.debugInfo());
-
- auto &tu = dwarf.translationUnitSource();
- StringRef newFileName = tu.name;
- StringRef newDirPath = tu.path;
-
- // Add an SO whenever the TU source file changes.
- if (newFileName != oldFileName || newDirPath != oldDirPath) {
- // Translation unit change, emit ending SO
- if (oldFileName != "")
- _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
-
- oldFileName = newFileName;
- oldDirPath = newDirPath;
-
- // If newDirPath doesn't end with a '/' we need to add one:
- if (newDirPath.back() != '/') {
- char *p =
- file.ownedAllocations.Allocate<char>(newDirPath.size() + 2);
- memcpy(p, newDirPath.data(), newDirPath.size());
- p[newDirPath.size()] = '/';
- p[newDirPath.size() + 1] = '\0';
- newDirPath = p;
- }
-
- // New translation unit, emit start SOs:
- _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newDirPath));
- _stabs.push_back(mach_o::Stab(nullptr, N_SO, 0, 0, 0, newFileName));
-
- // Synthesize OSO for start of file.
- char *fullPath = nullptr;
- {
- SmallString<1024> pathBuf(atomFile.path());
- if (auto EC = llvm::sys::fs::make_absolute(pathBuf))
- return llvm::errorCodeToError(EC);
- fullPath = file.ownedAllocations.Allocate<char>(pathBuf.size() + 1);
- memcpy(fullPath, pathBuf.c_str(), pathBuf.size() + 1);
- }
-
- // Get mod time.
- uint32_t modTime = 0;
- llvm::sys::fs::file_status stat;
- if (!llvm::sys::fs::status(fullPath, stat))
- if (llvm::sys::fs::exists(stat))
- modTime = llvm::sys::toTimeT(stat.getLastModificationTime());
-
- _stabs.push_back(mach_o::Stab(nullptr, N_OSO, _ctx.getCPUSubType(), 1,
- modTime, fullPath));
- // <rdar://problem/6337329> linker should put cpusubtype in n_sect field
- // of nlist entry for N_OSO debug note entries.
- wroteStartSO = true;
- }
-
- if (atom->contentType() == DefinedAtom::typeCode) {
- // Synthesize BNSYM and start FUN stabs.
- _stabs.push_back(mach_o::Stab(atom, N_BNSYM, 1, 0, 0, ""));
- _stabs.push_back(mach_o::Stab(atom, N_FUN, 1, 0, 0, atom->name()));
- // Synthesize any SOL stabs needed
- // FIXME: add SOL stabs.
- _stabs.push_back(mach_o::Stab(nullptr, N_FUN, 0, 0,
- atom->rawContent().size(), ""));
- _stabs.push_back(mach_o::Stab(nullptr, N_ENSYM, 1, 0,
- atom->rawContent().size(), ""));
- } else {
- if (atom->scope() == Atom::scopeTranslationUnit)
- _stabs.push_back(mach_o::Stab(atom, N_STSYM, 1, 0, 0, atom->name()));
- else
- _stabs.push_back(mach_o::Stab(nullptr, N_GSYM, 1, 0, 0, atom->name()));
- }
- }
-
- // Emit ending SO if necessary.
- if (wroteStartSO)
- _stabs.push_back(mach_o::Stab(nullptr, N_SO, 1, 0, 0, ""));
-
- // Copy any stabs from .o file.
- for (const auto *objFile : filesWithStabs) {
- const auto &stabsList =
- cast<mach_o::StabsDebugInfo>(objFile->debugInfo())->stabs();
- for (auto &stab : stabsList) {
- // FIXME: Drop stabs whose atoms have been dead-stripped.
- _stabs.push_back(stab);
- }
- }
-
- return llvm::Error::success();
-}
-
-uint16_t Util::descBits(const DefinedAtom* atom) {
- uint16_t desc = 0;
- switch (atom->merge()) {
- case lld::DefinedAtom::mergeNo:
- case lld::DefinedAtom::mergeAsTentative:
- break;
- case lld::DefinedAtom::mergeAsWeak:
- case lld::DefinedAtom::mergeAsWeakAndAddressUsed:
- desc |= N_WEAK_DEF;
- break;
- case lld::DefinedAtom::mergeSameNameAndSize:
- case lld::DefinedAtom::mergeByLargestSection:
- case lld::DefinedAtom::mergeByContent:
- llvm_unreachable("Unsupported DefinedAtom::merge()");
- break;
- }
- if (atom->contentType() == lld::DefinedAtom::typeResolver)
- desc |= N_SYMBOL_RESOLVER;
- if (atom->contentType() == lld::DefinedAtom::typeMachHeader)
- desc |= REFERENCED_DYNAMICALLY;
- if (_archHandler.isThumbFunction(*atom))
- desc |= N_ARM_THUMB_DEF;
- if (atom->deadStrip() == DefinedAtom::deadStripNever &&
- _ctx.outputMachOType() == llvm::MachO::MH_OBJECT) {
- if ((atom->contentType() != DefinedAtom::typeInitializerPtr)
- && (atom->contentType() != DefinedAtom::typeTerminatorPtr))
- desc |= N_NO_DEAD_STRIP;
- }
- return desc;
-}
-
-bool Util::AtomSorter::operator()(const AtomAndIndex &left,
- const AtomAndIndex &right) {
- return (left.atom->name().compare(right.atom->name()) < 0);
-}
-
-llvm::Error Util::getSymbolTableRegion(const DefinedAtom* atom,
- bool &inGlobalsRegion,
- SymbolScope &scope) {
- bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
- switch (atom->scope()) {
- case Atom::scopeTranslationUnit:
- scope = 0;
- inGlobalsRegion = false;
- return llvm::Error::success();
- case Atom::scopeLinkageUnit:
- if ((_ctx.exportMode() == MachOLinkingContext::ExportMode::exported) &&
- _ctx.exportSymbolNamed(atom->name())) {
- return llvm::make_error<GenericError>(
- Twine("cannot export hidden symbol ") + atom->name());
- }
- if (rMode) {
- if (_ctx.keepPrivateExterns()) {
- // -keep_private_externs means keep in globals region as N_PEXT.
- scope = N_PEXT | N_EXT;
- inGlobalsRegion = true;
- return llvm::Error::success();
- }
- }
- // scopeLinkageUnit symbols are no longer global once linked.
- scope = N_PEXT;
- inGlobalsRegion = false;
- return llvm::Error::success();
- case Atom::scopeGlobal:
- if (_ctx.exportRestrictMode()) {
- if (_ctx.exportSymbolNamed(atom->name())) {
- scope = N_EXT;
- inGlobalsRegion = true;
- return llvm::Error::success();
- } else {
- scope = N_PEXT;
- inGlobalsRegion = false;
- return llvm::Error::success();
- }
- } else {
- scope = N_EXT;
- inGlobalsRegion = true;
- return llvm::Error::success();
- }
- break;
- }
- llvm_unreachable("atom->scope() unknown enum value");
-}
-
-
-
-llvm::Error Util::addSymbols(const lld::File &atomFile,
- NormalizedFile &file) {
- bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
- // Mach-O symbol table has four regions: stabs, locals, globals, undefs.
-
- // Add all stabs.
- for (auto &stab : _stabs) {
- lld::mach_o::normalized::Symbol sym;
- sym.type = static_cast<NListType>(stab.type);
- sym.scope = 0;
- sym.sect = stab.other;
- sym.desc = stab.desc;
- if (stab.atom)
- sym.value = _atomToAddress[stab.atom];
- else
- sym.value = stab.value;
- sym.name = stab.str;
- file.stabsSymbols.push_back(sym);
- }
-
- // Add all local (non-global) symbols in address order
- std::vector<AtomAndIndex> globals;
- globals.reserve(512);
- for (SectionInfo *sect : _sectionInfos) {
- for (const AtomInfo &info : sect->atomsAndOffsets) {
- const DefinedAtom *atom = info.atom;
- if (!atom->name().empty()) {
- SymbolScope symbolScope;
- bool inGlobalsRegion;
- if (auto ec = getSymbolTableRegion(atom, inGlobalsRegion, symbolScope)){
- return ec;
- }
- if (inGlobalsRegion) {
- AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope };
- globals.push_back(ai);
- } else {
- lld::mach_o::normalized::Symbol sym;
- sym.name = atom->name();
- sym.type = N_SECT;
- sym.scope = symbolScope;
- sym.sect = sect->finalSectionIndex;
- sym.desc = descBits(atom);
- sym.value = _atomToAddress[atom];
- _atomToSymbolIndex[atom] = file.localSymbols.size();
- file.localSymbols.push_back(sym);
- }
- } else if (rMode && _archHandler.needsLocalSymbolInRelocatableFile(atom)){
- // Create 'Lxxx' labels for anonymous atoms if archHandler says so.
- static unsigned tempNum = 1;
- char tmpName[16];
- sprintf(tmpName, "L%04u", tempNum++);
- StringRef tempRef(tmpName);
- lld::mach_o::normalized::Symbol sym;
- sym.name = tempRef.copy(file.ownedAllocations);
- sym.type = N_SECT;
- sym.scope = 0;
- sym.sect = sect->finalSectionIndex;
- sym.desc = 0;
- sym.value = _atomToAddress[atom];
- _atomToSymbolIndex[atom] = file.localSymbols.size();
- file.localSymbols.push_back(sym);
- }
- }
- }
-
- // Sort global symbol alphabetically, then add to symbol table.
- std::sort(globals.begin(), globals.end(), AtomSorter());
- const uint32_t globalStartIndex = file.localSymbols.size();
- for (AtomAndIndex &ai : globals) {
- lld::mach_o::normalized::Symbol sym;
- sym.name = ai.atom->name();
- sym.type = N_SECT;
- sym.scope = ai.scope;
- sym.sect = ai.index;
- sym.desc = descBits(static_cast<const DefinedAtom*>(ai.atom));
- sym.value = _atomToAddress[ai.atom];
- _atomToSymbolIndex[ai.atom] = globalStartIndex + file.globalSymbols.size();
- file.globalSymbols.push_back(sym);
- }
-
- // Sort undefined symbol alphabetically, then add to symbol table.
- std::vector<AtomAndIndex> undefs;
- undefs.reserve(128);
- for (const UndefinedAtom *atom : atomFile.undefined()) {
- AtomAndIndex ai = { atom, 0, N_EXT };
- undefs.push_back(ai);
- }
- for (const SharedLibraryAtom *atom : atomFile.sharedLibrary()) {
- AtomAndIndex ai = { atom, 0, N_EXT };
- undefs.push_back(ai);
- }
- std::sort(undefs.begin(), undefs.end(), AtomSorter());
- const uint32_t start = file.globalSymbols.size() + file.localSymbols.size();
- for (AtomAndIndex &ai : undefs) {
- lld::mach_o::normalized::Symbol sym;
- uint16_t desc = 0;
- if (!rMode) {
- uint8_t ordinal = 0;
- if (!_ctx.useFlatNamespace())
- ordinal = dylibOrdinal(dyn_cast<SharedLibraryAtom>(ai.atom));
- llvm::MachO::SET_LIBRARY_ORDINAL(desc, ordinal);
- }
- sym.name = ai.atom->name();
- sym.type = N_UNDF;
- sym.scope = ai.scope;
- sym.sect = 0;
- sym.desc = desc;
- sym.value = 0;
- _atomToSymbolIndex[ai.atom] = file.undefinedSymbols.size() + start;
- file.undefinedSymbols.push_back(sym);
- }
-
- return llvm::Error::success();
-}
-
-const Atom *Util::targetOfLazyPointer(const DefinedAtom *lpAtom) {
- for (const Reference *ref : *lpAtom) {
- if (_archHandler.isLazyPointer(*ref)) {
- return ref->target();
- }
- }
- return nullptr;
-}
-
-const Atom *Util::targetOfStub(const DefinedAtom *stubAtom) {
- for (const Reference *ref : *stubAtom) {
- if (const Atom *ta = ref->target()) {
- if (const DefinedAtom *lpAtom = dyn_cast<DefinedAtom>(ta)) {
- const Atom *target = targetOfLazyPointer(lpAtom);
- if (target)
- return target;
- }
- }
- }
- return nullptr;
-}
-
-void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) {
- for (SectionInfo *si : _sectionInfos) {
- Section &normSect = file.sections[si->normalizedSectionIndex];
- switch (si->type) {
- case llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS:
- for (const AtomInfo &info : si->atomsAndOffsets) {
- bool foundTarget = false;
- for (const Reference *ref : *info.atom) {
- const Atom *target = ref->target();
- if (target) {
- if (isa<const SharedLibraryAtom>(target)) {
- uint32_t index = _atomToSymbolIndex[target];
- normSect.indirectSymbols.push_back(index);
- foundTarget = true;
- } else {
- normSect.indirectSymbols.push_back(
- llvm::MachO::INDIRECT_SYMBOL_LOCAL);
- }
- }
- }
- if (!foundTarget) {
- normSect.indirectSymbols.push_back(
- llvm::MachO::INDIRECT_SYMBOL_ABS);
- }
- }
- break;
- case llvm::MachO::S_LAZY_SYMBOL_POINTERS:
- for (const AtomInfo &info : si->atomsAndOffsets) {
- const Atom *target = targetOfLazyPointer(info.atom);
- if (target) {
- uint32_t index = _atomToSymbolIndex[target];
- normSect.indirectSymbols.push_back(index);
- }
- }
- break;
- case llvm::MachO::S_SYMBOL_STUBS:
- for (const AtomInfo &info : si->atomsAndOffsets) {
- const Atom *target = targetOfStub(info.atom);
- if (target) {
- uint32_t index = _atomToSymbolIndex[target];
- normSect.indirectSymbols.push_back(index);
- }
- }
- break;
- default:
- break;
- }
- }
-}
-
-void Util::addDependentDylibs(const lld::File &atomFile,
- NormalizedFile &nFile) {
- // Scan all imported symbols and build up list of dylibs they are from.
- int ordinal = 1;
- for (const auto *dylib : _ctx.allDylibs()) {
- DylibPathToInfo::iterator pos = _dylibInfo.find(dylib->installName());
- if (pos == _dylibInfo.end()) {
- DylibInfo info;
- bool flatNamespaceAtom = dylib == _ctx.flatNamespaceFile();
-
- // If we're in -flat_namespace mode (or this atom came from the flat
- // namespace file under -undefined dynamic_lookup) then use the flat
- // lookup ordinal.
- if (flatNamespaceAtom || _ctx.useFlatNamespace())
- info.ordinal = BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
- else
- info.ordinal = ordinal++;
- info.hasWeak = false;
- info.hasNonWeak = !info.hasWeak;
- _dylibInfo[dylib->installName()] = info;
-
- // Unless this was a flat_namespace atom, record the source dylib.
- if (!flatNamespaceAtom) {
- DependentDylib depInfo;
- depInfo.path = dylib->installName();
- depInfo.kind = llvm::MachO::LC_LOAD_DYLIB;
- depInfo.currentVersion = _ctx.dylibCurrentVersion(dylib->path());
- depInfo.compatVersion = _ctx.dylibCompatVersion(dylib->path());
- nFile.dependentDylibs.push_back(depInfo);
- }
- } else {
- pos->second.hasWeak = false;
- pos->second.hasNonWeak = !pos->second.hasWeak;
- }
- }
- // Automatically weak link dylib in which all symbols are weak (canBeNull).
- for (DependentDylib &dep : nFile.dependentDylibs) {
- DylibInfo &info = _dylibInfo[dep.path];
- if (info.hasWeak && !info.hasNonWeak)
- dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB;
- else if (_ctx.isUpwardDylib(dep.path))
- dep.kind = llvm::MachO::LC_LOAD_UPWARD_DYLIB;
- }
-}
-
-int Util::dylibOrdinal(const SharedLibraryAtom *sa) {
- return _dylibInfo[sa->loadName()].ordinal;
-}
-
-void Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex,
- uint64_t &segmentStartAddr) {
- segmentIndex = 0;
- for (const SegmentInfo *seg : _segmentInfos) {
- if ((seg->address <= sect->address)
- && (seg->address+seg->size >= sect->address+sect->size)) {
- segmentStartAddr = seg->address;
- return;
- }
- ++segmentIndex;
- }
- llvm_unreachable("section not in any segment");
-}
-
-uint32_t Util::sectionIndexForAtom(const Atom *atom) {
- uint64_t address = _atomToAddress[atom];
- for (const SectionInfo *si : _sectionInfos) {
- if ((si->address <= address) && (address < si->address+si->size))
- return si->finalSectionIndex;
- }
- llvm_unreachable("atom not in any section");
-}
-
-void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
- if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
- return;
-
- // Utility function for ArchHandler to find symbol index for an atom.
- auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t {
- auto pos = _atomToSymbolIndex.find(&atom);
- assert(pos != _atomToSymbolIndex.end());
- return pos->second;
- };
-
- // Utility function for ArchHandler to find section index for an atom.
- auto sectIndexForAtom = [&] (const Atom &atom) -> uint32_t {
- return sectionIndexForAtom(&atom);
- };
-
- // Utility function for ArchHandler to find address of atom in output file.
- auto addressForAtom = [&] (const Atom &atom) -> uint64_t {
- auto pos = _atomToAddress.find(&atom);
- assert(pos != _atomToAddress.end());
- return pos->second;
- };
-
- for (SectionInfo *si : _sectionInfos) {
- Section &normSect = file.sections[si->normalizedSectionIndex];
- for (const AtomInfo &info : si->atomsAndOffsets) {
- const DefinedAtom *atom = info.atom;
- for (const Reference *ref : *atom) {
- // Skip emitting relocs for sections which are always able to be
- // implicitly regenerated and where the relocation targets an address
- // which is defined.
- if (si->relocsToDefinedCanBeImplicit && isa<DefinedAtom>(ref->target()))
- continue;
- _archHandler.appendSectionRelocations(*atom, info.offsetInSection, *ref,
- symIndexForAtom,
- sectIndexForAtom,
- addressForAtom,
- normSect.relocations);
- }
- }
- }
-}
-
-void Util::addFunctionStarts(const lld::File &, NormalizedFile &file) {
- if (!_ctx.generateFunctionStartsLoadCommand())
- return;
- file.functionStarts.reserve(8192);
- // Delta compress function starts, starting with the mach header symbol.
- const uint64_t badAddress = ~0ULL;
- uint64_t addr = badAddress;
- for (SectionInfo *si : _sectionInfos) {
- for (const AtomInfo &info : si->atomsAndOffsets) {
- auto type = info.atom->contentType();
- if (type == DefinedAtom::typeMachHeader) {
- addr = _atomToAddress[info.atom];
- continue;
- }
- if (type != DefinedAtom::typeCode)
- continue;
- assert(addr != badAddress && "Missing mach header symbol");
- // Skip atoms which have 0 size. This is so that LC_FUNCTION_STARTS
- // can't spill in to the next section.
- if (!info.atom->size())
- continue;
- uint64_t nextAddr = _atomToAddress[info.atom];
- if (_archHandler.isThumbFunction(*info.atom))
- nextAddr |= 1;
- uint64_t delta = nextAddr - addr;
- if (delta) {
- ByteBuffer buffer;
- buffer.append_uleb128(delta);
- file.functionStarts.insert(file.functionStarts.end(), buffer.bytes(),
- buffer.bytes() + buffer.size());
- }
- addr = nextAddr;
- }
- }
-
- // Null terminate, and pad to pointer size for this arch.
- file.functionStarts.push_back(0);
-
- auto size = file.functionStarts.size();
- for (unsigned i = size, e = llvm::alignTo(size, _ctx.is64Bit() ? 8 : 4);
- i != e; ++i)
- file.functionStarts.push_back(0);
-}
-
-void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) {
- if (!_ctx.generateDataInCodeLoadCommand())
- return;
- for (SectionInfo *si : _sectionInfos) {
- for (const AtomInfo &info : si->atomsAndOffsets) {
- // Atoms that contain data-in-code have "transition" references
- // which mark a point where the embedded data starts of ends.
- // This needs to be converted to the mach-o format which is an array
- // of data-in-code ranges.
- uint32_t startOffset = 0;
- DataRegionType mode = DataRegionType(0);
- for (const Reference *ref : *info.atom) {
- if (ref->kindNamespace() != Reference::KindNamespace::mach_o)
- continue;
- if (_archHandler.isDataInCodeTransition(ref->kindValue())) {
- DataRegionType nextMode = (DataRegionType)ref->addend();
- if (mode != nextMode) {
- if (mode != 0) {
- // Found end data range, so make range entry.
- DataInCode entry;
- entry.offset = si->address + info.offsetInSection + startOffset;
- entry.length = ref->offsetInAtom() - startOffset;
- entry.kind = mode;
- file.dataInCode.push_back(entry);
- }
- }
- mode = nextMode;
- startOffset = ref->offsetInAtom();
- }
- }
- if (mode != 0) {
- // Function ends with data (no end transition).
- DataInCode entry;
- entry.offset = si->address + info.offsetInSection + startOffset;
- entry.length = info.atom->size() - startOffset;
- entry.kind = mode;
- file.dataInCode.push_back(entry);
- }
- }
- }
-}
-
-void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
- NormalizedFile &nFile) {
- if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT)
- return;
-
- uint8_t segmentIndex;
- uint64_t segmentStartAddr;
- uint32_t offsetInBindInfo = 0;
-
- for (SectionInfo *sect : _sectionInfos) {
- segIndexForSection(sect, segmentIndex, segmentStartAddr);
- for (const AtomInfo &info : sect->atomsAndOffsets) {
- const DefinedAtom *atom = info.atom;
- for (const Reference *ref : *atom) {
- uint64_t segmentOffset = _atomToAddress[atom] + ref->offsetInAtom()
- - segmentStartAddr;
- const Atom* targ = ref->target();
- if (_archHandler.isPointer(*ref)) {
- // A pointer to a DefinedAtom requires rebasing.
- if (isa<DefinedAtom>(targ)) {
- RebaseLocation rebase;
- rebase.segIndex = segmentIndex;
- rebase.segOffset = segmentOffset;
- rebase.kind = llvm::MachO::REBASE_TYPE_POINTER;
- nFile.rebasingInfo.push_back(rebase);
- }
- // A pointer to an SharedLibraryAtom requires binding.
- if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) {
- BindLocation bind;
- bind.segIndex = segmentIndex;
- bind.segOffset = segmentOffset;
- bind.kind = llvm::MachO::BIND_TYPE_POINTER;
- bind.canBeNull = sa->canBeNullAtRuntime();
- bind.ordinal = dylibOrdinal(sa);
- bind.symbolName = targ->name();
- bind.addend = ref->addend();
- nFile.bindingInfo.push_back(bind);
- }
- }
- else if (_archHandler.isLazyPointer(*ref)) {
- BindLocation bind;
- if (const SharedLibraryAtom *sa = dyn_cast<SharedLibraryAtom>(targ)) {
- bind.ordinal = dylibOrdinal(sa);
- } else {
- bind.ordinal = llvm::MachO::BIND_SPECIAL_DYLIB_SELF;
- }
- bind.segIndex = segmentIndex;
- bind.segOffset = segmentOffset;
- bind.kind = llvm::MachO::BIND_TYPE_POINTER;
- bind.canBeNull = false; //sa->canBeNullAtRuntime();
- bind.symbolName = targ->name();
- bind.addend = ref->addend();
- nFile.lazyBindingInfo.push_back(bind);
-
- // Now that we know the segmentOffset and the ordinal attribute,
- // we can fix the helper's code
-
- fixLazyReferenceImm(atom, offsetInBindInfo, nFile);
-
- // 5 bytes for opcodes + variable sizes (target name + \0 and offset
- // encode's size)
- offsetInBindInfo +=
- 6 + targ->name().size() + llvm::getULEB128Size(bind.segOffset);
- if (bind.ordinal > BIND_IMMEDIATE_MASK)
- offsetInBindInfo += llvm::getULEB128Size(bind.ordinal);
- }
- }
- }
- }
-}
-
-void Util::fixLazyReferenceImm(const DefinedAtom *atom, uint32_t offset,
- NormalizedFile &file) {
- for (const Reference *ref : *atom) {
- const DefinedAtom *da = dyn_cast<DefinedAtom>(ref->target());
- if (da == nullptr)
- return;
-
- const Reference *helperRef = nullptr;
- for (const Reference *hr : *da) {
- if (hr->kindValue() == _archHandler.lazyImmediateLocationKind()) {
- helperRef = hr;
- break;
- }
- }
- if (helperRef == nullptr)
- continue;
-
- // TODO: maybe get the fixed atom content from _archHandler ?
- for (SectionInfo *sectInfo : _sectionInfos) {
- for (const AtomInfo &atomInfo : sectInfo->atomsAndOffsets) {
- if (atomInfo.atom == helperRef->target()) {
- auto sectionContent =
- file.sections[sectInfo->normalizedSectionIndex].content;
- uint8_t *rawb =
- file.ownedAllocations.Allocate<uint8_t>(sectionContent.size());
- llvm::MutableArrayRef<uint8_t> newContent{rawb,
- sectionContent.size()};
- std::copy(sectionContent.begin(), sectionContent.end(),
- newContent.begin());
- llvm::support::ulittle32_t *loc =
- reinterpret_cast<llvm::support::ulittle32_t *>(
- &newContent[atomInfo.offsetInSection +
- helperRef->offsetInAtom()]);
- *loc = offset;
- file.sections[sectInfo->normalizedSectionIndex].content = newContent;
- }
- }
- }
- }
-}
-
-void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) {
- if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT)
- return;
-
- for (SectionInfo *sect : _sectionInfos) {
- for (const AtomInfo &info : sect->atomsAndOffsets) {
- const DefinedAtom *atom = info.atom;
- if (atom->scope() != Atom::scopeGlobal)
- continue;
- if (_ctx.exportRestrictMode()) {
- if (!_ctx.exportSymbolNamed(atom->name()))
- continue;
- }
- Export exprt;
- exprt.name = atom->name();
- exprt.offset = _atomToAddress[atom] - _ctx.baseAddress();
- exprt.kind = EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
- if (atom->merge() == DefinedAtom::mergeAsWeak)
- exprt.flags = EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
- else
- exprt.flags = 0;
- exprt.otherOffset = 0;
- exprt.otherName = StringRef();
- nFile.exportInfo.push_back(exprt);
- }
- }
-}
-
-uint32_t Util::fileFlags() {
- // FIXME: these need to determined at runtime.
- if (_ctx.outputMachOType() == MH_OBJECT) {
- return _subsectionsViaSymbols ? (uint32_t)MH_SUBSECTIONS_VIA_SYMBOLS : 0;
- } else {
- uint32_t flags = MH_DYLDLINK;
- if (!_ctx.useFlatNamespace())
- flags |= MH_TWOLEVEL | MH_NOUNDEFS;
- if ((_ctx.outputMachOType() == MH_EXECUTE) && _ctx.PIE())
- flags |= MH_PIE;
- if (_hasTLVDescriptors)
- flags |= (MH_PIE | MH_HAS_TLV_DESCRIPTORS);
- return flags;
- }
-}
-
-} // end anonymous namespace
-
-namespace lld {
-namespace mach_o {
-namespace normalized {
-
-/// Convert a set of Atoms into a normalized mach-o file.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-normalizedFromAtoms(const lld::File &atomFile,
- const MachOLinkingContext &context) {
- // The util object buffers info until the normalized file can be made.
- Util util(context);
- util.processDefinedAtoms(atomFile);
- util.organizeSections();
-
- std::unique_ptr<NormalizedFile> f(new NormalizedFile());
- NormalizedFile &normFile = *f.get();
- normFile.arch = context.arch();
- normFile.fileType = context.outputMachOType();
- normFile.flags = util.fileFlags();
- normFile.stackSize = context.stackSize();
- normFile.installName = context.installName();
- normFile.currentVersion = context.currentVersion();
- normFile.compatVersion = context.compatibilityVersion();
- normFile.os = context.os();
-
- // If we are emitting an object file, then the min version is the maximum
- // of the min's of all the source files and the cmdline.
- if (normFile.fileType == llvm::MachO::MH_OBJECT)
- normFile.minOSverson = std::max(context.osMinVersion(), util.minVersion());
- else
- normFile.minOSverson = context.osMinVersion();
-
- normFile.minOSVersionKind = util.minVersionCommandType();
-
- normFile.sdkVersion = context.sdkVersion();
- normFile.sourceVersion = context.sourceVersion();
-
- if (context.generateVersionLoadCommand() &&
- context.os() != MachOLinkingContext::OS::unknown)
- normFile.hasMinVersionLoadCommand = true;
- else if (normFile.fileType == llvm::MachO::MH_OBJECT &&
- util.allSourceFilesHaveMinVersions() &&
- ((normFile.os != MachOLinkingContext::OS::unknown) ||
- util.minVersionCommandType())) {
- // If we emit an object file, then it should contain a min version load
- // command if all of the source files also contained min version commands.
- // Also, we either need to have a platform, or found a platform from the
- // source object files.
- normFile.hasMinVersionLoadCommand = true;
- }
- normFile.generateDataInCodeLoadCommand =
- context.generateDataInCodeLoadCommand();
- normFile.pageSize = context.pageSize();
- normFile.rpaths = context.rpaths();
- util.addDependentDylibs(atomFile, normFile);
- util.copySegmentInfo(normFile);
- util.copySectionInfo(normFile);
- util.assignAddressesToSections(normFile);
- util.buildAtomToAddressMap();
- if (auto err = util.synthesizeDebugNotes(normFile))
- return std::move(err);
- util.updateSectionInfo(normFile);
- util.copySectionContent(normFile);
- if (auto ec = util.addSymbols(atomFile, normFile)) {
- return std::move(ec);
- }
- util.addIndirectSymbols(atomFile, normFile);
- util.addRebaseAndBindingInfo(atomFile, normFile);
- util.addExportInfo(atomFile, normFile);
- util.addSectionRelocs(atomFile, normFile);
- util.addFunctionStarts(atomFile, normFile);
- util.buildDataInCodeArray(atomFile, normFile);
- util.copyEntryPointAddress(normFile);
-
- return std::move(f);
-}
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file Converts from in-memory normalized mach-o to in-memory Atoms.
-///
-/// +------------+
-/// | normalized |
-/// +------------+
-/// |
-/// |
-/// v
-/// +-------+
-/// | Atoms |
-/// +-------+
-
-#include "ArchHandler.h"
-#include "Atoms.h"
-#include "File.h"
-#include "MachONormalizedFile.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
-#include "llvm/Support/DataExtractor.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/LEB128.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-#define DEBUG_TYPE "normalized-file-to-atoms"
-
-namespace lld {
-namespace mach_o {
-
-
-namespace { // anonymous
-
-
-#define ENTRY(seg, sect, type, atomType) \
- {seg, sect, type, DefinedAtom::atomType }
-
-struct MachORelocatableSectionToAtomType {
- StringRef segmentName;
- StringRef sectionName;
- SectionType sectionType;
- DefinedAtom::ContentType atomType;
-};
-
-const MachORelocatableSectionToAtomType sectsToAtomType[] = {
- ENTRY("__TEXT", "__text", S_REGULAR, typeCode),
- ENTRY("__TEXT", "__text", S_REGULAR, typeResolver),
- ENTRY("__TEXT", "__cstring", S_CSTRING_LITERALS, typeCString),
- ENTRY("", "", S_CSTRING_LITERALS, typeCString),
- ENTRY("__TEXT", "__ustring", S_REGULAR, typeUTF16String),
- ENTRY("__TEXT", "__const", S_REGULAR, typeConstant),
- ENTRY("__TEXT", "__const_coal", S_COALESCED, typeConstant),
- ENTRY("__TEXT", "__eh_frame", S_COALESCED, typeCFI),
- ENTRY("__TEXT", "__eh_frame", S_REGULAR, typeCFI),
- ENTRY("__TEXT", "__literal4", S_4BYTE_LITERALS, typeLiteral4),
- ENTRY("__TEXT", "__literal8", S_8BYTE_LITERALS, typeLiteral8),
- ENTRY("__TEXT", "__literal16", S_16BYTE_LITERALS, typeLiteral16),
- ENTRY("__TEXT", "__gcc_except_tab", S_REGULAR, typeLSDA),
- ENTRY("__DATA", "__data", S_REGULAR, typeData),
- ENTRY("__DATA", "__datacoal_nt", S_COALESCED, typeData),
- ENTRY("__DATA", "__const", S_REGULAR, typeConstData),
- ENTRY("__DATA", "__cfstring", S_REGULAR, typeCFString),
- ENTRY("__DATA", "__mod_init_func", S_MOD_INIT_FUNC_POINTERS,
- typeInitializerPtr),
- ENTRY("__DATA", "__mod_term_func", S_MOD_TERM_FUNC_POINTERS,
- typeTerminatorPtr),
- ENTRY("__DATA", "__got", S_NON_LAZY_SYMBOL_POINTERS,
- typeGOT),
- ENTRY("__DATA", "__bss", S_ZEROFILL, typeZeroFill),
- ENTRY("", "", S_NON_LAZY_SYMBOL_POINTERS,
- typeGOT),
- ENTRY("__DATA", "__interposing", S_INTERPOSING, typeInterposingTuples),
- ENTRY("__DATA", "__thread_vars", S_THREAD_LOCAL_VARIABLES,
- typeThunkTLV),
- ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, typeTLVInitialData),
- ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL,
- typeTLVInitialZeroFill),
- ENTRY("__DATA", "__objc_imageinfo", S_REGULAR, typeObjCImageInfo),
- ENTRY("__DATA", "__objc_catlist", S_REGULAR, typeObjC2CategoryList),
- ENTRY("", "", S_INTERPOSING, typeInterposingTuples),
- ENTRY("__LD", "__compact_unwind", S_REGULAR,
- typeCompactUnwindInfo),
- ENTRY("", "", S_REGULAR, typeUnknown)
-};
-#undef ENTRY
-
-
-/// Figures out ContentType of a mach-o section.
-DefinedAtom::ContentType atomTypeFromSection(const Section §ion,
- bool &customSectionName) {
- // First look for match of name and type. Empty names in table are wildcards.
- customSectionName = false;
- for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
- p->atomType != DefinedAtom::typeUnknown; ++p) {
- if (p->sectionType != section.type)
- continue;
- if (!p->segmentName.equals(section.segmentName) && !p->segmentName.empty())
- continue;
- if (!p->sectionName.equals(section.sectionName) && !p->sectionName.empty())
- continue;
- customSectionName = p->segmentName.empty() && p->sectionName.empty();
- return p->atomType;
- }
- // Look for code denoted by section attributes
- if (section.attributes & S_ATTR_PURE_INSTRUCTIONS)
- return DefinedAtom::typeCode;
-
- return DefinedAtom::typeUnknown;
-}
-
-enum AtomizeModel {
- atomizeAtSymbols,
- atomizeFixedSize,
- atomizePointerSize,
- atomizeUTF8,
- atomizeUTF16,
- atomizeCFI,
- atomizeCU,
- atomizeCFString
-};
-
-/// Returns info on how to atomize a section of the specified ContentType.
-void sectionParseInfo(DefinedAtom::ContentType atomType,
- unsigned int &sizeMultiple,
- DefinedAtom::Scope &scope,
- DefinedAtom::Merge &merge,
- AtomizeModel &atomizeModel) {
- struct ParseInfo {
- DefinedAtom::ContentType atomType;
- unsigned int sizeMultiple;
- DefinedAtom::Scope scope;
- DefinedAtom::Merge merge;
- AtomizeModel atomizeModel;
- };
-
- #define ENTRY(type, size, scope, merge, model) \
- {DefinedAtom::type, size, DefinedAtom::scope, DefinedAtom::merge, model }
-
- static const ParseInfo parseInfo[] = {
- ENTRY(typeCode, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeData, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeConstData, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeZeroFill, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeConstant, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols),
- ENTRY(typeCString, 1, scopeLinkageUnit, mergeByContent,
- atomizeUTF8),
- ENTRY(typeUTF16String, 1, scopeLinkageUnit, mergeByContent,
- atomizeUTF16),
- ENTRY(typeCFI, 4, scopeTranslationUnit, mergeNo,
- atomizeCFI),
- ENTRY(typeLiteral4, 4, scopeLinkageUnit, mergeByContent,
- atomizeFixedSize),
- ENTRY(typeLiteral8, 8, scopeLinkageUnit, mergeByContent,
- atomizeFixedSize),
- ENTRY(typeLiteral16, 16, scopeLinkageUnit, mergeByContent,
- atomizeFixedSize),
- ENTRY(typeCFString, 4, scopeLinkageUnit, mergeByContent,
- atomizeCFString),
- ENTRY(typeInitializerPtr, 4, scopeTranslationUnit, mergeNo,
- atomizePointerSize),
- ENTRY(typeTerminatorPtr, 4, scopeTranslationUnit, mergeNo,
- atomizePointerSize),
- ENTRY(typeCompactUnwindInfo, 4, scopeTranslationUnit, mergeNo,
- atomizeCU),
- ENTRY(typeGOT, 4, scopeLinkageUnit, mergeByContent,
- atomizePointerSize),
- ENTRY(typeObjC2CategoryList, 4, scopeTranslationUnit, mergeByContent,
- atomizePointerSize),
- ENTRY(typeUnknown, 1, scopeGlobal, mergeNo,
- atomizeAtSymbols)
- };
- #undef ENTRY
- const int tableLen = sizeof(parseInfo) / sizeof(ParseInfo);
- for (int i=0; i < tableLen; ++i) {
- if (parseInfo[i].atomType == atomType) {
- sizeMultiple = parseInfo[i].sizeMultiple;
- scope = parseInfo[i].scope;
- merge = parseInfo[i].merge;
- atomizeModel = parseInfo[i].atomizeModel;
- return;
- }
- }
-
- // Unknown type is atomized by symbols.
- sizeMultiple = 1;
- scope = DefinedAtom::scopeGlobal;
- merge = DefinedAtom::mergeNo;
- atomizeModel = atomizeAtSymbols;
-}
-
-
-Atom::Scope atomScope(uint8_t scope) {
- switch (scope) {
- case N_EXT:
- return Atom::scopeGlobal;
- case N_PEXT:
- case N_PEXT | N_EXT:
- return Atom::scopeLinkageUnit;
- case 0:
- return Atom::scopeTranslationUnit;
- }
- llvm_unreachable("unknown scope value!");
-}
-
-void appendSymbolsInSection(
- const std::vector<lld::mach_o::normalized::Symbol> &inSymbols,
- uint32_t sectionIndex,
- SmallVector<const lld::mach_o::normalized::Symbol *, 64> &outSyms) {
- for (const lld::mach_o::normalized::Symbol &sym : inSymbols) {
- // Only look at definition symbols.
- if ((sym.type & N_TYPE) != N_SECT)
- continue;
- if (sym.sect != sectionIndex)
- continue;
- outSyms.push_back(&sym);
- }
-}
-
-void atomFromSymbol(DefinedAtom::ContentType atomType, const Section §ion,
- MachOFile &file, uint64_t symbolAddr, StringRef symbolName,
- uint16_t symbolDescFlags, Atom::Scope symbolScope,
- uint64_t nextSymbolAddr, bool scatterable, bool copyRefs) {
- // Mach-O symbol table does have size in it. Instead the size is the
- // difference between this and the next symbol.
- uint64_t size = nextSymbolAddr - symbolAddr;
- uint64_t offset = symbolAddr - section.address;
- bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP) || !scatterable;
- if (isZeroFillSection(section.type)) {
- file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size,
- noDeadStrip, copyRefs, §ion);
- } else {
- DefinedAtom::Merge merge = (symbolDescFlags & N_WEAK_DEF)
- ? DefinedAtom::mergeAsWeak : DefinedAtom::mergeNo;
- bool thumb = (symbolDescFlags & N_ARM_THUMB_DEF);
- if (atomType == DefinedAtom::typeUnknown) {
- // Mach-O needs a segment and section name. Concatenate those two
- // with a / separator (e.g. "seg/sect") to fit into the lld model
- // of just a section name.
- std::string segSectName = section.segmentName.str()
- + "/" + section.sectionName.str();
- file.addDefinedAtomInCustomSection(symbolName, symbolScope, atomType,
- merge, thumb, noDeadStrip, offset,
- size, segSectName, true, §ion);
- } else {
- if ((atomType == lld::DefinedAtom::typeCode) &&
- (symbolDescFlags & N_SYMBOL_RESOLVER)) {
- atomType = lld::DefinedAtom::typeResolver;
- }
- file.addDefinedAtom(symbolName, symbolScope, atomType, merge,
- offset, size, thumb, noDeadStrip, copyRefs, §ion);
- }
- }
-}
-
-llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
- const Section §ion,
- const NormalizedFile &normalizedFile,
- MachOFile &file, bool scatterable,
- bool copyRefs) {
- // Find section's index.
- uint32_t sectIndex = 1;
- for (auto § : normalizedFile.sections) {
- if (§ == §ion)
- break;
- ++sectIndex;
- }
-
- // Find all symbols in this section.
- SmallVector<const lld::mach_o::normalized::Symbol *, 64> symbols;
- appendSymbolsInSection(normalizedFile.globalSymbols, sectIndex, symbols);
- appendSymbolsInSection(normalizedFile.localSymbols, sectIndex, symbols);
-
- // Sort symbols.
- std::sort(symbols.begin(), symbols.end(),
- [](const lld::mach_o::normalized::Symbol *lhs,
- const lld::mach_o::normalized::Symbol *rhs) -> bool {
- if (lhs == rhs)
- return false;
- // First by address.
- uint64_t lhsAddr = lhs->value;
- uint64_t rhsAddr = rhs->value;
- if (lhsAddr != rhsAddr)
- return lhsAddr < rhsAddr;
- // If same address, one is an alias so sort by scope.
- Atom::Scope lScope = atomScope(lhs->scope);
- Atom::Scope rScope = atomScope(rhs->scope);
- if (lScope != rScope)
- return lScope < rScope;
- // If same address and scope, see if one might be better as
- // the alias.
- bool lPrivate = (lhs->name.front() == 'l');
- bool rPrivate = (rhs->name.front() == 'l');
- if (lPrivate != rPrivate)
- return lPrivate;
- // If same address and scope, sort by name.
- return lhs->name < rhs->name;
- });
-
- // Debug logging of symbols.
- // for (const Symbol *sym : symbols)
- // llvm::errs() << " sym: "
- // << llvm::format("0x%08llx ", (uint64_t)sym->value)
- // << ", " << sym->name << "\n";
-
- // If section has no symbols and no content, there are no atoms.
- if (symbols.empty() && section.content.empty())
- return llvm::Error::success();
-
- if (symbols.empty()) {
- // Section has no symbols, put all content in one anonymous atom.
- atomFromSymbol(atomType, section, file, section.address, StringRef(),
- 0, Atom::scopeTranslationUnit,
- section.address + section.content.size(),
- scatterable, copyRefs);
- }
- else if (symbols.front()->value != section.address) {
- // Section has anonymous content before first symbol.
- atomFromSymbol(atomType, section, file, section.address, StringRef(),
- 0, Atom::scopeTranslationUnit, symbols.front()->value,
- scatterable, copyRefs);
- }
-
- const lld::mach_o::normalized::Symbol *lastSym = nullptr;
- for (const lld::mach_o::normalized::Symbol *sym : symbols) {
- if (lastSym != nullptr) {
- // Ignore any assembler added "ltmpNNN" symbol at start of section
- // if there is another symbol at the start.
- if ((lastSym->value != sym->value)
- || lastSym->value != section.address
- || !lastSym->name.startswith("ltmp")) {
- atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
- lastSym->desc, atomScope(lastSym->scope), sym->value,
- scatterable, copyRefs);
- }
- }
- lastSym = sym;
- }
- if (lastSym != nullptr) {
- atomFromSymbol(atomType, section, file, lastSym->value, lastSym->name,
- lastSym->desc, atomScope(lastSym->scope),
- section.address + section.content.size(),
- scatterable, copyRefs);
- }
-
- // If object built without .subsections_via_symbols, add reference chain.
- if (!scatterable) {
- MachODefinedAtom *prevAtom = nullptr;
- file.eachAtomInSection(section,
- [&](MachODefinedAtom *atom, uint64_t offset)->void {
- if (prevAtom)
- prevAtom->addReference(Reference::KindNamespace::all,
- Reference::KindArch::all,
- Reference::kindLayoutAfter, 0, atom, 0);
- prevAtom = atom;
- });
- }
-
- return llvm::Error::success();
-}
-
-llvm::Error processSection(DefinedAtom::ContentType atomType,
- const Section §ion,
- bool customSectionName,
- const NormalizedFile &normalizedFile,
- MachOFile &file, bool scatterable,
- bool copyRefs) {
- const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
- const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
-
- // Get info on how to atomize section.
- unsigned int sizeMultiple;
- DefinedAtom::Scope scope;
- DefinedAtom::Merge merge;
- AtomizeModel atomizeModel;
- sectionParseInfo(atomType, sizeMultiple, scope, merge, atomizeModel);
-
- // Validate section size.
- if ((section.content.size() % sizeMultiple) != 0)
- return llvm::make_error<GenericError>(Twine("Section ")
- + section.segmentName
- + "/" + section.sectionName
- + " has size ("
- + Twine(section.content.size())
- + ") which is not a multiple of "
- + Twine(sizeMultiple));
-
- if (atomizeModel == atomizeAtSymbols) {
- // Break section up into atoms each with a fixed size.
- return processSymboledSection(atomType, section, normalizedFile, file,
- scatterable, copyRefs);
- } else {
- unsigned int size;
- for (unsigned int offset = 0, e = section.content.size(); offset != e;) {
- switch (atomizeModel) {
- case atomizeFixedSize:
- // Break section up into atoms each with a fixed size.
- size = sizeMultiple;
- break;
- case atomizePointerSize:
- // Break section up into atoms each the size of a pointer.
- size = is64 ? 8 : 4;
- break;
- case atomizeUTF8:
- // Break section up into zero terminated c-strings.
- size = 0;
- for (unsigned int i = offset; i < e; ++i) {
- if (section.content[i] == 0) {
- size = i + 1 - offset;
- break;
- }
- }
- break;
- case atomizeUTF16:
- // Break section up into zero terminated UTF16 strings.
- size = 0;
- for (unsigned int i = offset; i < e; i += 2) {
- if ((section.content[i] == 0) && (section.content[i + 1] == 0)) {
- size = i + 2 - offset;
- break;
- }
- }
- break;
- case atomizeCFI:
- // Break section up into dwarf unwind CFIs (FDE or CIE).
- size = read32(§ion.content[offset], isBig) + 4;
- if (offset+size > section.content.size()) {
- return llvm::make_error<GenericError>(Twine("Section ")
- + section.segmentName
- + "/" + section.sectionName
- + " is malformed. Size of CFI "
- "starting at offset ("
- + Twine(offset)
- + ") is past end of section.");
- }
- break;
- case atomizeCU:
- // Break section up into compact unwind entries.
- size = is64 ? 32 : 20;
- break;
- case atomizeCFString:
- // Break section up into NS/CFString objects.
- size = is64 ? 32 : 16;
- break;
- case atomizeAtSymbols:
- break;
- }
- if (size == 0) {
- return llvm::make_error<GenericError>(Twine("Section ")
- + section.segmentName
- + "/" + section.sectionName
- + " is malformed. The last atom "
- "is not zero terminated.");
- }
- if (customSectionName) {
- // Mach-O needs a segment and section name. Concatenate those two
- // with a / separator (e.g. "seg/sect") to fit into the lld model
- // of just a section name.
- std::string segSectName = section.segmentName.str()
- + "/" + section.sectionName.str();
- file.addDefinedAtomInCustomSection(StringRef(), scope, atomType,
- merge, false, false, offset,
- size, segSectName, true, §ion);
- } else {
- file.addDefinedAtom(StringRef(), scope, atomType, merge, offset, size,
- false, false, copyRefs, §ion);
- }
- offset += size;
- }
- }
- return llvm::Error::success();
-}
-
-const Section* findSectionCoveringAddress(const NormalizedFile &normalizedFile,
- uint64_t address) {
- for (const Section &s : normalizedFile.sections) {
- uint64_t sAddr = s.address;
- if ((sAddr <= address) && (address < sAddr+s.content.size())) {
- return &s;
- }
- }
- return nullptr;
-}
-
-const MachODefinedAtom *
-findAtomCoveringAddress(const NormalizedFile &normalizedFile, MachOFile &file,
- uint64_t addr, Reference::Addend &addend) {
- const Section *sect = nullptr;
- sect = findSectionCoveringAddress(normalizedFile, addr);
- if (!sect)
- return nullptr;
-
- uint32_t offsetInTarget;
- uint64_t offsetInSect = addr - sect->address;
- auto atom =
- file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
- addend = offsetInTarget;
- return atom;
-}
-
-// Walks all relocations for a section in a normalized .o file and
-// creates corresponding lld::Reference objects.
-llvm::Error convertRelocs(const Section §ion,
- const NormalizedFile &normalizedFile,
- bool scatterable,
- MachOFile &file,
- ArchHandler &handler) {
- // Utility function for ArchHandler to find atom by its address.
- auto atomByAddr = [&] (uint32_t sectIndex, uint64_t addr,
- const lld::Atom **atom, Reference::Addend *addend)
- -> llvm::Error {
- if (sectIndex > normalizedFile.sections.size())
- return llvm::make_error<GenericError>(Twine("out of range section "
- "index (") + Twine(sectIndex) + ")");
- const Section *sect = nullptr;
- if (sectIndex == 0) {
- sect = findSectionCoveringAddress(normalizedFile, addr);
- if (!sect)
- return llvm::make_error<GenericError>(Twine("address (" + Twine(addr)
- + ") is not in any section"));
- } else {
- sect = &normalizedFile.sections[sectIndex-1];
- }
- uint32_t offsetInTarget;
- uint64_t offsetInSect = addr - sect->address;
- *atom = file.findAtomCoveringAddress(*sect, offsetInSect, &offsetInTarget);
- *addend = offsetInTarget;
- return llvm::Error::success();
- };
-
- // Utility function for ArchHandler to find atom by its symbol index.
- auto atomBySymbol = [&] (uint32_t symbolIndex, const lld::Atom **result)
- -> llvm::Error {
- // Find symbol from index.
- const lld::mach_o::normalized::Symbol *sym = nullptr;
- uint32_t numStabs = normalizedFile.stabsSymbols.size();
- uint32_t numLocal = normalizedFile.localSymbols.size();
- uint32_t numGlobal = normalizedFile.globalSymbols.size();
- uint32_t numUndef = normalizedFile.undefinedSymbols.size();
- assert(symbolIndex >= numStabs && "Searched for stab via atomBySymbol?");
- if (symbolIndex < numStabs+numLocal) {
- sym = &normalizedFile.localSymbols[symbolIndex-numStabs];
- } else if (symbolIndex < numStabs+numLocal+numGlobal) {
- sym = &normalizedFile.globalSymbols[symbolIndex-numStabs-numLocal];
- } else if (symbolIndex < numStabs+numLocal+numGlobal+numUndef) {
- sym = &normalizedFile.undefinedSymbols[symbolIndex-numStabs-numLocal-
- numGlobal];
- } else {
- return llvm::make_error<GenericError>(Twine("symbol index (")
- + Twine(symbolIndex) + ") out of range");
- }
-
- // Find atom from symbol.
- if ((sym->type & N_TYPE) == N_SECT) {
- if (sym->sect > normalizedFile.sections.size())
- return llvm::make_error<GenericError>(Twine("symbol section index (")
- + Twine(sym->sect) + ") out of range ");
- const Section &symSection = normalizedFile.sections[sym->sect-1];
- uint64_t targetOffsetInSect = sym->value - symSection.address;
- MachODefinedAtom *target = file.findAtomCoveringAddress(symSection,
- targetOffsetInSect);
- if (target) {
- *result = target;
- return llvm::Error::success();
- }
- return llvm::make_error<GenericError>("no atom found for defined symbol");
- } else if ((sym->type & N_TYPE) == N_UNDF) {
- const lld::Atom *target = file.findUndefAtom(sym->name);
- if (target) {
- *result = target;
- return llvm::Error::success();
- }
- return llvm::make_error<GenericError>("no undefined atom found for sym");
- } else {
- // Search undefs
- return llvm::make_error<GenericError>("no atom found for symbol");
- }
- };
-
- const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
- // Use old-school iterator so that paired relocations can be grouped.
- for (auto it=section.relocations.begin(), e=section.relocations.end();
- it != e; ++it) {
- const Relocation &reloc = *it;
- // Find atom this relocation is in.
- if (reloc.offset > section.content.size())
- return llvm::make_error<GenericError>(
- Twine("r_address (") + Twine(reloc.offset)
- + ") is larger than section size ("
- + Twine(section.content.size()) + ")");
- uint32_t offsetInAtom;
- MachODefinedAtom *inAtom = file.findAtomCoveringAddress(section,
- reloc.offset,
- &offsetInAtom);
- assert(inAtom && "r_address in range, should have found atom");
- uint64_t fixupAddress = section.address + reloc.offset;
-
- const lld::Atom *target = nullptr;
- Reference::Addend addend = 0;
- Reference::KindValue kind;
- if (handler.isPairedReloc(reloc)) {
- // Handle paired relocations together.
- const Relocation &reloc2 = *++it;
- auto relocErr = handler.getPairReferenceInfo(
- reloc, reloc2, inAtom, offsetInAtom, fixupAddress, isBig, scatterable,
- atomByAddr, atomBySymbol, &kind, &target, &addend);
- if (relocErr) {
- return handleErrors(std::move(relocErr),
- [&](std::unique_ptr<GenericError> GE) {
- return llvm::make_error<GenericError>(
- Twine("bad relocation (") + GE->getMessage()
- + ") in section "
- + section.segmentName + "/" + section.sectionName
- + " (r1_address=" + Twine::utohexstr(reloc.offset)
- + ", r1_type=" + Twine(reloc.type)
- + ", r1_extern=" + Twine(reloc.isExtern)
- + ", r1_length=" + Twine((int)reloc.length)
- + ", r1_pcrel=" + Twine(reloc.pcRel)
- + (!reloc.scattered ? (Twine(", r1_symbolnum=")
- + Twine(reloc.symbol))
- : (Twine(", r1_scattered=1, r1_value=")
- + Twine(reloc.value)))
- + ")"
- + ", (r2_address=" + Twine::utohexstr(reloc2.offset)
- + ", r2_type=" + Twine(reloc2.type)
- + ", r2_extern=" + Twine(reloc2.isExtern)
- + ", r2_length=" + Twine((int)reloc2.length)
- + ", r2_pcrel=" + Twine(reloc2.pcRel)
- + (!reloc2.scattered ? (Twine(", r2_symbolnum=")
- + Twine(reloc2.symbol))
- : (Twine(", r2_scattered=1, r2_value=")
- + Twine(reloc2.value)))
- + ")" );
- });
- }
- }
- else {
- // Use ArchHandler to convert relocation record into information
- // needed to instantiate an lld::Reference object.
- auto relocErr = handler.getReferenceInfo(
- reloc, inAtom, offsetInAtom, fixupAddress, isBig, atomByAddr,
- atomBySymbol, &kind, &target, &addend);
- if (relocErr) {
- return handleErrors(std::move(relocErr),
- [&](std::unique_ptr<GenericError> GE) {
- return llvm::make_error<GenericError>(
- Twine("bad relocation (") + GE->getMessage()
- + ") in section "
- + section.segmentName + "/" + section.sectionName
- + " (r_address=" + Twine::utohexstr(reloc.offset)
- + ", r_type=" + Twine(reloc.type)
- + ", r_extern=" + Twine(reloc.isExtern)
- + ", r_length=" + Twine((int)reloc.length)
- + ", r_pcrel=" + Twine(reloc.pcRel)
- + (!reloc.scattered ? (Twine(", r_symbolnum=") + Twine(reloc.symbol))
- : (Twine(", r_scattered=1, r_value=")
- + Twine(reloc.value)))
- + ")" );
- });
- }
- }
- // Instantiate an lld::Reference object and add to its atom.
- inAtom->addReference(Reference::KindNamespace::mach_o,
- handler.kindArch(),
- kind, offsetInAtom, target, addend);
- }
-
- return llvm::Error::success();
-}
-
-bool isDebugInfoSection(const Section §ion) {
- if ((section.attributes & S_ATTR_DEBUG) == 0)
- return false;
- return section.segmentName.equals("__DWARF");
-}
-
-static const Atom* findDefinedAtomByName(MachOFile &file, Twine name) {
- std::string strName = name.str();
- for (auto *atom : file.defined())
- if (atom->name() == strName)
- return atom;
- return nullptr;
-}
-
-static StringRef copyDebugString(StringRef str, BumpPtrAllocator &alloc) {
- char *strCopy = alloc.Allocate<char>(str.size() + 1);
- memcpy(strCopy, str.data(), str.size());
- strCopy[str.size()] = '\0';
- return strCopy;
-}
-
-llvm::Error parseStabs(MachOFile &file,
- const NormalizedFile &normalizedFile,
- bool copyRefs) {
-
- if (normalizedFile.stabsSymbols.empty())
- return llvm::Error::success();
-
- // FIXME: Kill this off when we can move to sane yaml parsing.
- std::unique_ptr<BumpPtrAllocator> allocator;
- if (copyRefs)
- allocator = std::make_unique<BumpPtrAllocator>();
-
- enum { start, inBeginEnd } state = start;
-
- const Atom *currentAtom = nullptr;
- uint64_t currentAtomAddress = 0;
- StabsDebugInfo::StabsList stabsList;
- for (const auto &stabSym : normalizedFile.stabsSymbols) {
- Stab stab(nullptr, stabSym.type, stabSym.sect, stabSym.desc,
- stabSym.value, stabSym.name);
- switch (state) {
- case start:
- switch (static_cast<StabType>(stabSym.type)) {
- case N_BNSYM:
- state = inBeginEnd;
- currentAtomAddress = stabSym.value;
- Reference::Addend addend;
- currentAtom = findAtomCoveringAddress(normalizedFile, file,
- currentAtomAddress, addend);
- if (addend != 0)
- return llvm::make_error<GenericError>(
- "Non-zero addend for BNSYM '" + stabSym.name + "' in " +
- file.path());
- if (currentAtom)
- stab.atom = currentAtom;
- else {
- // FIXME: ld64 just issues a warning here - should we match that?
- return llvm::make_error<GenericError>(
- "can't find atom for stabs BNSYM at " +
- Twine::utohexstr(stabSym.value) + " in " + file.path());
- }
- break;
- case N_SO:
- case N_OSO:
- // Not associated with an atom, just copy.
- if (copyRefs)
- stab.str = copyDebugString(stabSym.name, *allocator);
- else
- stab.str = stabSym.name;
- break;
- case N_GSYM: {
- auto colonIdx = stabSym.name.find(':');
- if (colonIdx != StringRef::npos) {
- StringRef name = stabSym.name.substr(0, colonIdx);
- currentAtom = findDefinedAtomByName(file, "_" + name);
- stab.atom = currentAtom;
- if (copyRefs)
- stab.str = copyDebugString(stabSym.name, *allocator);
- else
- stab.str = stabSym.name;
- } else {
- currentAtom = findDefinedAtomByName(file, stabSym.name);
- stab.atom = currentAtom;
- if (copyRefs)
- stab.str = copyDebugString(stabSym.name, *allocator);
- else
- stab.str = stabSym.name;
- }
- if (stab.atom == nullptr)
- return llvm::make_error<GenericError>(
- "can't find atom for N_GSYM stabs" + stabSym.name +
- " in " + file.path());
- break;
- }
- case N_FUN:
- return llvm::make_error<GenericError>(
- "old-style N_FUN stab '" + stabSym.name + "' unsupported");
- default:
- return llvm::make_error<GenericError>(
- "unrecognized stab symbol '" + stabSym.name + "'");
- }
- break;
- case inBeginEnd:
- stab.atom = currentAtom;
- switch (static_cast<StabType>(stabSym.type)) {
- case N_ENSYM:
- state = start;
- currentAtom = nullptr;
- break;
- case N_FUN:
- // Just copy the string.
- if (copyRefs)
- stab.str = copyDebugString(stabSym.name, *allocator);
- else
- stab.str = stabSym.name;
- break;
- default:
- return llvm::make_error<GenericError>(
- "unrecognized stab symbol '" + stabSym.name + "'");
- }
- }
- llvm::dbgs() << "Adding to stabsList: " << stab << "\n";
- stabsList.push_back(stab);
- }
-
- file.setDebugInfo(std::make_unique<StabsDebugInfo>(std::move(stabsList)));
-
- // FIXME: Kill this off when we fix YAML memory ownership.
- file.debugInfo()->setAllocator(std::move(allocator));
-
- return llvm::Error::success();
-}
-
-static llvm::DataExtractor
-dataExtractorFromSection(const NormalizedFile &normalizedFile,
- const Section &S) {
- const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
- const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
- StringRef SecData(reinterpret_cast<const char*>(S.content.data()),
- S.content.size());
- return llvm::DataExtractor(SecData, !isBig, is64 ? 8 : 4);
-}
-
-// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
-// inspection" code if possible.
-static uint64_t getCUAbbrevOffset(llvm::DataExtractor abbrevData,
- uint64_t abbrCode) {
- uint64_t offset = 0;
- while (abbrevData.getULEB128(&offset) != abbrCode) {
- // Tag
- abbrevData.getULEB128(&offset);
- // DW_CHILDREN
- abbrevData.getU8(&offset);
- // Attributes
- while (abbrevData.getULEB128(&offset) | abbrevData.getULEB128(&offset))
- ;
- }
- return offset;
-}
-
-// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
-// inspection" code if possible.
-static Expected<const char *>
-getIndexedString(const NormalizedFile &normalizedFile,
- llvm::dwarf::Form form, llvm::DataExtractor infoData,
- uint64_t &infoOffset, const Section &stringsSection) {
- if (form == llvm::dwarf::DW_FORM_string)
- return infoData.getCStr(&infoOffset);
- if (form != llvm::dwarf::DW_FORM_strp)
- return llvm::make_error<GenericError>(
- "string field encoded without DW_FORM_strp");
- uint64_t stringOffset = infoData.getU32(&infoOffset);
- llvm::DataExtractor stringsData =
- dataExtractorFromSection(normalizedFile, stringsSection);
- return stringsData.getCStr(&stringOffset);
-}
-
-// FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
-// inspection" code if possible.
-static llvm::Expected<TranslationUnitSource>
-readCompUnit(const NormalizedFile &normalizedFile,
- const Section &info,
- const Section &abbrev,
- const Section &strings,
- StringRef path) {
- // FIXME: Cribbed from llvm-dwp -- should share "lightweight CU DIE
- // inspection" code if possible.
- uint64_t offset = 0;
- llvm::dwarf::DwarfFormat Format = llvm::dwarf::DwarfFormat::DWARF32;
- auto infoData = dataExtractorFromSection(normalizedFile, info);
- uint32_t length = infoData.getU32(&offset);
- if (length == llvm::dwarf::DW_LENGTH_DWARF64) {
- Format = llvm::dwarf::DwarfFormat::DWARF64;
- infoData.getU64(&offset);
- }
- else if (length >= llvm::dwarf::DW_LENGTH_lo_reserved)
- return llvm::make_error<GenericError>("Malformed DWARF in " + path);
-
- uint16_t version = infoData.getU16(&offset);
-
- if (version < 2 || version > 4)
- return llvm::make_error<GenericError>("Unsupported DWARF version in " +
- path);
-
- infoData.getU32(&offset); // Abbrev offset (should be zero)
- uint8_t addrSize = infoData.getU8(&offset);
-
- uint32_t abbrCode = infoData.getULEB128(&offset);
- auto abbrevData = dataExtractorFromSection(normalizedFile, abbrev);
- uint64_t abbrevOffset = getCUAbbrevOffset(abbrevData, abbrCode);
- uint64_t tag = abbrevData.getULEB128(&abbrevOffset);
- if (tag != llvm::dwarf::DW_TAG_compile_unit)
- return llvm::make_error<GenericError>("top level DIE is not a compile unit");
- // DW_CHILDREN
- abbrevData.getU8(&abbrevOffset);
- uint32_t name;
- llvm::dwarf::Form form;
- llvm::dwarf::FormParams formParams = {version, addrSize, Format};
- TranslationUnitSource tu;
- while ((name = abbrevData.getULEB128(&abbrevOffset)) |
- (form = static_cast<llvm::dwarf::Form>(
- abbrevData.getULEB128(&abbrevOffset))) &&
- (name != 0 || form != 0)) {
- switch (name) {
- case llvm::dwarf::DW_AT_name: {
- if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
- strings))
- tu.name = *eName;
- else
- return eName.takeError();
- break;
- }
- case llvm::dwarf::DW_AT_comp_dir: {
- if (auto eName = getIndexedString(normalizedFile, form, infoData, offset,
- strings))
- tu.path = *eName;
- else
- return eName.takeError();
- break;
- }
- default:
- llvm::DWARFFormValue::skipValue(form, infoData, &offset, formParams);
- }
- }
- return tu;
-}
-
-llvm::Error parseDebugInfo(MachOFile &file,
- const NormalizedFile &normalizedFile, bool copyRefs) {
-
- // Find the interesting debug info sections.
- const Section *debugInfo = nullptr;
- const Section *debugAbbrev = nullptr;
- const Section *debugStrings = nullptr;
-
- for (auto &s : normalizedFile.sections) {
- if (s.segmentName == "__DWARF") {
- if (s.sectionName == "__debug_info")
- debugInfo = &s;
- else if (s.sectionName == "__debug_abbrev")
- debugAbbrev = &s;
- else if (s.sectionName == "__debug_str")
- debugStrings = &s;
- }
- }
-
- if (!debugInfo)
- return parseStabs(file, normalizedFile, copyRefs);
-
- if (debugInfo->content.size() == 0)
- return llvm::Error::success();
-
- if (debugInfo->content.size() < 12)
- return llvm::make_error<GenericError>("Malformed __debug_info section in " +
- file.path() + ": too small");
-
- if (!debugAbbrev)
- return llvm::make_error<GenericError>("Missing __dwarf_abbrev section in " +
- file.path());
-
- if (auto tuOrErr = readCompUnit(normalizedFile, *debugInfo, *debugAbbrev,
- *debugStrings, file.path())) {
- // FIXME: Kill of allocator and code under 'copyRefs' when we fix YAML
- // memory ownership.
- std::unique_ptr<BumpPtrAllocator> allocator;
- if (copyRefs) {
- allocator = std::make_unique<BumpPtrAllocator>();
- tuOrErr->name = copyDebugString(tuOrErr->name, *allocator);
- tuOrErr->path = copyDebugString(tuOrErr->path, *allocator);
- }
- file.setDebugInfo(std::make_unique<DwarfDebugInfo>(std::move(*tuOrErr)));
- if (copyRefs)
- file.debugInfo()->setAllocator(std::move(allocator));
- } else
- return tuOrErr.takeError();
-
- return llvm::Error::success();
-}
-
-static int64_t readSPtr(bool is64, bool isBig, const uint8_t *addr) {
- if (is64)
- return read64(addr, isBig);
-
- int32_t res = read32(addr, isBig);
- return res;
-}
-
-/// --- Augmentation String Processing ---
-
-struct CIEInfo {
- bool _augmentationDataPresent = false;
- bool _mayHaveEH = false;
- uint32_t _offsetOfLSDA = ~0U;
- uint32_t _offsetOfPersonality = ~0U;
- uint32_t _offsetOfFDEPointerEncoding = ~0U;
- uint32_t _augmentationDataLength = ~0U;
-};
-
-typedef llvm::DenseMap<const MachODefinedAtom*, CIEInfo> CIEInfoMap;
-
-static llvm::Error processAugmentationString(const uint8_t *augStr,
- CIEInfo &cieInfo,
- unsigned &len) {
-
- if (augStr[0] == '\0') {
- len = 1;
- return llvm::Error::success();
- }
-
- if (augStr[0] != 'z')
- return llvm::make_error<GenericError>("expected 'z' at start of "
- "augmentation string");
-
- cieInfo._augmentationDataPresent = true;
- uint64_t idx = 1;
-
- uint32_t offsetInAugmentationData = 0;
- while (augStr[idx] != '\0') {
- if (augStr[idx] == 'L') {
- cieInfo._offsetOfLSDA = offsetInAugmentationData;
- // This adds a single byte to the augmentation data.
- ++offsetInAugmentationData;
- ++idx;
- continue;
- }
- if (augStr[idx] == 'P') {
- cieInfo._offsetOfPersonality = offsetInAugmentationData;
- // This adds a single byte to the augmentation data for the encoding,
- // then a number of bytes for the pointer data.
- // FIXME: We are assuming 4 is correct here for the pointer size as we
- // always currently use delta32ToGOT.
- offsetInAugmentationData += 5;
- ++idx;
- continue;
- }
- if (augStr[idx] == 'R') {
- cieInfo._offsetOfFDEPointerEncoding = offsetInAugmentationData;
- // This adds a single byte to the augmentation data.
- ++offsetInAugmentationData;
- ++idx;
- continue;
- }
- if (augStr[idx] == 'e') {
- if (augStr[idx + 1] != 'h')
- return llvm::make_error<GenericError>("expected 'eh' in "
- "augmentation string");
- cieInfo._mayHaveEH = true;
- idx += 2;
- continue;
- }
- ++idx;
- }
-
- cieInfo._augmentationDataLength = offsetInAugmentationData;
-
- len = idx + 1;
- return llvm::Error::success();
-}
-
-static llvm::Error processCIE(const NormalizedFile &normalizedFile,
- MachOFile &file,
- mach_o::ArchHandler &handler,
- const Section *ehFrameSection,
- MachODefinedAtom *atom,
- uint64_t offset,
- CIEInfoMap &cieInfos) {
- const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
- const uint8_t *frameData = atom->rawContent().data();
-
- CIEInfo cieInfo;
-
- uint32_t size = read32(frameData, isBig);
- uint64_t cieIDField = size == 0xffffffffU
- ? sizeof(uint32_t) + sizeof(uint64_t)
- : sizeof(uint32_t);
- uint64_t versionField = cieIDField + sizeof(uint32_t);
- uint64_t augmentationStringField = versionField + sizeof(uint8_t);
-
- unsigned augmentationStringLength = 0;
- if (auto err = processAugmentationString(frameData + augmentationStringField,
- cieInfo, augmentationStringLength))
- return err;
-
- if (cieInfo._offsetOfPersonality != ~0U) {
- // If we have augmentation data for the personality function, then we may
- // need to implicitly generate its relocation.
-
- // Parse the EH Data field which is pointer sized.
- uint64_t EHDataField = augmentationStringField + augmentationStringLength;
- const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
- unsigned EHDataFieldSize = (cieInfo._mayHaveEH ? (is64 ? 8 : 4) : 0);
-
- // Parse Code Align Factor which is a ULEB128.
- uint64_t CodeAlignField = EHDataField + EHDataFieldSize;
- unsigned lengthFieldSize = 0;
- llvm::decodeULEB128(frameData + CodeAlignField, &lengthFieldSize);
-
- // Parse Data Align Factor which is a SLEB128.
- uint64_t DataAlignField = CodeAlignField + lengthFieldSize;
- llvm::decodeSLEB128(frameData + DataAlignField, &lengthFieldSize);
-
- // Parse Return Address Register which is a byte.
- uint64_t ReturnAddressField = DataAlignField + lengthFieldSize;
-
- // Parse the augmentation length which is a ULEB128.
- uint64_t AugmentationLengthField = ReturnAddressField + 1;
- uint64_t AugmentationLength =
- llvm::decodeULEB128(frameData + AugmentationLengthField,
- &lengthFieldSize);
-
- if (AugmentationLength != cieInfo._augmentationDataLength)
- return llvm::make_error<GenericError>("CIE augmentation data length "
- "mismatch");
-
- // Get the start address of the augmentation data.
- uint64_t AugmentationDataField = AugmentationLengthField + lengthFieldSize;
-
- // Parse the personality function from the augmentation data.
- uint64_t PersonalityField =
- AugmentationDataField + cieInfo._offsetOfPersonality;
-
- // Parse the personality encoding.
- // FIXME: Verify that this is a 32-bit pcrel offset.
- uint64_t PersonalityFunctionField = PersonalityField + 1;
-
- if (atom->begin() != atom->end()) {
- // If we have an explicit relocation, then make sure it matches this
- // offset as this is where we'd expect it to be applied to.
- DefinedAtom::reference_iterator CurrentRef = atom->begin();
- if (CurrentRef->offsetInAtom() != PersonalityFunctionField)
- return llvm::make_error<GenericError>("CIE personality reloc at "
- "wrong offset");
-
- if (++CurrentRef != atom->end())
- return llvm::make_error<GenericError>("CIE contains too many relocs");
- } else {
- // Implicitly generate the personality function reloc. It's assumed to
- // be a delta32 offset to a GOT entry.
- // FIXME: Parse the encoding and check this.
- int32_t funcDelta = read32(frameData + PersonalityFunctionField, isBig);
- uint64_t funcAddress = ehFrameSection->address + offset +
- PersonalityFunctionField;
- funcAddress += funcDelta;
-
- const MachODefinedAtom *func = nullptr;
- Reference::Addend addend;
- func = findAtomCoveringAddress(normalizedFile, file, funcAddress,
- addend);
- atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
- handler.unwindRefToPersonalityFunctionKind(),
- PersonalityFunctionField, func, addend);
- }
- } else if (atom->begin() != atom->end()) {
- // Otherwise, we expect there to be no relocations in this atom as the only
- // relocation would have been to the personality function.
- return llvm::make_error<GenericError>("unexpected relocation in CIE");
- }
-
-
- cieInfos[atom] = std::move(cieInfo);
-
- return llvm::Error::success();
-}
-
-static llvm::Error processFDE(const NormalizedFile &normalizedFile,
- MachOFile &file,
- mach_o::ArchHandler &handler,
- const Section *ehFrameSection,
- MachODefinedAtom *atom,
- uint64_t offset,
- const CIEInfoMap &cieInfos) {
-
- const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
- const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
-
- // Compiler wasn't lazy and actually told us what it meant.
- // Unfortunately, the compiler may not have generated references for all of
- // [cie, func, lsda] and so we still need to parse the FDE and add references
- // for any the compiler didn't generate.
- if (atom->begin() != atom->end())
- atom->sortReferences();
-
- DefinedAtom::reference_iterator CurrentRef = atom->begin();
-
- // This helper returns the reference (if one exists) at the offset we are
- // currently processing. It automatically increments the ref iterator if we
- // do return a ref, and throws an error if we pass over a ref without
- // comsuming it.
- auto currentRefGetter = [&CurrentRef,
- &atom](uint64_t Offset)->const Reference* {
- // If there are no more refs found, then we are done.
- if (CurrentRef == atom->end())
- return nullptr;
-
- const Reference *Ref = *CurrentRef;
-
- // If we haven't reached the offset for this reference, then return that
- // we don't yet have a reference to process.
- if (Offset < Ref->offsetInAtom())
- return nullptr;
-
- // If the offset is equal, then we want to process this ref.
- if (Offset == Ref->offsetInAtom()) {
- ++CurrentRef;
- return Ref;
- }
-
- // The current ref is at an offset which is earlier than the current
- // offset, then we failed to consume it when we should have. In this case
- // throw an error.
- llvm::report_fatal_error("Skipped reference when processing FDE");
- };
-
- // Helper to either get the reference at this current location, and verify
- // that it is of the expected type, or add a reference of that type.
- // Returns the reference target.
- auto verifyOrAddReference = [&](uint64_t targetAddress,
- Reference::KindValue refKind,
- uint64_t refAddress,
- bool allowsAddend)->const Atom* {
- if (auto *ref = currentRefGetter(refAddress)) {
- // The compiler already emitted a relocation for the CIE ref. This should
- // have been converted to the correct type of reference in
- // get[Pair]ReferenceInfo().
- assert(ref->kindValue() == refKind &&
- "Incorrect EHFrame reference kind");
- return ref->target();
- }
- Reference::Addend addend;
- auto *target = findAtomCoveringAddress(normalizedFile, file,
- targetAddress, addend);
- atom->addReference(Reference::KindNamespace::mach_o, handler.kindArch(),
- refKind, refAddress, target, addend);
-
- if (!allowsAddend)
- assert(!addend && "EHFrame reference cannot have addend");
- return target;
- };
-
- const uint8_t *startFrameData = atom->rawContent().data();
- const uint8_t *frameData = startFrameData;
-
- uint32_t size = read32(frameData, isBig);
- uint64_t cieFieldInFDE = size == 0xffffffffU
- ? sizeof(uint32_t) + sizeof(uint64_t)
- : sizeof(uint32_t);
-
- // Linker needs to fixup a reference from the FDE to its parent CIE (a
- // 32-bit byte offset backwards in the __eh_frame section).
- uint32_t cieDelta = read32(frameData + cieFieldInFDE, isBig);
- uint64_t cieAddress = ehFrameSection->address + offset + cieFieldInFDE;
- cieAddress -= cieDelta;
-
- auto *cieRefTarget = verifyOrAddReference(cieAddress,
- handler.unwindRefToCIEKind(),
- cieFieldInFDE, false);
- const MachODefinedAtom *cie = dyn_cast<MachODefinedAtom>(cieRefTarget);
- assert(cie && cie->contentType() == DefinedAtom::typeCFI &&
- "FDE's CIE field does not point at the start of a CIE.");
-
- const CIEInfo &cieInfo = cieInfos.find(cie)->second;
-
- // Linker needs to fixup reference from the FDE to the function it's
- // describing. FIXME: there are actually different ways to do this, and the
- // particular method used is specified in the CIE's augmentation fields
- // (hopefully)
- uint64_t rangeFieldInFDE = cieFieldInFDE + sizeof(uint32_t);
-
- int64_t functionFromFDE = readSPtr(is64, isBig,
- frameData + rangeFieldInFDE);
- uint64_t rangeStart = ehFrameSection->address + offset + rangeFieldInFDE;
- rangeStart += functionFromFDE;
-
- verifyOrAddReference(rangeStart,
- handler.unwindRefToFunctionKind(),
- rangeFieldInFDE, true);
-
- // Handle the augmentation data if there is any.
- if (cieInfo._augmentationDataPresent) {
- // First process the augmentation data length field.
- uint64_t augmentationDataLengthFieldInFDE =
- rangeFieldInFDE + 2 * (is64 ? sizeof(uint64_t) : sizeof(uint32_t));
- unsigned lengthFieldSize = 0;
- uint64_t augmentationDataLength =
- llvm::decodeULEB128(frameData + augmentationDataLengthFieldInFDE,
- &lengthFieldSize);
-
- if (cieInfo._offsetOfLSDA != ~0U && augmentationDataLength > 0) {
-
- // Look at the augmentation data field.
- uint64_t augmentationDataFieldInFDE =
- augmentationDataLengthFieldInFDE + lengthFieldSize;
-
- int64_t lsdaFromFDE = readSPtr(is64, isBig,
- frameData + augmentationDataFieldInFDE);
- uint64_t lsdaStart =
- ehFrameSection->address + offset + augmentationDataFieldInFDE +
- lsdaFromFDE;
-
- verifyOrAddReference(lsdaStart,
- handler.unwindRefToFunctionKind(),
- augmentationDataFieldInFDE, true);
- }
- }
-
- return llvm::Error::success();
-}
-
-llvm::Error addEHFrameReferences(const NormalizedFile &normalizedFile,
- MachOFile &file,
- mach_o::ArchHandler &handler) {
-
- const Section *ehFrameSection = nullptr;
- for (auto §ion : normalizedFile.sections)
- if (section.segmentName == "__TEXT" &&
- section.sectionName == "__eh_frame") {
- ehFrameSection = §ion;
- break;
- }
-
- // No __eh_frame so nothing to do.
- if (!ehFrameSection)
- return llvm::Error::success();
-
- llvm::Error ehFrameErr = llvm::Error::success();
- CIEInfoMap cieInfos;
-
- file.eachAtomInSection(*ehFrameSection,
- [&](MachODefinedAtom *atom, uint64_t offset) -> void {
- assert(atom->contentType() == DefinedAtom::typeCFI);
-
- // Bail out if we've encountered an error.
- if (ehFrameErr)
- return;
-
- const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
- if (ArchHandler::isDwarfCIE(isBig, atom))
- ehFrameErr = processCIE(normalizedFile, file, handler, ehFrameSection,
- atom, offset, cieInfos);
- else
- ehFrameErr = processFDE(normalizedFile, file, handler, ehFrameSection,
- atom, offset, cieInfos);
- });
-
- return ehFrameErr;
-}
-
-llvm::Error parseObjCImageInfo(const Section §,
- const NormalizedFile &normalizedFile,
- MachOFile &file) {
-
- // struct objc_image_info {
- // uint32_t version; // initially 0
- // uint32_t flags;
- // };
-
- ArrayRef<uint8_t> content = sect.content;
- if (content.size() != 8)
- return llvm::make_error<GenericError>(sect.segmentName + "/" +
- sect.sectionName +
- " in file " + file.path() +
- " should be 8 bytes in size");
-
- const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
- uint32_t version = read32(content.data(), isBig);
- if (version)
- return llvm::make_error<GenericError>(sect.segmentName + "/" +
- sect.sectionName +
- " in file " + file.path() +
- " should have version=0");
-
- uint32_t flags = read32(content.data() + 4, isBig);
- if (flags & (MachOLinkingContext::objc_supports_gc |
- MachOLinkingContext::objc_gc_only))
- return llvm::make_error<GenericError>(sect.segmentName + "/" +
- sect.sectionName +
- " in file " + file.path() +
- " uses GC. This is not supported");
-
- if (flags & MachOLinkingContext::objc_retainReleaseForSimulator)
- file.setObjcConstraint(MachOLinkingContext::objc_retainReleaseForSimulator);
- else
- file.setObjcConstraint(MachOLinkingContext::objc_retainRelease);
-
- file.setSwiftVersion((flags >> 8) & 0xFF);
-
- return llvm::Error::success();
-}
-
-/// Converts normalized mach-o file into an lld::File and lld::Atoms.
-llvm::Expected<std::unique_ptr<lld::File>>
-objectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
- bool copyRefs) {
- auto file = std::make_unique<MachOFile>(path);
- if (auto ec = normalizedObjectToAtoms(file.get(), normalizedFile, copyRefs))
- return std::move(ec);
- return std::unique_ptr<File>(std::move(file));
-}
-
-llvm::Expected<std::unique_ptr<lld::File>>
-dylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
- bool copyRefs) {
- // Instantiate SharedLibraryFile object.
- auto file = std::make_unique<MachODylibFile>(path);
- if (auto ec = normalizedDylibToAtoms(file.get(), normalizedFile, copyRefs))
- return std::move(ec);
- return std::unique_ptr<File>(std::move(file));
-}
-
-} // anonymous namespace
-
-namespace normalized {
-
-static bool isObjCImageInfo(const Section §) {
- return (sect.segmentName == "__OBJC" && sect.sectionName == "__image_info") ||
- (sect.segmentName == "__DATA" && sect.sectionName == "__objc_imageinfo");
-}
-
-llvm::Error
-normalizedObjectToAtoms(MachOFile *file,
- const NormalizedFile &normalizedFile,
- bool copyRefs) {
- LLVM_DEBUG(llvm::dbgs() << "******** Normalizing file to atoms: "
- << file->path() << "\n");
- bool scatterable = ((normalizedFile.flags & MH_SUBSECTIONS_VIA_SYMBOLS) != 0);
-
- // Create atoms from each section.
- for (auto § : normalizedFile.sections) {
-
- // If this is a debug-info section parse it specially.
- if (isDebugInfoSection(sect))
- continue;
-
- // If the file contains an objc_image_info struct, then we should parse the
- // ObjC flags and Swift version.
- if (isObjCImageInfo(sect)) {
- if (auto ec = parseObjCImageInfo(sect, normalizedFile, *file))
- return ec;
- // We then skip adding atoms for this section as we use the ObjCPass to
- // re-emit this data after it has been aggregated for all files.
- continue;
- }
-
- bool customSectionName;
- DefinedAtom::ContentType atomType = atomTypeFromSection(sect,
- customSectionName);
- if (auto ec = processSection(atomType, sect, customSectionName,
- normalizedFile, *file, scatterable, copyRefs))
- return ec;
- }
- // Create atoms from undefined symbols.
- for (auto &sym : normalizedFile.undefinedSymbols) {
- // Undefined symbols with n_value != 0 are actually tentative definitions.
- if (sym.value == Hex64(0)) {
- file->addUndefinedAtom(sym.name, copyRefs);
- } else {
- file->addTentativeDefAtom(sym.name, atomScope(sym.scope), sym.value,
- DefinedAtom::Alignment(1 << (sym.desc >> 8)),
- copyRefs);
- }
- }
-
- // Convert mach-o relocations to References
- std::unique_ptr<mach_o::ArchHandler> handler
- = ArchHandler::create(normalizedFile.arch);
- for (auto § : normalizedFile.sections) {
- if (isDebugInfoSection(sect))
- continue;
- if (llvm::Error ec = convertRelocs(sect, normalizedFile, scatterable,
- *file, *handler))
- return ec;
- }
-
- // Add additional arch-specific References
- file->eachDefinedAtom([&](MachODefinedAtom* atom) -> void {
- handler->addAdditionalReferences(*atom);
- });
-
- // Each __eh_frame section needs references to both __text (the function we're
- // providing unwind info for) and itself (FDE -> CIE). These aren't
- // represented in the relocations on some architectures, so we have to add
- // them back in manually there.
- if (auto ec = addEHFrameReferences(normalizedFile, *file, *handler))
- return ec;
-
- // Process mach-o data-in-code regions array. That information is encoded in
- // atoms as References at each transition point.
- unsigned nextIndex = 0;
- for (const DataInCode &entry : normalizedFile.dataInCode) {
- ++nextIndex;
- const Section* s = findSectionCoveringAddress(normalizedFile, entry.offset);
- if (!s) {
- return llvm::make_error<GenericError>(Twine("LC_DATA_IN_CODE address ("
- + Twine(entry.offset)
- + ") is not in any section"));
- }
- uint64_t offsetInSect = entry.offset - s->address;
- uint32_t offsetInAtom;
- MachODefinedAtom *atom = file->findAtomCoveringAddress(*s, offsetInSect,
- &offsetInAtom);
- if (offsetInAtom + entry.length > atom->size()) {
- return llvm::make_error<GenericError>(Twine("LC_DATA_IN_CODE entry "
- "(offset="
- + Twine(entry.offset)
- + ", length="
- + Twine(entry.length)
- + ") crosses atom boundary."));
- }
- // Add reference that marks start of data-in-code.
- atom->addReference(Reference::KindNamespace::mach_o, handler->kindArch(),
- handler->dataInCodeTransitionStart(*atom),
- offsetInAtom, atom, entry.kind);
-
- // Peek at next entry, if it starts where this one ends, skip ending ref.
- if (nextIndex < normalizedFile.dataInCode.size()) {
- const DataInCode &nextEntry = normalizedFile.dataInCode[nextIndex];
- if (nextEntry.offset == (entry.offset + entry.length))
- continue;
- }
-
- // If data goes to end of function, skip ending ref.
- if ((offsetInAtom + entry.length) == atom->size())
- continue;
-
- // Add reference that marks end of data-in-code.
- atom->addReference(Reference::KindNamespace::mach_o, handler->kindArch(),
- handler->dataInCodeTransitionEnd(*atom),
- offsetInAtom+entry.length, atom, 0);
- }
-
- // Cache some attributes on the file for use later.
- file->setFlags(normalizedFile.flags);
- file->setArch(normalizedFile.arch);
- file->setOS(normalizedFile.os);
- file->setMinVersion(normalizedFile.minOSverson);
- file->setMinVersionLoadCommandKind(normalizedFile.minOSVersionKind);
-
- // Sort references in each atom to their canonical order.
- for (const DefinedAtom* defAtom : file->defined()) {
- reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences();
- }
-
- if (auto err = parseDebugInfo(*file, normalizedFile, copyRefs))
- return err;
-
- return llvm::Error::success();
-}
-
-llvm::Error
-normalizedDylibToAtoms(MachODylibFile *file,
- const NormalizedFile &normalizedFile,
- bool copyRefs) {
- file->setInstallName(normalizedFile.installName);
- file->setCompatVersion(normalizedFile.compatVersion);
- file->setCurrentVersion(normalizedFile.currentVersion);
-
- // Tell MachODylibFile object about all symbols it exports.
- if (!normalizedFile.exportInfo.empty()) {
- // If exports trie exists, use it instead of traditional symbol table.
- for (const Export &exp : normalizedFile.exportInfo) {
- bool weakDef = (exp.flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
- // StringRefs from export iterator are ephemeral, so force copy.
- file->addExportedSymbol(exp.name, weakDef, true);
- }
- } else {
- for (auto &sym : normalizedFile.globalSymbols) {
- assert((sym.scope & N_EXT) && "only expect external symbols here");
- bool weakDef = (sym.desc & N_WEAK_DEF);
- file->addExportedSymbol(sym.name, weakDef, copyRefs);
- }
- }
- // Tell MachODylibFile object about all dylibs it re-exports.
- for (const DependentDylib &dep : normalizedFile.dependentDylibs) {
- if (dep.kind == llvm::MachO::LC_REEXPORT_DYLIB)
- file->addReExportedDylib(dep.path);
- }
- return llvm::Error::success();
-}
-
-void relocatableSectionInfoForContentType(DefinedAtom::ContentType atomType,
- StringRef &segmentName,
- StringRef §ionName,
- SectionType §ionType,
- SectionAttr §ionAttrs,
- bool &relocsToDefinedCanBeImplicit) {
-
- for (const MachORelocatableSectionToAtomType *p = sectsToAtomType ;
- p->atomType != DefinedAtom::typeUnknown; ++p) {
- if (p->atomType != atomType)
- continue;
- // Wild carded entries are ignored for reverse lookups.
- if (p->segmentName.empty() || p->sectionName.empty())
- continue;
- segmentName = p->segmentName;
- sectionName = p->sectionName;
- sectionType = p->sectionType;
- sectionAttrs = 0;
- relocsToDefinedCanBeImplicit = false;
- if (atomType == DefinedAtom::typeCode)
- sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
- if (atomType == DefinedAtom::typeCFI)
- relocsToDefinedCanBeImplicit = true;
- return;
- }
- llvm_unreachable("content type not yet supported");
-}
-
-llvm::Expected<std::unique_ptr<lld::File>>
-normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
- bool copyRefs) {
- switch (normalizedFile.fileType) {
- case MH_DYLIB:
- case MH_DYLIB_STUB:
- return dylibToAtoms(normalizedFile, path, copyRefs);
- case MH_OBJECT:
- return objectToAtoms(normalizedFile, path, copyRefs);
- default:
- llvm_unreachable("unhandled MachO file type!");
- }
-}
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp -----------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-///
-/// \file For mach-o object files, this implementation uses YAML I/O to
-/// provide the convert between YAML and the normalized mach-o (NM).
-///
-/// +------------+ +------+
-/// | normalized | <-> | yaml |
-/// +------------+ +------+
-
-#include "MachONormalizedFile.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/Error.h"
-#include "lld/ReaderWriter/YamlContext.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/Support/raw_ostream.h"
-#include <system_error>
-
-using llvm::StringRef;
-using namespace llvm::yaml;
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-using lld::YamlContext;
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(Segment)
-LLVM_YAML_IS_SEQUENCE_VECTOR(DependentDylib)
-LLVM_YAML_IS_SEQUENCE_VECTOR(RebaseLocation)
-LLVM_YAML_IS_SEQUENCE_VECTOR(BindLocation)
-LLVM_YAML_IS_SEQUENCE_VECTOR(Export)
-LLVM_YAML_IS_SEQUENCE_VECTOR(DataInCode)
-
-
-// for compatibility with gcc-4.7 in C++11 mode, add extra namespace
-namespace llvm {
-namespace yaml {
-
-// A vector of Sections is a sequence.
-template<>
-struct SequenceTraits< std::vector<Section> > {
- static size_t size(IO &io, std::vector<Section> &seq) {
- return seq.size();
- }
- static Section& element(IO &io, std::vector<Section> &seq, size_t index) {
- if ( index >= seq.size() )
- seq.resize(index+1);
- return seq[index];
- }
-};
-
-template<>
-struct SequenceTraits< std::vector<Symbol> > {
- static size_t size(IO &io, std::vector<Symbol> &seq) {
- return seq.size();
- }
- static Symbol& element(IO &io, std::vector<Symbol> &seq, size_t index) {
- if ( index >= seq.size() )
- seq.resize(index+1);
- return seq[index];
- }
-};
-
-// A vector of Relocations is a sequence.
-template<>
-struct SequenceTraits< Relocations > {
- static size_t size(IO &io, Relocations &seq) {
- return seq.size();
- }
- static Relocation& element(IO &io, Relocations &seq, size_t index) {
- if ( index >= seq.size() )
- seq.resize(index+1);
- return seq[index];
- }
-};
-
-// The content for a section is represented as a flow sequence of hex bytes.
-template<>
-struct SequenceTraits< ContentBytes > {
- static size_t size(IO &io, ContentBytes &seq) {
- return seq.size();
- }
- static Hex8& element(IO &io, ContentBytes &seq, size_t index) {
- if ( index >= seq.size() )
- seq.resize(index+1);
- return seq[index];
- }
- static const bool flow = true;
-};
-
-// The indirect symbols for a section is represented as a flow sequence
-// of numbers (symbol table indexes).
-template<>
-struct SequenceTraits< IndirectSymbols > {
- static size_t size(IO &io, IndirectSymbols &seq) {
- return seq.size();
- }
- static uint32_t& element(IO &io, IndirectSymbols &seq, size_t index) {
- if ( index >= seq.size() )
- seq.resize(index+1);
- return seq[index];
- }
- static const bool flow = true;
-};
-
-template <>
-struct ScalarEnumerationTraits<lld::MachOLinkingContext::Arch> {
- static void enumeration(IO &io, lld::MachOLinkingContext::Arch &value) {
- io.enumCase(value, "unknown",lld::MachOLinkingContext::arch_unknown);
- io.enumCase(value, "ppc", lld::MachOLinkingContext::arch_ppc);
- io.enumCase(value, "x86", lld::MachOLinkingContext::arch_x86);
- io.enumCase(value, "x86_64", lld::MachOLinkingContext::arch_x86_64);
- io.enumCase(value, "armv6", lld::MachOLinkingContext::arch_armv6);
- io.enumCase(value, "armv7", lld::MachOLinkingContext::arch_armv7);
- io.enumCase(value, "armv7s", lld::MachOLinkingContext::arch_armv7s);
- io.enumCase(value, "arm64", lld::MachOLinkingContext::arch_arm64);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<lld::MachOLinkingContext::OS> {
- static void enumeration(IO &io, lld::MachOLinkingContext::OS &value) {
- io.enumCase(value, "unknown",
- lld::MachOLinkingContext::OS::unknown);
- io.enumCase(value, "Mac OS X",
- lld::MachOLinkingContext::OS::macOSX);
- io.enumCase(value, "iOS",
- lld::MachOLinkingContext::OS::iOS);
- io.enumCase(value, "iOS Simulator",
- lld::MachOLinkingContext::OS::iOS_simulator);
- }
-};
-
-
-template <>
-struct ScalarEnumerationTraits<HeaderFileType> {
- static void enumeration(IO &io, HeaderFileType &value) {
- io.enumCase(value, "MH_OBJECT", llvm::MachO::MH_OBJECT);
- io.enumCase(value, "MH_DYLIB", llvm::MachO::MH_DYLIB);
- io.enumCase(value, "MH_EXECUTE", llvm::MachO::MH_EXECUTE);
- io.enumCase(value, "MH_BUNDLE", llvm::MachO::MH_BUNDLE);
- }
-};
-
-
-template <>
-struct ScalarBitSetTraits<FileFlags> {
- static void bitset(IO &io, FileFlags &value) {
- io.bitSetCase(value, "MH_TWOLEVEL",
- llvm::MachO::MH_TWOLEVEL);
- io.bitSetCase(value, "MH_SUBSECTIONS_VIA_SYMBOLS",
- llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- }
-};
-
-
-template <>
-struct ScalarEnumerationTraits<SectionType> {
- static void enumeration(IO &io, SectionType &value) {
- io.enumCase(value, "S_REGULAR",
- llvm::MachO::S_REGULAR);
- io.enumCase(value, "S_ZEROFILL",
- llvm::MachO::S_ZEROFILL);
- io.enumCase(value, "S_CSTRING_LITERALS",
- llvm::MachO::S_CSTRING_LITERALS);
- io.enumCase(value, "S_4BYTE_LITERALS",
- llvm::MachO::S_4BYTE_LITERALS);
- io.enumCase(value, "S_8BYTE_LITERALS",
- llvm::MachO::S_8BYTE_LITERALS);
- io.enumCase(value, "S_LITERAL_POINTERS",
- llvm::MachO::S_LITERAL_POINTERS);
- io.enumCase(value, "S_NON_LAZY_SYMBOL_POINTERS",
- llvm::MachO::S_NON_LAZY_SYMBOL_POINTERS);
- io.enumCase(value, "S_LAZY_SYMBOL_POINTERS",
- llvm::MachO::S_LAZY_SYMBOL_POINTERS);
- io.enumCase(value, "S_SYMBOL_STUBS",
- llvm::MachO::S_SYMBOL_STUBS);
- io.enumCase(value, "S_MOD_INIT_FUNC_POINTERS",
- llvm::MachO::S_MOD_INIT_FUNC_POINTERS);
- io.enumCase(value, "S_MOD_TERM_FUNC_POINTERS",
- llvm::MachO::S_MOD_TERM_FUNC_POINTERS);
- io.enumCase(value, "S_COALESCED",
- llvm::MachO::S_COALESCED);
- io.enumCase(value, "S_GB_ZEROFILL",
- llvm::MachO::S_GB_ZEROFILL);
- io.enumCase(value, "S_INTERPOSING",
- llvm::MachO::S_INTERPOSING);
- io.enumCase(value, "S_16BYTE_LITERALS",
- llvm::MachO::S_16BYTE_LITERALS);
- io.enumCase(value, "S_DTRACE_DOF",
- llvm::MachO::S_DTRACE_DOF);
- io.enumCase(value, "S_LAZY_DYLIB_SYMBOL_POINTERS",
- llvm::MachO::S_LAZY_DYLIB_SYMBOL_POINTERS);
- io.enumCase(value, "S_THREAD_LOCAL_REGULAR",
- llvm::MachO::S_THREAD_LOCAL_REGULAR);
- io.enumCase(value, "S_THREAD_LOCAL_ZEROFILL",
- llvm::MachO::S_THREAD_LOCAL_ZEROFILL);
- io.enumCase(value, "S_THREAD_LOCAL_VARIABLES",
- llvm::MachO::S_THREAD_LOCAL_VARIABLES);
- io.enumCase(value, "S_THREAD_LOCAL_VARIABLE_POINTERS",
- llvm::MachO::S_THREAD_LOCAL_VARIABLE_POINTERS);
- io.enumCase(value, "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS",
- llvm::MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS);
- }
-};
-
-template <>
-struct ScalarBitSetTraits<SectionAttr> {
- static void bitset(IO &io, SectionAttr &value) {
- io.bitSetCase(value, "S_ATTR_PURE_INSTRUCTIONS",
- llvm::MachO::S_ATTR_PURE_INSTRUCTIONS);
- io.bitSetCase(value, "S_ATTR_SOME_INSTRUCTIONS",
- llvm::MachO::S_ATTR_SOME_INSTRUCTIONS);
- io.bitSetCase(value, "S_ATTR_NO_DEAD_STRIP",
- llvm::MachO::S_ATTR_NO_DEAD_STRIP);
- io.bitSetCase(value, "S_ATTR_EXT_RELOC",
- llvm::MachO::S_ATTR_EXT_RELOC);
- io.bitSetCase(value, "S_ATTR_LOC_RELOC",
- llvm::MachO::S_ATTR_LOC_RELOC);
- io.bitSetCase(value, "S_ATTR_DEBUG",
- llvm::MachO::S_ATTR_DEBUG);
- }
-};
-
-/// This is a custom formatter for SectionAlignment. Values are
-/// the power to raise by, ie, the n in 2^n.
-template <> struct ScalarTraits<SectionAlignment> {
- static void output(const SectionAlignment &value, void *ctxt,
- raw_ostream &out) {
- out << llvm::format("%d", (uint32_t)value);
- }
-
- static StringRef input(StringRef scalar, void *ctxt,
- SectionAlignment &value) {
- uint32_t alignment;
- if (scalar.getAsInteger(0, alignment)) {
- return "malformed alignment value";
- }
- if (!llvm::isPowerOf2_32(alignment))
- return "alignment must be a power of 2";
- value = alignment;
- return StringRef(); // returning empty string means success
- }
-
- static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <>
-struct ScalarEnumerationTraits<NListType> {
- static void enumeration(IO &io, NListType &value) {
- io.enumCase(value, "N_UNDF", llvm::MachO::N_UNDF);
- io.enumCase(value, "N_ABS", llvm::MachO::N_ABS);
- io.enumCase(value, "N_SECT", llvm::MachO::N_SECT);
- io.enumCase(value, "N_PBUD", llvm::MachO::N_PBUD);
- io.enumCase(value, "N_INDR", llvm::MachO::N_INDR);
- }
-};
-
-template <>
-struct ScalarBitSetTraits<SymbolScope> {
- static void bitset(IO &io, SymbolScope &value) {
- io.bitSetCase(value, "N_EXT", llvm::MachO::N_EXT);
- io.bitSetCase(value, "N_PEXT", llvm::MachO::N_PEXT);
- }
-};
-
-template <>
-struct ScalarBitSetTraits<SymbolDesc> {
- static void bitset(IO &io, SymbolDesc &value) {
- io.bitSetCase(value, "N_NO_DEAD_STRIP", llvm::MachO::N_NO_DEAD_STRIP);
- io.bitSetCase(value, "N_WEAK_REF", llvm::MachO::N_WEAK_REF);
- io.bitSetCase(value, "N_WEAK_DEF", llvm::MachO::N_WEAK_DEF);
- io.bitSetCase(value, "N_ARM_THUMB_DEF", llvm::MachO::N_ARM_THUMB_DEF);
- io.bitSetCase(value, "N_SYMBOL_RESOLVER", llvm::MachO::N_SYMBOL_RESOLVER);
- }
-};
-
-
-template <>
-struct MappingTraits<Section> {
- struct NormalizedContentBytes;
- static void mapping(IO &io, Section §) {
- io.mapRequired("segment", sect.segmentName);
- io.mapRequired("section", sect.sectionName);
- io.mapRequired("type", sect.type);
- io.mapOptional("attributes", sect.attributes);
- io.mapOptional("alignment", sect.alignment, (SectionAlignment)1);
- io.mapRequired("address", sect.address);
- if (isZeroFillSection(sect.type)) {
- // S_ZEROFILL sections use "size:" instead of "content:"
- uint64_t size = sect.content.size();
- io.mapOptional("size", size);
- if (!io.outputting()) {
- uint8_t *bytes = nullptr;
- sect.content = makeArrayRef(bytes, size);
- }
- } else {
- MappingNormalization<NormalizedContent, ArrayRef<uint8_t>> content(
- io, sect.content);
- io.mapOptional("content", content->_normalizedContent);
- }
- io.mapOptional("relocations", sect.relocations);
- io.mapOptional("indirect-syms", sect.indirectSymbols);
- }
-
- struct NormalizedContent {
- NormalizedContent(IO &io) : _io(io) {}
- NormalizedContent(IO &io, ArrayRef<uint8_t> content) : _io(io) {
- // When writing yaml, copy content byte array to Hex8 vector.
- for (auto &c : content) {
- _normalizedContent.push_back(c);
- }
- }
- ArrayRef<uint8_t> denormalize(IO &io) {
- // When reading yaml, allocate byte array owned by NormalizedFile and
- // copy Hex8 vector to byte array.
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- NormalizedFile *file = info->_normalizeMachOFile;
- assert(file != nullptr);
- size_t size = _normalizedContent.size();
- if (!size)
- return None;
- uint8_t *bytes = file->ownedAllocations.Allocate<uint8_t>(size);
- std::copy(_normalizedContent.begin(), _normalizedContent.end(), bytes);
- return makeArrayRef(bytes, size);
- }
-
- IO &_io;
- ContentBytes _normalizedContent;
- };
-};
-
-
-template <>
-struct MappingTraits<Relocation> {
- static void mapping(IO &io, Relocation &reloc) {
- io.mapRequired("offset", reloc.offset);
- io.mapOptional("scattered", reloc.scattered, false);
- io.mapRequired("type", reloc.type);
- io.mapRequired("length", reloc.length);
- io.mapRequired("pc-rel", reloc.pcRel);
- if ( !reloc.scattered )
- io.mapRequired("extern", reloc.isExtern);
- if ( reloc.scattered )
- io.mapRequired("value", reloc.value);
- if ( !reloc.scattered )
- io.mapRequired("symbol", reloc.symbol);
- }
-};
-
-
-template <>
-struct ScalarEnumerationTraits<RelocationInfoType> {
- static void enumeration(IO &io, RelocationInfoType &value) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- NormalizedFile *file = info->_normalizeMachOFile;
- assert(file != nullptr);
- switch (file->arch) {
- case lld::MachOLinkingContext::arch_x86_64:
- io.enumCase(value, "X86_64_RELOC_UNSIGNED",
- llvm::MachO::X86_64_RELOC_UNSIGNED);
- io.enumCase(value, "X86_64_RELOC_SIGNED",
- llvm::MachO::X86_64_RELOC_SIGNED);
- io.enumCase(value, "X86_64_RELOC_BRANCH",
- llvm::MachO::X86_64_RELOC_BRANCH);
- io.enumCase(value, "X86_64_RELOC_GOT_LOAD",
- llvm::MachO::X86_64_RELOC_GOT_LOAD);
- io.enumCase(value, "X86_64_RELOC_GOT",
- llvm::MachO::X86_64_RELOC_GOT);
- io.enumCase(value, "X86_64_RELOC_SUBTRACTOR",
- llvm::MachO::X86_64_RELOC_SUBTRACTOR);
- io.enumCase(value, "X86_64_RELOC_SIGNED_1",
- llvm::MachO::X86_64_RELOC_SIGNED_1);
- io.enumCase(value, "X86_64_RELOC_SIGNED_2",
- llvm::MachO::X86_64_RELOC_SIGNED_2);
- io.enumCase(value, "X86_64_RELOC_SIGNED_4",
- llvm::MachO::X86_64_RELOC_SIGNED_4);
- io.enumCase(value, "X86_64_RELOC_TLV",
- llvm::MachO::X86_64_RELOC_TLV);
- break;
- case lld::MachOLinkingContext::arch_x86:
- io.enumCase(value, "GENERIC_RELOC_VANILLA",
- llvm::MachO::GENERIC_RELOC_VANILLA);
- io.enumCase(value, "GENERIC_RELOC_PAIR",
- llvm::MachO::GENERIC_RELOC_PAIR);
- io.enumCase(value, "GENERIC_RELOC_SECTDIFF",
- llvm::MachO::GENERIC_RELOC_SECTDIFF);
- io.enumCase(value, "GENERIC_RELOC_LOCAL_SECTDIFF",
- llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF);
- io.enumCase(value, "GENERIC_RELOC_TLV",
- llvm::MachO::GENERIC_RELOC_TLV);
- break;
- case lld::MachOLinkingContext::arch_armv6:
- case lld::MachOLinkingContext::arch_armv7:
- case lld::MachOLinkingContext::arch_armv7s:
- io.enumCase(value, "ARM_RELOC_VANILLA",
- llvm::MachO::ARM_RELOC_VANILLA);
- io.enumCase(value, "ARM_RELOC_PAIR",
- llvm::MachO::ARM_RELOC_PAIR);
- io.enumCase(value, "ARM_RELOC_SECTDIFF",
- llvm::MachO::ARM_RELOC_SECTDIFF);
- io.enumCase(value, "ARM_RELOC_LOCAL_SECTDIFF",
- llvm::MachO::ARM_RELOC_LOCAL_SECTDIFF);
- io.enumCase(value, "ARM_RELOC_BR24",
- llvm::MachO::ARM_RELOC_BR24);
- io.enumCase(value, "ARM_THUMB_RELOC_BR22",
- llvm::MachO::ARM_THUMB_RELOC_BR22);
- io.enumCase(value, "ARM_RELOC_HALF",
- llvm::MachO::ARM_RELOC_HALF);
- io.enumCase(value, "ARM_RELOC_HALF_SECTDIFF",
- llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
- break;
- case lld::MachOLinkingContext::arch_arm64:
- io.enumCase(value, "ARM64_RELOC_UNSIGNED",
- llvm::MachO::ARM64_RELOC_UNSIGNED);
- io.enumCase(value, "ARM64_RELOC_SUBTRACTOR",
- llvm::MachO::ARM64_RELOC_SUBTRACTOR);
- io.enumCase(value, "ARM64_RELOC_BRANCH26",
- llvm::MachO::ARM64_RELOC_BRANCH26);
- io.enumCase(value, "ARM64_RELOC_PAGE21",
- llvm::MachO::ARM64_RELOC_PAGE21);
- io.enumCase(value, "ARM64_RELOC_PAGEOFF12",
- llvm::MachO::ARM64_RELOC_PAGEOFF12);
- io.enumCase(value, "ARM64_RELOC_GOT_LOAD_PAGE21",
- llvm::MachO::ARM64_RELOC_GOT_LOAD_PAGE21);
- io.enumCase(value, "ARM64_RELOC_GOT_LOAD_PAGEOFF12",
- llvm::MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12);
- io.enumCase(value, "ARM64_RELOC_POINTER_TO_GOT",
- llvm::MachO::ARM64_RELOC_POINTER_TO_GOT);
- io.enumCase(value, "ARM64_RELOC_TLVP_LOAD_PAGE21",
- llvm::MachO::ARM64_RELOC_TLVP_LOAD_PAGE21);
- io.enumCase(value, "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
- llvm::MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12);
- io.enumCase(value, "ARM64_RELOC_ADDEND",
- llvm::MachO::ARM64_RELOC_ADDEND);
- break;
- default:
- llvm_unreachable("unknown architecture");
- }
- }
-};
-
-
-template <>
-struct MappingTraits<Symbol> {
- static void mapping(IO &io, Symbol& sym) {
- io.mapRequired("name", sym.name);
- io.mapRequired("type", sym.type);
- io.mapOptional("scope", sym.scope, SymbolScope(0));
- io.mapOptional("sect", sym.sect, (uint8_t)0);
- if (sym.type == llvm::MachO::N_UNDF) {
- // In undef symbols, desc field contains alignment/ordinal info
- // which is better represented as a hex vaule.
- uint16_t t1 = sym.desc;
- Hex16 t2 = t1;
- io.mapOptional("desc", t2, Hex16(0));
- sym.desc = t2;
- } else {
- // In defined symbols, desc fit is a set of option bits.
- io.mapOptional("desc", sym.desc, SymbolDesc(0));
- }
- io.mapRequired("value", sym.value);
- }
-};
-
-// Custom mapping for VMProtect (e.g. "r-x").
-template <>
-struct ScalarTraits<VMProtect> {
- static void output(const VMProtect &value, void*, raw_ostream &out) {
- out << ( (value & llvm::MachO::VM_PROT_READ) ? 'r' : '-');
- out << ( (value & llvm::MachO::VM_PROT_WRITE) ? 'w' : '-');
- out << ( (value & llvm::MachO::VM_PROT_EXECUTE) ? 'x' : '-');
- }
- static StringRef input(StringRef scalar, void*, VMProtect &value) {
- value = 0;
- if (scalar.size() != 3)
- return "segment access protection must be three chars (e.g. \"r-x\")";
- switch (scalar[0]) {
- case 'r':
- value = llvm::MachO::VM_PROT_READ;
- break;
- case '-':
- break;
- default:
- return "segment access protection first char must be 'r' or '-'";
- }
- switch (scalar[1]) {
- case 'w':
- value = value | llvm::MachO::VM_PROT_WRITE;
- break;
- case '-':
- break;
- default:
- return "segment access protection second char must be 'w' or '-'";
- }
- switch (scalar[2]) {
- case 'x':
- value = value | llvm::MachO::VM_PROT_EXECUTE;
- break;
- case '-':
- break;
- default:
- return "segment access protection third char must be 'x' or '-'";
- }
- // Return the empty string on success,
- return StringRef();
- }
- static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-
-template <>
-struct MappingTraits<Segment> {
- static void mapping(IO &io, Segment& seg) {
- io.mapRequired("name", seg.name);
- io.mapRequired("address", seg.address);
- io.mapRequired("size", seg.size);
- io.mapRequired("init-access", seg.init_access);
- io.mapRequired("max-access", seg.max_access);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<LoadCommandType> {
- static void enumeration(IO &io, LoadCommandType &value) {
- io.enumCase(value, "LC_LOAD_DYLIB",
- llvm::MachO::LC_LOAD_DYLIB);
- io.enumCase(value, "LC_LOAD_WEAK_DYLIB",
- llvm::MachO::LC_LOAD_WEAK_DYLIB);
- io.enumCase(value, "LC_REEXPORT_DYLIB",
- llvm::MachO::LC_REEXPORT_DYLIB);
- io.enumCase(value, "LC_LOAD_UPWARD_DYLIB",
- llvm::MachO::LC_LOAD_UPWARD_DYLIB);
- io.enumCase(value, "LC_LAZY_LOAD_DYLIB",
- llvm::MachO::LC_LAZY_LOAD_DYLIB);
- io.enumCase(value, "LC_VERSION_MIN_MACOSX",
- llvm::MachO::LC_VERSION_MIN_MACOSX);
- io.enumCase(value, "LC_VERSION_MIN_IPHONEOS",
- llvm::MachO::LC_VERSION_MIN_IPHONEOS);
- io.enumCase(value, "LC_VERSION_MIN_TVOS",
- llvm::MachO::LC_VERSION_MIN_TVOS);
- io.enumCase(value, "LC_VERSION_MIN_WATCHOS",
- llvm::MachO::LC_VERSION_MIN_WATCHOS);
- }
-};
-
-template <>
-struct MappingTraits<DependentDylib> {
- static void mapping(IO &io, DependentDylib& dylib) {
- io.mapRequired("path", dylib.path);
- io.mapOptional("kind", dylib.kind,
- llvm::MachO::LC_LOAD_DYLIB);
- io.mapOptional("compat-version", dylib.compatVersion,
- PackedVersion(0x10000));
- io.mapOptional("current-version", dylib.currentVersion,
- PackedVersion(0x10000));
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<RebaseType> {
- static void enumeration(IO &io, RebaseType &value) {
- io.enumCase(value, "REBASE_TYPE_POINTER",
- llvm::MachO::REBASE_TYPE_POINTER);
- io.enumCase(value, "REBASE_TYPE_TEXT_PCREL32",
- llvm::MachO::REBASE_TYPE_TEXT_PCREL32);
- io.enumCase(value, "REBASE_TYPE_TEXT_ABSOLUTE32",
- llvm::MachO::REBASE_TYPE_TEXT_ABSOLUTE32);
- }
-};
-
-
-template <>
-struct MappingTraits<RebaseLocation> {
- static void mapping(IO &io, RebaseLocation& rebase) {
- io.mapRequired("segment-index", rebase.segIndex);
- io.mapRequired("segment-offset", rebase.segOffset);
- io.mapOptional("kind", rebase.kind,
- llvm::MachO::REBASE_TYPE_POINTER);
- }
-};
-
-
-
-template <>
-struct ScalarEnumerationTraits<BindType> {
- static void enumeration(IO &io, BindType &value) {
- io.enumCase(value, "BIND_TYPE_POINTER",
- llvm::MachO::BIND_TYPE_POINTER);
- io.enumCase(value, "BIND_TYPE_TEXT_ABSOLUTE32",
- llvm::MachO::BIND_TYPE_TEXT_ABSOLUTE32);
- io.enumCase(value, "BIND_TYPE_TEXT_PCREL32",
- llvm::MachO::BIND_TYPE_TEXT_PCREL32);
- }
-};
-
-template <>
-struct MappingTraits<BindLocation> {
- static void mapping(IO &io, BindLocation &bind) {
- io.mapRequired("segment-index", bind.segIndex);
- io.mapRequired("segment-offset", bind.segOffset);
- io.mapOptional("kind", bind.kind,
- llvm::MachO::BIND_TYPE_POINTER);
- io.mapOptional("can-be-null", bind.canBeNull, false);
- io.mapRequired("ordinal", bind.ordinal);
- io.mapRequired("symbol-name", bind.symbolName);
- io.mapOptional("addend", bind.addend, Hex64(0));
- }
-};
-
-
-template <>
-struct ScalarEnumerationTraits<ExportSymbolKind> {
- static void enumeration(IO &io, ExportSymbolKind &value) {
- io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_REGULAR",
- llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR);
- io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL",
- llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
- io.enumCase(value, "EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE",
- llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
- }
-};
-
-template <>
-struct ScalarBitSetTraits<ExportFlags> {
- static void bitset(IO &io, ExportFlags &value) {
- io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION",
- llvm::MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
- io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_REEXPORT",
- llvm::MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
- io.bitSetCase(value, "EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER",
- llvm::MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
- }
-};
-
-
-template <>
-struct MappingTraits<Export> {
- static void mapping(IO &io, Export &exp) {
- io.mapRequired("name", exp.name);
- io.mapOptional("offset", exp.offset);
- io.mapOptional("kind", exp.kind,
- llvm::MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR);
- if (!io.outputting() || exp.flags)
- io.mapOptional("flags", exp.flags);
- io.mapOptional("other", exp.otherOffset, Hex32(0));
- io.mapOptional("other-name", exp.otherName, StringRef());
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<DataRegionType> {
- static void enumeration(IO &io, DataRegionType &value) {
- io.enumCase(value, "DICE_KIND_DATA",
- llvm::MachO::DICE_KIND_DATA);
- io.enumCase(value, "DICE_KIND_JUMP_TABLE8",
- llvm::MachO::DICE_KIND_JUMP_TABLE8);
- io.enumCase(value, "DICE_KIND_JUMP_TABLE16",
- llvm::MachO::DICE_KIND_JUMP_TABLE16);
- io.enumCase(value, "DICE_KIND_JUMP_TABLE32",
- llvm::MachO::DICE_KIND_JUMP_TABLE32);
- io.enumCase(value, "DICE_KIND_ABS_JUMP_TABLE32",
- llvm::MachO::DICE_KIND_ABS_JUMP_TABLE32);
- }
-};
-
-template <>
-struct MappingTraits<DataInCode> {
- static void mapping(IO &io, DataInCode &entry) {
- io.mapRequired("offset", entry.offset);
- io.mapRequired("length", entry.length);
- io.mapRequired("kind", entry.kind);
- }
-};
-
-template <>
-struct ScalarTraits<PackedVersion> {
- static void output(const PackedVersion &value, void*, raw_ostream &out) {
- out << llvm::format("%d.%d", (value >> 16), (value >> 8) & 0xFF);
- if (value & 0xFF) {
- out << llvm::format(".%d", (value & 0xFF));
- }
- }
- static StringRef input(StringRef scalar, void*, PackedVersion &result) {
- uint32_t value;
- if (lld::MachOLinkingContext::parsePackedVersion(scalar, value))
- return "malformed version number";
- result = value;
- // Return the empty string on success,
- return StringRef();
- }
- static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <>
-struct MappingTraits<NormalizedFile> {
- static void mapping(IO &io, NormalizedFile &file) {
- io.mapRequired("arch", file.arch);
- io.mapRequired("file-type", file.fileType);
- io.mapOptional("flags", file.flags);
- io.mapOptional("dependents", file.dependentDylibs);
- io.mapOptional("install-name", file.installName, StringRef());
- io.mapOptional("compat-version", file.compatVersion, PackedVersion(0x10000));
- io.mapOptional("current-version", file.currentVersion, PackedVersion(0x10000));
- io.mapOptional("has-UUID", file.hasUUID, true);
- io.mapOptional("rpaths", file.rpaths);
- io.mapOptional("entry-point", file.entryAddress, Hex64(0));
- io.mapOptional("stack-size", file.stackSize, Hex64(0));
- io.mapOptional("source-version", file.sourceVersion, Hex64(0));
- io.mapOptional("OS", file.os);
- io.mapOptional("min-os-version", file.minOSverson, PackedVersion(0));
- io.mapOptional("min-os-version-kind", file.minOSVersionKind, (LoadCommandType)0);
- io.mapOptional("sdk-version", file.sdkVersion, PackedVersion(0));
- io.mapOptional("segments", file.segments);
- io.mapOptional("sections", file.sections);
- io.mapOptional("local-symbols", file.localSymbols);
- io.mapOptional("global-symbols", file.globalSymbols);
- io.mapOptional("undefined-symbols",file.undefinedSymbols);
- io.mapOptional("page-size", file.pageSize, Hex32(4096));
- io.mapOptional("rebasings", file.rebasingInfo);
- io.mapOptional("bindings", file.bindingInfo);
- io.mapOptional("weak-bindings", file.weakBindingInfo);
- io.mapOptional("lazy-bindings", file.lazyBindingInfo);
- io.mapOptional("exports", file.exportInfo);
- io.mapOptional("dataInCode", file.dataInCode);
- }
- static std::string validate(IO &io, NormalizedFile &file) { return {}; }
-};
-
-} // namespace llvm
-} // namespace yaml
-
-
-namespace lld {
-namespace mach_o {
-
-/// Handles !mach-o tagged yaml documents.
-bool MachOYamlIOTaggedDocumentHandler::handledDocTag(llvm::yaml::IO &io,
- const lld::File *&file) const {
- if (!io.mapTag("!mach-o"))
- return false;
- // Step 1: parse yaml into normalized mach-o struct.
- NormalizedFile nf;
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- assert(info->_normalizeMachOFile == nullptr);
- info->_normalizeMachOFile = &nf;
- MappingTraits<NormalizedFile>::mapping(io, nf);
- // Step 2: parse normalized mach-o struct into atoms.
- auto fileOrError = normalizedToAtoms(nf, info->_path, true);
-
- // Check that we parsed successfully.
- if (!fileOrError) {
- std::string buffer;
- llvm::raw_string_ostream stream(buffer);
- handleAllErrors(fileOrError.takeError(),
- [&](const llvm::ErrorInfoBase &EI) {
- EI.log(stream);
- stream << "\n";
- });
- io.setError(stream.str());
- return false;
- }
-
- if (nf.arch != _arch) {
- io.setError(Twine("file is wrong architecture. Expected ("
- + MachOLinkingContext::nameFromArch(_arch)
- + ") found ("
- + MachOLinkingContext::nameFromArch(nf.arch)
- + ")"));
- return false;
- }
- info->_normalizeMachOFile = nullptr;
- file = fileOrError->release();
- return true;
-}
-
-
-
-namespace normalized {
-
-/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
-llvm::Expected<std::unique_ptr<NormalizedFile>>
-readYaml(std::unique_ptr<MemoryBuffer> &mb) {
- // Make empty NormalizedFile.
- std::unique_ptr<NormalizedFile> f(new NormalizedFile());
-
- // Create YAML Input parser.
- YamlContext yamlContext;
- yamlContext._normalizeMachOFile = f.get();
- llvm::yaml::Input yin(mb->getBuffer(), &yamlContext);
-
- // Fill NormalizedFile by parsing yaml.
- yin >> *f;
-
- // Return error if there were parsing problems.
- if (auto ec = yin.error())
- return llvm::make_error<GenericError>(Twine("YAML parsing error: ")
- + ec.message());
-
- // Hand ownership of instantiated NormalizedFile to caller.
- return std::move(f);
-}
-
-
-/// Writes a yaml encoded mach-o files from an in-memory normalized view.
-std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out) {
- // YAML I/O is not const aware, so need to cast away ;-(
- NormalizedFile *f = const_cast<NormalizedFile*>(&file);
-
- // Create yaml Output writer, using yaml options for context.
- YamlContext yamlContext;
- yamlContext._normalizeMachOFile = f;
- llvm::yaml::Output yout(out, &yamlContext);
-
- // Stream out yaml.
- yout << *f;
-
- return std::error_code();
-}
-
-} // namespace normalized
-} // namespace mach_o
-} // namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/MachOPasses.h -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_PASSES_H
-#define LLD_READER_WRITER_MACHO_PASSES_H
-
-#include "lld/Core/PassManager.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-
-namespace lld {
-namespace mach_o {
-
-void addLayoutPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx);
-void addShimPass(PassManager &pm, const MachOLinkingContext &ctx);
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_PASSES_H
+++ /dev/null
-//===- lib/ReaderWriter/MachO/ObjCPass.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachONormalizedFileBinaryUtils.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-
-namespace lld {
-namespace mach_o {
-
-///
-/// ObjC Image Info Atom created by the ObjC pass.
-///
-class ObjCImageInfoAtom : public SimpleDefinedAtom {
-public:
- ObjCImageInfoAtom(const File &file, bool isBig,
- MachOLinkingContext::ObjCConstraint objCConstraint,
- uint32_t swiftVersion)
- : SimpleDefinedAtom(file) {
-
- Data.info.version = 0;
-
- switch (objCConstraint) {
- case MachOLinkingContext::objc_unknown:
- llvm_unreachable("Shouldn't run the objc pass without a constraint");
- case MachOLinkingContext::objc_supports_gc:
- case MachOLinkingContext::objc_gc_only:
- llvm_unreachable("GC is not supported");
- case MachOLinkingContext::objc_retainReleaseForSimulator:
- // The retain/release for simulator flag is already the correct
- // encoded value for the data so just set it here.
- Data.info.flags = (uint32_t)objCConstraint;
- break;
- case MachOLinkingContext::objc_retainRelease:
- // We don't need to encode this flag, so just leave the flags as 0.
- Data.info.flags = 0;
- break;
- }
-
- Data.info.flags |= (swiftVersion << 8);
-
- normalized::write32(Data.bytes + 4, Data.info.flags, isBig);
- }
-
- ~ObjCImageInfoAtom() override = default;
-
- ContentType contentType() const override {
- return DefinedAtom::typeObjCImageInfo;
- }
-
- Alignment alignment() const override {
- return 4;
- }
-
- uint64_t size() const override {
- return 8;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permR__;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(Data.bytes, size());
- }
-
-private:
-
- struct objc_image_info {
- uint32_t version;
- uint32_t flags;
- };
-
- union {
- objc_image_info info;
- uint8_t bytes[8];
- } Data;
-};
-
-class ObjCPass : public Pass {
-public:
- ObjCPass(const MachOLinkingContext &context)
- : _ctx(context),
- _file(*_ctx.make_file<MachOFile>("<mach-o objc pass>")) {
- _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
- }
-
- llvm::Error perform(SimpleFile &mergedFile) override {
- // Add the image info.
- mergedFile.addAtom(*getImageInfo());
-
- return llvm::Error::success();
- }
-
-private:
-
- const DefinedAtom* getImageInfo() {
- bool IsBig = MachOLinkingContext::isBigEndian(_ctx.arch());
- return new (_file.allocator()) ObjCImageInfoAtom(_file, IsBig,
- _ctx.objcConstraint(),
- _ctx.swiftVersion());
- }
-
- const MachOLinkingContext &_ctx;
- MachOFile &_file;
-};
-
-
-
-void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx) {
- pm.add(std::make_unique<ObjCPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
+++ /dev/null
-//===---- lib/ReaderWriter/MachO/SectCreateFile.h ---------------*- c++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
-#define LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-// A FlateNamespaceFile instance may be added as a resolution source of last
-// resort, depending on how -flat_namespace and -undefined are set.
-//
-class SectCreateFile : public File {
-public:
- class SectCreateAtom : public SimpleDefinedAtom {
- public:
- SectCreateAtom(const File &file, StringRef segName, StringRef sectName,
- std::unique_ptr<MemoryBuffer> content)
- : SimpleDefinedAtom(file),
- _combinedName((segName + "/" + sectName).str()),
- _content(std::move(content)) {}
-
- ~SectCreateAtom() override = default;
-
- uint64_t size() const override { return _content->getBufferSize(); }
-
- Scope scope() const override { return scopeGlobal; }
-
- ContentType contentType() const override { return typeSectCreate; }
-
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
-
- StringRef customSectionName() const override { return _combinedName; }
-
- DeadStripKind deadStrip() const override { return deadStripNever; }
-
- ArrayRef<uint8_t> rawContent() const override {
- const uint8_t *data =
- reinterpret_cast<const uint8_t*>(_content->getBufferStart());
- return ArrayRef<uint8_t>(data, _content->getBufferSize());
- }
-
- StringRef segmentName() const { return _segName; }
- StringRef sectionName() const { return _sectName; }
-
- private:
- std::string _combinedName;
- StringRef _segName;
- StringRef _sectName;
- std::unique_ptr<MemoryBuffer> _content;
- };
-
- SectCreateFile() : File("sectcreate", kindSectCreateObject) {}
-
- void addSection(StringRef seg, StringRef sect,
- std::unique_ptr<MemoryBuffer> content) {
- _definedAtoms.push_back(
- new (allocator()) SectCreateAtom(*this, seg, sect, std::move(content)));
- }
-
- const AtomRange<DefinedAtom> defined() const override {
- return _definedAtoms;
- }
-
- const AtomRange<UndefinedAtom> undefined() const override {
- return _noUndefinedAtoms;
- }
-
- const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
- return _noSharedLibraryAtoms;
- }
-
- const AtomRange<AbsoluteAtom> absolute() const override {
- return _noAbsoluteAtoms;
- }
-
- void clearAtoms() override {
- _definedAtoms.clear();
- _noUndefinedAtoms.clear();
- _noSharedLibraryAtoms.clear();
- _noAbsoluteAtoms.clear();
- }
-
-private:
- AtomVector<DefinedAtom> _definedAtoms;
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
+++ /dev/null
-//===- lib/ReaderWriter/MachO/ShimPass.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This linker pass updates branch-sites whose target is a different mode
-// (thumb vs arm).
-//
-// Arm code has two instruction encodings thumb and arm. When branching from
-// one code encoding to another, you need to use an instruction that switches
-// the instruction mode. Usually the transition only happens at call sites, and
-// the linker can transform a BL instruction in BLX (or vice versa). But if the
-// compiler did a tail call optimization and a function ends with a branch (not
-// branch and link), there is no pc-rel BX instruction.
-//
-// The ShimPass looks for pc-rel B instructions that will need to switch mode.
-// For those cases it synthesizes a shim which does the transition, then
-// modifies the original atom with the B instruction to target to the shim atom.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-
-namespace lld {
-namespace mach_o {
-
-class ShimPass : public Pass {
-public:
- ShimPass(const MachOLinkingContext &context)
- : _ctx(context), _archHandler(_ctx.archHandler()),
- _stubInfo(_archHandler.stubInfo()),
- _file(*_ctx.make_file<MachOFile>("<mach-o shim pass>")) {
- _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
- }
-
- llvm::Error perform(SimpleFile &mergedFile) override {
- // Scan all references in all atoms.
- for (const DefinedAtom *atom : mergedFile.defined()) {
- for (const Reference *ref : *atom) {
- // Look at non-call branches.
- if (!_archHandler.isNonCallBranch(*ref))
- continue;
- const Atom *target = ref->target();
- assert(target != nullptr);
- if (const lld::DefinedAtom *daTarget = dyn_cast<DefinedAtom>(target)) {
- bool atomIsThumb = _archHandler.isThumbFunction(*atom);
- bool targetIsThumb = _archHandler.isThumbFunction(*daTarget);
- if (atomIsThumb != targetIsThumb)
- updateBranchToUseShim(atomIsThumb, *daTarget, ref);
- }
- }
- }
- // Exit early if no shims needed.
- if (_targetToShim.empty())
- return llvm::Error::success();
-
- // Sort shim atoms so the layout order is stable.
- std::vector<const DefinedAtom *> shims;
- shims.reserve(_targetToShim.size());
- for (auto element : _targetToShim) {
- shims.push_back(element.second);
- }
- std::sort(shims.begin(), shims.end(),
- [](const DefinedAtom *l, const DefinedAtom *r) {
- return (l->name() < r->name());
- });
-
- // Add all shims to merged file.
- for (const DefinedAtom *shim : shims)
- mergedFile.addAtom(*shim);
-
- return llvm::Error::success();
- }
-
-private:
-
- void updateBranchToUseShim(bool thumbToArm, const DefinedAtom& target,
- const Reference *ref) {
- // Make file-format specific stub and other support atoms.
- const DefinedAtom *shim = this->getShim(thumbToArm, target);
- assert(shim != nullptr);
- // Switch branch site to target shim atom.
- const_cast<Reference *>(ref)->setTarget(shim);
- }
-
- const DefinedAtom* getShim(bool thumbToArm, const DefinedAtom& target) {
- auto pos = _targetToShim.find(&target);
- if ( pos != _targetToShim.end() ) {
- // Reuse an existing shim.
- assert(pos->second != nullptr);
- return pos->second;
- } else {
- // There is no existing shim, so create a new one.
- const DefinedAtom *shim = _archHandler.createShim(_file, thumbToArm,
- target);
- _targetToShim[&target] = shim;
- return shim;
- }
- }
-
- const MachOLinkingContext &_ctx;
- mach_o::ArchHandler &_archHandler;
- const ArchHandler::StubInfo &_stubInfo;
- MachOFile &_file;
- llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToShim;
-};
-
-
-
-void addShimPass(PassManager &pm, const MachOLinkingContext &ctx) {
- pm.add(std::make_unique<ShimPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/StubsPass.cpp ---------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// 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. Each file format defines a subclass of StubsPass which implements
-// the abstract methods for creating the file format specific StubAtoms.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachOPasses.h"
-#include "lld/Common/LLVM.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-// Lazy Pointer Atom created by the stubs pass.
-//
-class LazyPointerAtom : public SimpleDefinedAtom {
-public:
- LazyPointerAtom(const File &file, bool is64)
- : SimpleDefinedAtom(file), _is64(is64) { }
-
- ~LazyPointerAtom() override = default;
-
- ContentType contentType() const override {
- return DefinedAtom::typeLazyPointer;
- }
-
- Alignment alignment() const override {
- return _is64 ? 8 : 4;
- }
-
- uint64_t size() const override {
- return _is64 ? 8 : 4;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permRW_;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- static const uint8_t zeros[] =
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- return llvm::makeArrayRef(zeros, size());
- }
-
-private:
- const bool _is64;
-};
-
-//
-// NonLazyPointer (GOT) Atom created by the stubs pass.
-//
-class NonLazyPointerAtom : public SimpleDefinedAtom {
-public:
- NonLazyPointerAtom(const File &file, bool is64, ContentType contentType)
- : SimpleDefinedAtom(file), _is64(is64), _contentType(contentType) { }
-
- ~NonLazyPointerAtom() override = default;
-
- ContentType contentType() const override {
- return _contentType;
- }
-
- Alignment alignment() const override {
- return _is64 ? 8 : 4;
- }
-
- uint64_t size() const override {
- return _is64 ? 8 : 4;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permRW_;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- static const uint8_t zeros[] =
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- return llvm::makeArrayRef(zeros, size());
- }
-
-private:
- const bool _is64;
- const ContentType _contentType;
-};
-
-//
-// Stub Atom created by the stubs pass.
-//
-class StubAtom : public SimpleDefinedAtom {
-public:
- StubAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
- : SimpleDefinedAtom(file), _stubInfo(stubInfo){ }
-
- ~StubAtom() override = default;
-
- ContentType contentType() const override {
- return DefinedAtom::typeStub;
- }
-
- Alignment alignment() const override {
- return 1 << _stubInfo.codeAlignment;
- }
-
- uint64_t size() const override {
- return _stubInfo.stubSize;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permR_X;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(_stubInfo.stubBytes, _stubInfo.stubSize);
- }
-
-private:
- const ArchHandler::StubInfo &_stubInfo;
-};
-
-//
-// Stub Helper Atom created by the stubs pass.
-//
-class StubHelperAtom : public SimpleDefinedAtom {
-public:
- StubHelperAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
- : SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
-
- ~StubHelperAtom() override = default;
-
- ContentType contentType() const override {
- return DefinedAtom::typeStubHelper;
- }
-
- Alignment alignment() const override {
- return 1 << _stubInfo.codeAlignment;
- }
-
- uint64_t size() const override {
- return _stubInfo.stubHelperSize;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permR_X;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(_stubInfo.stubHelperBytes,
- _stubInfo.stubHelperSize);
- }
-
-private:
- const ArchHandler::StubInfo &_stubInfo;
-};
-
-//
-// Stub Helper Common Atom created by the stubs pass.
-//
-class StubHelperCommonAtom : public SimpleDefinedAtom {
-public:
- StubHelperCommonAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
- : SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
-
- ~StubHelperCommonAtom() override = default;
-
- ContentType contentType() const override {
- return DefinedAtom::typeStubHelper;
- }
-
- Alignment alignment() const override {
- return 1 << _stubInfo.stubHelperCommonAlignment;
- }
-
- uint64_t size() const override {
- return _stubInfo.stubHelperCommonSize;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permR_X;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(_stubInfo.stubHelperCommonBytes,
- _stubInfo.stubHelperCommonSize);
- }
-
-private:
- const ArchHandler::StubInfo &_stubInfo;
-};
-
-class StubsPass : public Pass {
-public:
- StubsPass(const MachOLinkingContext &context)
- : _ctx(context), _archHandler(_ctx.archHandler()),
- _stubInfo(_archHandler.stubInfo()),
- _file(*_ctx.make_file<MachOFile>("<mach-o Stubs pass>")) {
- _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
- }
-
- llvm::Error perform(SimpleFile &mergedFile) override {
- // Skip this pass if output format uses text relocations instead of stubs.
- if (!this->noTextRelocs())
- return llvm::Error::success();
-
- // Scan all references in all atoms.
- for (const DefinedAtom *atom : mergedFile.defined()) {
- for (const Reference *ref : *atom) {
- // Look at call-sites.
- if (!this->isCallSite(*ref))
- continue;
- const Atom *target = ref->target();
- assert(target != nullptr);
- if (isa<SharedLibraryAtom>(target)) {
- // Calls to shared libraries go through stubs.
- _targetToUses[target].push_back(ref);
- continue;
- }
- const DefinedAtom *defTarget = dyn_cast<DefinedAtom>(target);
- if (defTarget && defTarget->interposable() != DefinedAtom::interposeNo){
- // Calls to interposable functions in same linkage unit must also go
- // through a stub.
- assert(defTarget->scope() != DefinedAtom::scopeTranslationUnit);
- _targetToUses[target].push_back(ref);
- }
- }
- }
-
- // Exit early if no stubs needed.
- if (_targetToUses.empty())
- return llvm::Error::success();
-
- // First add help-common and GOT slots used by lazy binding.
- SimpleDefinedAtom *helperCommonAtom =
- new (_file.allocator()) StubHelperCommonAtom(_file, _stubInfo);
- SimpleDefinedAtom *helperCacheNLPAtom =
- new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit(),
- _stubInfo.stubHelperImageCacheContentType);
- SimpleDefinedAtom *helperBinderNLPAtom =
- new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit(),
- _stubInfo.stubHelperImageCacheContentType);
- addReference(helperCommonAtom, _stubInfo.stubHelperCommonReferenceToCache,
- helperCacheNLPAtom);
- addOptReference(
- helperCommonAtom, _stubInfo.stubHelperCommonReferenceToCache,
- _stubInfo.optStubHelperCommonReferenceToCache, helperCacheNLPAtom);
- addReference(helperCommonAtom, _stubInfo.stubHelperCommonReferenceToBinder,
- helperBinderNLPAtom);
- addOptReference(
- helperCommonAtom, _stubInfo.stubHelperCommonReferenceToBinder,
- _stubInfo.optStubHelperCommonReferenceToBinder, helperBinderNLPAtom);
- mergedFile.addAtom(*helperCommonAtom);
- mergedFile.addAtom(*helperBinderNLPAtom);
- mergedFile.addAtom(*helperCacheNLPAtom);
-
- // Add reference to dyld_stub_binder in libSystem.dylib
- auto I = llvm::find_if(
- mergedFile.sharedLibrary(), [&](const SharedLibraryAtom *atom) {
- return atom->name().equals(_stubInfo.binderSymbolName);
- });
- assert(I != mergedFile.sharedLibrary().end() &&
- "dyld_stub_binder not found");
- addReference(helperBinderNLPAtom, _stubInfo.nonLazyPointerReferenceToBinder, *I);
-
- // Sort targets by name, so stubs and lazy pointers are consistent
- std::vector<const Atom *> targetsNeedingStubs;
- for (auto it : _targetToUses)
- targetsNeedingStubs.push_back(it.first);
- std::sort(targetsNeedingStubs.begin(), targetsNeedingStubs.end(),
- [](const Atom * left, const Atom * right) {
- return (left->name().compare(right->name()) < 0);
- });
-
- // Make and append stubs, lazy pointers, and helpers in alphabetical order.
- unsigned lazyOffset = 0;
- for (const Atom *target : targetsNeedingStubs) {
- auto *stub = new (_file.allocator()) StubAtom(_file, _stubInfo);
- auto *lp =
- new (_file.allocator()) LazyPointerAtom(_file, _ctx.is64Bit());
- auto *helper = new (_file.allocator()) StubHelperAtom(_file, _stubInfo);
-
- addReference(stub, _stubInfo.stubReferenceToLP, lp);
- addOptReference(stub, _stubInfo.stubReferenceToLP,
- _stubInfo.optStubReferenceToLP, lp);
- addReference(lp, _stubInfo.lazyPointerReferenceToHelper, helper);
- addReference(lp, _stubInfo.lazyPointerReferenceToFinal, target);
- addReference(helper, _stubInfo.stubHelperReferenceToImm, helper);
- addReferenceAddend(helper, _stubInfo.stubHelperReferenceToImm, helper,
- lazyOffset);
- addReference(helper, _stubInfo.stubHelperReferenceToHelperCommon,
- helperCommonAtom);
-
- mergedFile.addAtom(*stub);
- mergedFile.addAtom(*lp);
- mergedFile.addAtom(*helper);
-
- // Update each reference to use stub.
- for (const Reference *ref : _targetToUses[target]) {
- assert(ref->target() == target);
- // Switch call site to reference stub atom instead.
- const_cast<Reference *>(ref)->setTarget(stub);
- }
-
- // Calculate new offset
- lazyOffset += target->name().size() + 12;
- }
-
- return llvm::Error::success();
- }
-
-private:
- bool noTextRelocs() {
- return true;
- }
-
- bool isCallSite(const Reference &ref) {
- return _archHandler.isCallSite(ref);
- }
-
- void addReference(SimpleDefinedAtom* atom,
- const ArchHandler::ReferenceInfo &refInfo,
- const lld::Atom* target) {
- atom->addReference(Reference::KindNamespace::mach_o,
- refInfo.arch, refInfo.kind, refInfo.offset,
- target, refInfo.addend);
- }
-
- void addReferenceAddend(SimpleDefinedAtom *atom,
- const ArchHandler::ReferenceInfo &refInfo,
- const lld::Atom *target, uint64_t addend) {
- atom->addReference(Reference::KindNamespace::mach_o, refInfo.arch,
- refInfo.kind, refInfo.offset, target, addend);
- }
-
- void addOptReference(SimpleDefinedAtom* atom,
- const ArchHandler::ReferenceInfo &refInfo,
- const ArchHandler::OptionalRefInfo &optRef,
- const lld::Atom* target) {
- if (!optRef.used)
- return;
- atom->addReference(Reference::KindNamespace::mach_o,
- refInfo.arch, optRef.kind, optRef.offset,
- target, optRef.addend);
- }
-
- typedef llvm::DenseMap<const Atom*,
- llvm::SmallVector<const Reference *, 8>> TargetToUses;
-
- const MachOLinkingContext &_ctx;
- mach_o::ArchHandler &_archHandler;
- const ArchHandler::StubInfo &_stubInfo;
- MachOFile &_file;
- TargetToUses _targetToUses;
-};
-
-void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx) {
- pm.add(std::unique_ptr<Pass>(new StubsPass(ctx)));
-}
-
-} // end namespace mach_o
-} // end namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/TLVPass.cpp -----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This linker pass transforms all TLV references to real references.
-///
-//===----------------------------------------------------------------------===//
-
-#include "ArchHandler.h"
-#include "File.h"
-#include "MachOPasses.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Debug.h"
-
-namespace lld {
-namespace mach_o {
-
-//
-// TLVP Entry Atom created by the TLV pass.
-//
-class TLVPEntryAtom : public SimpleDefinedAtom {
-public:
- TLVPEntryAtom(const File &file, bool is64, StringRef name)
- : SimpleDefinedAtom(file), _is64(is64), _name(name) {}
-
- ~TLVPEntryAtom() override = default;
-
- ContentType contentType() const override {
- return DefinedAtom::typeTLVInitializerPtr;
- }
-
- Alignment alignment() const override {
- return _is64 ? 8 : 4;
- }
-
- uint64_t size() const override {
- return _is64 ? 8 : 4;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permRW_;
- }
-
- ArrayRef<uint8_t> rawContent() const override {
- static const uint8_t zeros[] =
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- return llvm::makeArrayRef(zeros, size());
- }
-
- StringRef slotName() const {
- return _name;
- }
-
-private:
- const bool _is64;
- StringRef _name;
-};
-
-class TLVPass : public Pass {
-public:
- TLVPass(const MachOLinkingContext &context)
- : _ctx(context), _archHandler(_ctx.archHandler()),
- _file(*_ctx.make_file<MachOFile>("<mach-o TLV pass>")) {
- _file.setOrdinal(_ctx.getNextOrdinalAndIncrement());
- }
-
-private:
- llvm::Error perform(SimpleFile &mergedFile) override {
- bool allowTLV = _ctx.minOS("10.7", "1.0");
-
- for (const DefinedAtom *atom : mergedFile.defined()) {
- for (const Reference *ref : *atom) {
- if (!_archHandler.isTLVAccess(*ref))
- continue;
-
- if (!allowTLV)
- return llvm::make_error<GenericError>(
- "targeted OS version does not support use of thread local "
- "variables in " + atom->name() + " for architecture " +
- _ctx.archName());
-
- const Atom *target = ref->target();
- assert(target != nullptr);
-
- const DefinedAtom *tlvpEntry = makeTLVPEntry(target);
- const_cast<Reference*>(ref)->setTarget(tlvpEntry);
- _archHandler.updateReferenceToTLV(ref);
- }
- }
-
- std::vector<const TLVPEntryAtom*> entries;
- entries.reserve(_targetToTLVP.size());
- for (auto &it : _targetToTLVP)
- entries.push_back(it.second);
- std::sort(entries.begin(), entries.end(),
- [](const TLVPEntryAtom *lhs, const TLVPEntryAtom *rhs) {
- return (lhs->slotName().compare(rhs->slotName()) < 0);
- });
-
- for (const TLVPEntryAtom *slot : entries)
- mergedFile.addAtom(*slot);
-
- return llvm::Error::success();
- }
-
- const DefinedAtom *makeTLVPEntry(const Atom *target) {
- auto pos = _targetToTLVP.find(target);
-
- if (pos != _targetToTLVP.end())
- return pos->second;
-
- auto *tlvpEntry = new (_file.allocator())
- TLVPEntryAtom(_file, _ctx.is64Bit(), target->name());
- _targetToTLVP[target] = tlvpEntry;
- const ArchHandler::ReferenceInfo &nlInfo =
- _archHandler.stubInfo().nonLazyPointerReferenceToBinder;
- tlvpEntry->addReference(Reference::KindNamespace::mach_o, nlInfo.arch,
- nlInfo.kind, 0, target, 0);
- return tlvpEntry;
- }
-
- const MachOLinkingContext &_ctx;
- mach_o::ArchHandler &_archHandler;
- MachOFile &_file;
- llvm::DenseMap<const Atom*, const TLVPEntryAtom*> _targetToTLVP;
-};
-
-void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx) {
- assert(ctx.needsTLVPass());
- pm.add(std::make_unique<TLVPass>(ctx));
-}
-
-} // end namespace mach_o
-} // end namespace lld
+++ /dev/null
-//===- lib/ReaderWriter/MachO/WriterMachO.cpp -----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ExecutableAtoms.h"
-#include "MachONormalizedFile.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Writer.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <system_error>
-
-using lld::mach_o::normalized::NormalizedFile;
-
-namespace lld {
-namespace mach_o {
-
-class MachOWriter : public Writer {
-public:
- MachOWriter(const MachOLinkingContext &ctxt) : _ctx(ctxt) {}
-
- llvm::Error writeFile(const lld::File &file, StringRef path) override {
- // Construct empty normalized file from atoms.
- llvm::Expected<std::unique_ptr<NormalizedFile>> nFile =
- normalized::normalizedFromAtoms(file, _ctx);
- if (auto ec = nFile.takeError())
- return ec;
-
- // For testing, write out yaml form of normalized file.
- if (_ctx.printAtoms()) {
- std::unique_ptr<Writer> yamlWriter = createWriterYAML(_ctx);
- if (auto ec = yamlWriter->writeFile(file, "-"))
- return ec;
- }
-
- // Write normalized file as mach-o binary.
- return writeBinary(*nFile->get(), path);
- }
-
- void createImplicitFiles(std::vector<std::unique_ptr<File>> &r) override {
- // When building main executables, add _main as required entry point.
- if (_ctx.outputTypeHasEntry())
- r.emplace_back(new CEntryFile(_ctx));
- // If this can link with dylibs, need helper function (dyld_stub_binder).
- if (_ctx.needsStubsPass())
- r.emplace_back(new StubHelperFile(_ctx));
- // Final linked images can access a symbol for their mach_header.
- if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
- r.emplace_back(new MachHeaderAliasFile(_ctx));
- }
-private:
- const MachOLinkingContext &_ctx;
- };
-
-
-} // namespace mach_o
-
-std::unique_ptr<Writer> createWriterMachO(const MachOLinkingContext &context) {
- return std::unique_ptr<Writer>(new lld::mach_o::MachOWriter(context));
-}
-
-} // namespace lld
+++ /dev/null
-add_lld_library(lldYAML
- ReaderWriterYAML.cpp
-
- LINK_COMPONENTS
- Support
-
- LINK_LIBS
- lldCore
- )
+++ /dev/null
-//===- lib/ReaderWriter/YAML/ReaderWriterYAML.cpp -------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "lld/Core/AbsoluteAtom.h"
-#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/File.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Reference.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/Core/Simple.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/Core/Writer.h"
-#include "lld/ReaderWriter/YamlContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/Magic.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <cstdint>
-#include <cstring>
-#include <memory>
-#include <string>
-#include <system_error>
-#include <vector>
-
-using llvm::file_magic;
-using llvm::yaml::MappingTraits;
-using llvm::yaml::ScalarEnumerationTraits;
-using llvm::yaml::ScalarTraits;
-using llvm::yaml::IO;
-using llvm::yaml::SequenceTraits;
-using llvm::yaml::DocumentListTraits;
-
-using namespace lld;
-
-/// The conversion of Atoms to and from YAML uses LLVM's YAML I/O. This
-/// file just defines template specializations on the lld types which control
-/// how the mapping is done to and from YAML.
-
-namespace {
-
-/// Used when writing yaml files.
-/// 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
-/// cases that does not work, so ref-names are added. These are labels
-/// used only in yaml. The labels do not exist in the Atom model.
-///
-/// One need for ref-names are when atoms have no user supplied name
-/// (e.g. c-string literal). Another case is when two object files with
-/// identically named static functions are merged (ld -r) into one object file.
-/// In that case referencing the function by name is ambiguous, so a unique
-/// ref-name is added.
-class RefNameBuilder {
-public:
- RefNameBuilder(const lld::File &file)
- : _collisionCount(0), _unnamedCounter(0) {
- // visit all atoms
- for (const lld::DefinedAtom *atom : file.defined()) {
- // Build map of atoms names to detect duplicates
- if (!atom->name().empty())
- buildDuplicateNameMap(*atom);
-
- // Find references to unnamed atoms and create ref-names for them.
- for (const lld::Reference *ref : *atom) {
- // create refname for any unnamed reference target
- const lld::Atom *target = ref->target();
- if ((target != nullptr) && target->name().empty()) {
- std::string storage;
- llvm::raw_string_ostream buffer(storage);
- buffer << llvm::format("L%03d", _unnamedCounter++);
- StringRef newName = copyString(buffer.str());
- _refNames[target] = std::string(newName);
- DEBUG_WITH_TYPE("WriterYAML",
- llvm::dbgs() << "unnamed atom: creating ref-name: '"
- << newName << "' ("
- << (const void *)newName.data() << ", "
- << newName.size() << ")\n");
- }
- }
- }
- for (const lld::UndefinedAtom *undefAtom : file.undefined()) {
- buildDuplicateNameMap(*undefAtom);
- }
- for (const lld::SharedLibraryAtom *shlibAtom : file.sharedLibrary()) {
- buildDuplicateNameMap(*shlibAtom);
- }
- for (const lld::AbsoluteAtom *absAtom : file.absolute()) {
- if (!absAtom->name().empty())
- buildDuplicateNameMap(*absAtom);
- }
- }
-
- void buildDuplicateNameMap(const lld::Atom &atom) {
- assert(!atom.name().empty());
- NameToAtom::iterator pos = _nameMap.find(atom.name());
- if (pos != _nameMap.end()) {
- // Found name collision, give each a unique ref-name.
- std::string Storage;
- llvm::raw_string_ostream buffer(Storage);
- buffer << atom.name() << llvm::format(".%03d", ++_collisionCount);
- StringRef newName = copyString(buffer.str());
- _refNames[&atom] = std::string(newName);
- DEBUG_WITH_TYPE("WriterYAML",
- llvm::dbgs() << "name collision: creating ref-name: '"
- << newName << "' ("
- << (const void *)newName.data()
- << ", " << newName.size() << ")\n");
- const lld::Atom *prevAtom = pos->second;
- AtomToRefName::iterator pos2 = _refNames.find(prevAtom);
- if (pos2 == _refNames.end()) {
- // Only create ref-name for previous if none already created.
- std::string Storage2;
- llvm::raw_string_ostream buffer2(Storage2);
- buffer2 << prevAtom->name() << llvm::format(".%03d", ++_collisionCount);
- StringRef newName2 = copyString(buffer2.str());
- _refNames[prevAtom] = std::string(newName2);
- DEBUG_WITH_TYPE("WriterYAML",
- llvm::dbgs() << "name collision: creating ref-name: '"
- << newName2 << "' ("
- << (const void *)newName2.data() << ", "
- << newName2.size() << ")\n");
- }
- } else {
- // First time we've seen this name, just add it to map.
- _nameMap[atom.name()] = &atom;
- DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
- << "atom name seen for first time: '"
- << atom.name() << "' ("
- << (const void *)atom.name().data()
- << ", " << atom.name().size() << ")\n");
- }
- }
-
- bool hasRefName(const lld::Atom *atom) { return _refNames.count(atom); }
-
- StringRef refName(const lld::Atom *atom) {
- return _refNames.find(atom)->second;
- }
-
-private:
- typedef llvm::StringMap<const lld::Atom *> NameToAtom;
- typedef llvm::DenseMap<const lld::Atom *, std::string> AtomToRefName;
-
- // Allocate a new copy of this string in _storage, so the strings
- // can be freed when RefNameBuilder is destroyed.
- StringRef copyString(StringRef str) {
- char *s = _storage.Allocate<char>(str.size());
- memcpy(s, str.data(), str.size());
- return StringRef(s, str.size());
- }
-
- unsigned int _collisionCount;
- unsigned int _unnamedCounter;
- NameToAtom _nameMap;
- AtomToRefName _refNames;
- llvm::BumpPtrAllocator _storage;
-};
-
-/// Used when reading yaml files to find the target of a reference
-/// that could be a name or ref-name.
-class RefNameResolver {
-public:
- RefNameResolver(const lld::File *file, IO &io);
-
- const lld::Atom *lookup(StringRef name) const {
- NameToAtom::const_iterator pos = _nameMap.find(name);
- if (pos != _nameMap.end())
- return pos->second;
- _io.setError(Twine("no such atom name: ") + name);
- return nullptr;
- }
-
-private:
- typedef llvm::StringMap<const lld::Atom *> NameToAtom;
-
- void add(StringRef name, const lld::Atom *atom) {
- if (_nameMap.count(name)) {
- _io.setError(Twine("duplicate atom name: ") + name);
- } else {
- _nameMap[name] = atom;
- }
- }
-
- IO &_io;
- NameToAtom _nameMap;
-};
-
-/// Mapping of Atoms.
-template <typename T> class AtomList {
- using Ty = std::vector<OwningAtomPtr<T>>;
-
-public:
- typename Ty::iterator begin() { return _atoms.begin(); }
- typename Ty::iterator end() { return _atoms.end(); }
- Ty _atoms;
-};
-
-/// Mapping of kind: field in yaml files.
-enum FileKinds {
- fileKindObjectAtoms, // atom based object file encoded in yaml
- fileKindArchive, // static archive library encoded in yaml
- fileKindObjectMachO // mach-o object files encoded in yaml
-};
-
-struct ArchMember {
- FileKinds _kind;
- StringRef _name;
- const lld::File *_content;
-};
-
-// The content bytes in a DefinedAtom are just uint8_t but we want
-// special formatting, so define a strong type.
-LLVM_YAML_STRONG_TYPEDEF(uint8_t, ImplicitHex8)
-
-// SharedLibraryAtoms have a bool canBeNull() method which we'd like to be
-// more readable than just true/false.
-LLVM_YAML_STRONG_TYPEDEF(bool, ShlibCanBeNull)
-
-// lld::Reference::Kind is a tuple of <namespace, arch, value>.
-// For yaml, we just want one string that encapsulates the tuple.
-struct RefKind {
- Reference::KindNamespace ns;
- Reference::KindArch arch;
- Reference::KindValue value;
-};
-
-} // end anonymous namespace
-
-LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember)
-LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference *)
-// Always write DefinedAtoms content bytes as a flow sequence.
-LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(ImplicitHex8)
-
-// for compatibility with gcc-4.7 in C++11 mode, add extra namespace
-namespace llvm {
-namespace yaml {
-
-// This is a custom formatter for RefKind
-template <> struct ScalarTraits<RefKind> {
- static void output(const RefKind &kind, void *ctxt, raw_ostream &out) {
- assert(ctxt != nullptr);
- YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
- assert(info->_registry);
- StringRef str;
- if (info->_registry->referenceKindToString(kind.ns, kind.arch, kind.value,
- str))
- out << str;
- else
- out << (int)(kind.ns) << "-" << (int)(kind.arch) << "-" << kind.value;
- }
-
- static StringRef input(StringRef scalar, void *ctxt, RefKind &kind) {
- assert(ctxt != nullptr);
- YamlContext *info = reinterpret_cast<YamlContext *>(ctxt);
- assert(info->_registry);
- if (info->_registry->referenceKindFromString(scalar, kind.ns, kind.arch,
- kind.value))
- return StringRef();
- return StringRef("unknown reference kind");
- }
-
- static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <> struct ScalarEnumerationTraits<lld::File::Kind> {
- static void enumeration(IO &io, lld::File::Kind &value) {
- io.enumCase(value, "error-object", lld::File::kindErrorObject);
- io.enumCase(value, "object", lld::File::kindMachObject);
- io.enumCase(value, "shared-library", lld::File::kindSharedLibrary);
- io.enumCase(value, "static-library", lld::File::kindArchiveLibrary);
- }
-};
-
-template <> struct ScalarEnumerationTraits<lld::Atom::Scope> {
- static void enumeration(IO &io, lld::Atom::Scope &value) {
- io.enumCase(value, "global", lld::Atom::scopeGlobal);
- io.enumCase(value, "hidden", lld::Atom::scopeLinkageUnit);
- io.enumCase(value, "static", lld::Atom::scopeTranslationUnit);
- }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::SectionChoice> {
- static void enumeration(IO &io, lld::DefinedAtom::SectionChoice &value) {
- io.enumCase(value, "content", lld::DefinedAtom::sectionBasedOnContent);
- io.enumCase(value, "custom", lld::DefinedAtom::sectionCustomPreferred);
- io.enumCase(value, "custom-required",
- lld::DefinedAtom::sectionCustomRequired);
- }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::Interposable> {
- static void enumeration(IO &io, lld::DefinedAtom::Interposable &value) {
- io.enumCase(value, "no", DefinedAtom::interposeNo);
- io.enumCase(value, "yes", DefinedAtom::interposeYes);
- io.enumCase(value, "yes-and-weak", DefinedAtom::interposeYesAndRuntimeWeak);
- }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::Merge> {
- static void enumeration(IO &io, lld::DefinedAtom::Merge &value) {
- io.enumCase(value, "no", lld::DefinedAtom::mergeNo);
- io.enumCase(value, "as-tentative", lld::DefinedAtom::mergeAsTentative);
- io.enumCase(value, "as-weak", lld::DefinedAtom::mergeAsWeak);
- io.enumCase(value, "as-addressed-weak",
- lld::DefinedAtom::mergeAsWeakAndAddressUsed);
- io.enumCase(value, "by-content", lld::DefinedAtom::mergeByContent);
- io.enumCase(value, "same-name-and-size",
- lld::DefinedAtom::mergeSameNameAndSize);
- io.enumCase(value, "largest", lld::DefinedAtom::mergeByLargestSection);
- }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DeadStripKind> {
- static void enumeration(IO &io, lld::DefinedAtom::DeadStripKind &value) {
- io.enumCase(value, "normal", lld::DefinedAtom::deadStripNormal);
- io.enumCase(value, "never", lld::DefinedAtom::deadStripNever);
- io.enumCase(value, "always", lld::DefinedAtom::deadStripAlways);
- }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::DynamicExport> {
- static void enumeration(IO &io, lld::DefinedAtom::DynamicExport &value) {
- io.enumCase(value, "normal", lld::DefinedAtom::dynamicExportNormal);
- io.enumCase(value, "always", lld::DefinedAtom::dynamicExportAlways);
- }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::CodeModel> {
- static void enumeration(IO &io, lld::DefinedAtom::CodeModel &value) {
- io.enumCase(value, "none", lld::DefinedAtom::codeNA);
- io.enumCase(value, "mips-pic", lld::DefinedAtom::codeMipsPIC);
- io.enumCase(value, "mips-micro", lld::DefinedAtom::codeMipsMicro);
- io.enumCase(value, "mips-micro-pic", lld::DefinedAtom::codeMipsMicroPIC);
- io.enumCase(value, "mips-16", lld::DefinedAtom::codeMips16);
- io.enumCase(value, "arm-thumb", lld::DefinedAtom::codeARMThumb);
- io.enumCase(value, "arm-a", lld::DefinedAtom::codeARM_a);
- io.enumCase(value, "arm-d", lld::DefinedAtom::codeARM_d);
- io.enumCase(value, "arm-t", lld::DefinedAtom::codeARM_t);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<lld::DefinedAtom::ContentPermissions> {
- static void enumeration(IO &io, lld::DefinedAtom::ContentPermissions &value) {
- io.enumCase(value, "---", lld::DefinedAtom::perm___);
- io.enumCase(value, "r--", lld::DefinedAtom::permR__);
- io.enumCase(value, "r-x", lld::DefinedAtom::permR_X);
- io.enumCase(value, "rw-", lld::DefinedAtom::permRW_);
- io.enumCase(value, "rwx", lld::DefinedAtom::permRWX);
- io.enumCase(value, "rw-l", lld::DefinedAtom::permRW_L);
- io.enumCase(value, "unknown", lld::DefinedAtom::permUnknown);
- }
-};
-
-template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
- static void enumeration(IO &io, lld::DefinedAtom::ContentType &value) {
- io.enumCase(value, "unknown", DefinedAtom::typeUnknown);
- io.enumCase(value, "code", DefinedAtom::typeCode);
- io.enumCase(value, "stub", DefinedAtom::typeStub);
- io.enumCase(value, "constant", DefinedAtom::typeConstant);
- io.enumCase(value, "data", DefinedAtom::typeData);
- io.enumCase(value, "quick-data", DefinedAtom::typeDataFast);
- io.enumCase(value, "zero-fill", DefinedAtom::typeZeroFill);
- io.enumCase(value, "zero-fill-quick", DefinedAtom::typeZeroFillFast);
- io.enumCase(value, "const-data", DefinedAtom::typeConstData);
- io.enumCase(value, "got", DefinedAtom::typeGOT);
- io.enumCase(value, "resolver", DefinedAtom::typeResolver);
- io.enumCase(value, "branch-island", DefinedAtom::typeBranchIsland);
- io.enumCase(value, "branch-shim", DefinedAtom::typeBranchShim);
- io.enumCase(value, "stub-helper", DefinedAtom::typeStubHelper);
- io.enumCase(value, "c-string", DefinedAtom::typeCString);
- io.enumCase(value, "utf16-string", DefinedAtom::typeUTF16String);
- io.enumCase(value, "unwind-cfi", DefinedAtom::typeCFI);
- io.enumCase(value, "unwind-lsda", DefinedAtom::typeLSDA);
- io.enumCase(value, "const-4-byte", DefinedAtom::typeLiteral4);
- io.enumCase(value, "const-8-byte", DefinedAtom::typeLiteral8);
- io.enumCase(value, "const-16-byte", DefinedAtom::typeLiteral16);
- io.enumCase(value, "lazy-pointer", DefinedAtom::typeLazyPointer);
- io.enumCase(value, "lazy-dylib-pointer",
- DefinedAtom::typeLazyDylibPointer);
- io.enumCase(value, "cfstring", DefinedAtom::typeCFString);
- io.enumCase(value, "initializer-pointer",
- DefinedAtom::typeInitializerPtr);
- io.enumCase(value, "terminator-pointer",
- DefinedAtom::typeTerminatorPtr);
- io.enumCase(value, "c-string-pointer",DefinedAtom::typeCStringPtr);
- io.enumCase(value, "objc-class-pointer",
- DefinedAtom::typeObjCClassPtr);
- io.enumCase(value, "objc-category-list",
- DefinedAtom::typeObjC2CategoryList);
- io.enumCase(value, "objc-image-info",
- DefinedAtom::typeObjCImageInfo);
- io.enumCase(value, "objc-method-list",
- DefinedAtom::typeObjCMethodList);
- io.enumCase(value, "objc-class1", DefinedAtom::typeObjC1Class);
- io.enumCase(value, "dtraceDOF", DefinedAtom::typeDTraceDOF);
- io.enumCase(value, "interposing-tuples",
- DefinedAtom::typeInterposingTuples);
- io.enumCase(value, "lto-temp", DefinedAtom::typeTempLTO);
- io.enumCase(value, "compact-unwind", DefinedAtom::typeCompactUnwindInfo);
- io.enumCase(value, "unwind-info", DefinedAtom::typeProcessedUnwindInfo);
- io.enumCase(value, "tlv-thunk", DefinedAtom::typeThunkTLV);
- io.enumCase(value, "tlv-data", DefinedAtom::typeTLVInitialData);
- io.enumCase(value, "tlv-zero-fill", DefinedAtom::typeTLVInitialZeroFill);
- io.enumCase(value, "tlv-initializer-ptr",
- DefinedAtom::typeTLVInitializerPtr);
- io.enumCase(value, "mach_header", DefinedAtom::typeMachHeader);
- io.enumCase(value, "dso_handle", DefinedAtom::typeDSOHandle);
- io.enumCase(value, "sectcreate", DefinedAtom::typeSectCreate);
- }
-};
-
-template <> struct ScalarEnumerationTraits<lld::UndefinedAtom::CanBeNull> {
- static void enumeration(IO &io, lld::UndefinedAtom::CanBeNull &value) {
- io.enumCase(value, "never", lld::UndefinedAtom::canBeNullNever);
- io.enumCase(value, "at-runtime", lld::UndefinedAtom::canBeNullAtRuntime);
- io.enumCase(value, "at-buildtime",lld::UndefinedAtom::canBeNullAtBuildtime);
- }
-};
-
-template <> struct ScalarEnumerationTraits<ShlibCanBeNull> {
- static void enumeration(IO &io, ShlibCanBeNull &value) {
- io.enumCase(value, "never", false);
- io.enumCase(value, "at-runtime", true);
- }
-};
-
-template <>
-struct ScalarEnumerationTraits<lld::SharedLibraryAtom::Type> {
- static void enumeration(IO &io, lld::SharedLibraryAtom::Type &value) {
- io.enumCase(value, "code", lld::SharedLibraryAtom::Type::Code);
- io.enumCase(value, "data", lld::SharedLibraryAtom::Type::Data);
- io.enumCase(value, "unknown", lld::SharedLibraryAtom::Type::Unknown);
- }
-};
-
-/// This is a custom formatter for lld::DefinedAtom::Alignment. Values look
-/// like:
-/// 8 # 8-byte aligned
-/// 7 mod 16 # 16-byte aligned plus 7 bytes
-template <> struct ScalarTraits<lld::DefinedAtom::Alignment> {
- static void output(const lld::DefinedAtom::Alignment &value, void *ctxt,
- raw_ostream &out) {
- if (value.modulus == 0) {
- out << llvm::format("%d", value.value);
- } else {
- out << llvm::format("%d mod %d", value.modulus, value.value);
- }
- }
-
- static StringRef input(StringRef scalar, void *ctxt,
- lld::DefinedAtom::Alignment &value) {
- value.modulus = 0;
- size_t modStart = scalar.find("mod");
- if (modStart != StringRef::npos) {
- StringRef modStr = scalar.slice(0, modStart);
- modStr = modStr.rtrim();
- unsigned int modulus;
- if (modStr.getAsInteger(0, modulus)) {
- return "malformed alignment modulus";
- }
- value.modulus = modulus;
- scalar = scalar.drop_front(modStart + 3);
- scalar = scalar.ltrim();
- }
- unsigned int power;
- if (scalar.getAsInteger(0, power)) {
- return "malformed alignment power";
- }
- value.value = power;
- if (value.modulus >= power) {
- return "malformed alignment, modulus too large for power";
- }
- return StringRef(); // returning empty string means success
- }
-
- static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-template <> struct ScalarEnumerationTraits<FileKinds> {
- static void enumeration(IO &io, FileKinds &value) {
- io.enumCase(value, "object", fileKindObjectAtoms);
- io.enumCase(value, "archive", fileKindArchive);
- io.enumCase(value, "object-mach-o", fileKindObjectMachO);
- }
-};
-
-template <> struct MappingTraits<ArchMember> {
- static void mapping(IO &io, ArchMember &member) {
- io.mapOptional("kind", member._kind, fileKindObjectAtoms);
- io.mapOptional("name", member._name);
- io.mapRequired("content", member._content);
- }
-};
-
-// Declare that an AtomList is a yaml sequence.
-template <typename T> struct SequenceTraits<AtomList<T> > {
- static size_t size(IO &io, AtomList<T> &seq) { return seq._atoms.size(); }
- static T *&element(IO &io, AtomList<T> &seq, size_t index) {
- if (index >= seq._atoms.size())
- seq._atoms.resize(index + 1);
- return seq._atoms[index].get();
- }
-};
-
-// Declare that an AtomRange is a yaml sequence.
-template <typename T> struct SequenceTraits<File::AtomRange<T> > {
- static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
- static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
- assert(io.outputting() && "AtomRange only used when outputting");
- assert(index < seq.size() && "Out of range access");
- return seq[index].get();
- }
-};
-
-// Used to allow DefinedAtom content bytes to be a flow sequence of
-// two-digit hex numbers without the leading 0x (e.g. FF, 04, 0A)
-template <> struct ScalarTraits<ImplicitHex8> {
- static void output(const ImplicitHex8 &val, void *, raw_ostream &out) {
- uint8_t num = val;
- out << llvm::format("%02X", num);
- }
-
- static StringRef input(StringRef str, void *, ImplicitHex8 &val) {
- unsigned long long n;
- if (getAsUnsignedInteger(str, 16, n))
- return "invalid two-digit-hex number";
- if (n > 0xFF)
- return "out of range two-digit-hex number";
- val = n;
- return StringRef(); // returning empty string means success
- }
-
- static QuotingType mustQuote(StringRef) { return QuotingType::None; }
-};
-
-// YAML conversion for std::vector<const lld::File*>
-template <> struct DocumentListTraits<std::vector<const lld::File *> > {
- static size_t size(IO &io, std::vector<const lld::File *> &seq) {
- return seq.size();
- }
- static const lld::File *&element(IO &io, std::vector<const lld::File *> &seq,
- size_t index) {
- if (index >= seq.size())
- seq.resize(index + 1);
- return seq[index];
- }
-};
-
-// YAML conversion for const lld::File*
-template <> struct MappingTraits<const lld::File *> {
- class NormArchiveFile : public lld::ArchiveLibraryFile {
- public:
- NormArchiveFile(IO &io) : ArchiveLibraryFile("") {}
-
- NormArchiveFile(IO &io, const lld::File *file)
- : ArchiveLibraryFile(file->path()), _path(file->path()) {
- // If we want to support writing archives, this constructor would
- // need to populate _members.
- }
-
- const lld::File *denormalize(IO &io) { return this; }
-
- const AtomRange<lld::DefinedAtom> defined() const override {
- return _noDefinedAtoms;
- }
-
- const AtomRange<lld::UndefinedAtom> undefined() const override {
- return _noUndefinedAtoms;
- }
-
- const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
- return _noSharedLibraryAtoms;
- }
-
- const AtomRange<lld::AbsoluteAtom> absolute() const override {
- return _noAbsoluteAtoms;
- }
-
- void clearAtoms() override {
- _noDefinedAtoms.clear();
- _noUndefinedAtoms.clear();
- _noSharedLibraryAtoms.clear();
- _noAbsoluteAtoms.clear();
- }
-
- File *find(StringRef name) override {
- for (const ArchMember &member : _members)
- for (const lld::DefinedAtom *atom : member._content->defined())
- if (name == atom->name())
- return const_cast<File *>(member._content);
- return nullptr;
- }
-
- std::error_code
- parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
- return std::error_code();
- }
-
- StringRef _path;
- std::vector<ArchMember> _members;
- };
-
- class NormalizedFile : public lld::File {
- public:
- NormalizedFile(IO &io)
- : File("", kindNormalizedObject), _io(io), _rnb(nullptr),
- _definedAtomsRef(_definedAtoms._atoms),
- _undefinedAtomsRef(_undefinedAtoms._atoms),
- _sharedLibraryAtomsRef(_sharedLibraryAtoms._atoms),
- _absoluteAtomsRef(_absoluteAtoms._atoms) {}
-
- NormalizedFile(IO &io, const lld::File *file)
- : File(file->path(), kindNormalizedObject), _io(io),
- _rnb(new RefNameBuilder(*file)), _path(file->path()),
- _definedAtomsRef(file->defined()),
- _undefinedAtomsRef(file->undefined()),
- _sharedLibraryAtomsRef(file->sharedLibrary()),
- _absoluteAtomsRef(file->absolute()) {
- }
-
- ~NormalizedFile() override {
- }
-
- const lld::File *denormalize(IO &io);
-
- const AtomRange<lld::DefinedAtom> defined() const override {
- return _definedAtomsRef;
- }
-
- const AtomRange<lld::UndefinedAtom> undefined() const override {
- return _undefinedAtomsRef;
- }
-
- const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
- return _sharedLibraryAtomsRef;
- }
-
- const AtomRange<lld::AbsoluteAtom> absolute() const override {
- return _absoluteAtomsRef;
- }
-
- void clearAtoms() override {
- _definedAtoms._atoms.clear();
- _undefinedAtoms._atoms.clear();
- _sharedLibraryAtoms._atoms.clear();
- _absoluteAtoms._atoms.clear();
- }
-
- // Allocate a new copy of this string in _storage, so the strings
- // can be freed when File is destroyed.
- StringRef copyString(StringRef str) {
- char *s = _storage.Allocate<char>(str.size());
- memcpy(s, str.data(), str.size());
- return StringRef(s, str.size());
- }
-
- IO &_io;
- std::unique_ptr<RefNameBuilder> _rnb;
- StringRef _path;
- AtomList<lld::DefinedAtom> _definedAtoms;
- AtomList<lld::UndefinedAtom> _undefinedAtoms;
- AtomList<lld::SharedLibraryAtom> _sharedLibraryAtoms;
- AtomList<lld::AbsoluteAtom> _absoluteAtoms;
- AtomRange<lld::DefinedAtom> _definedAtomsRef;
- AtomRange<lld::UndefinedAtom> _undefinedAtomsRef;
- AtomRange<lld::SharedLibraryAtom> _sharedLibraryAtomsRef;
- AtomRange<lld::AbsoluteAtom> _absoluteAtomsRef;
- llvm::BumpPtrAllocator _storage;
- };
-
- static void mapping(IO &io, const lld::File *&file) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- // Let any register tag handler process this.
- if (info->_registry && info->_registry->handleTaggedDoc(io, file))
- return;
- // If no registered handler claims this tag and there is no tag,
- // grandfather in as "!native".
- if (io.mapTag("!native", true) || io.mapTag("tag:yaml.org,2002:map"))
- mappingAtoms(io, file);
- }
-
- static void mappingAtoms(IO &io, const lld::File *&file) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- MappingNormalizationHeap<NormalizedFile, const lld::File *>
- keys(io, file, nullptr);
- assert(info != nullptr);
- info->_file = keys.operator->();
-
- io.mapOptional("path", keys->_path);
-
- if (io.outputting()) {
- io.mapOptional("defined-atoms", keys->_definedAtomsRef);
- io.mapOptional("undefined-atoms", keys->_undefinedAtomsRef);
- io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtomsRef);
- io.mapOptional("absolute-atoms", keys->_absoluteAtomsRef);
- } else {
- io.mapOptional("defined-atoms", keys->_definedAtoms);
- io.mapOptional("undefined-atoms", keys->_undefinedAtoms);
- io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
- io.mapOptional("absolute-atoms", keys->_absoluteAtoms);
- }
- }
-
- static void mappingArchive(IO &io, const lld::File *&file) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- MappingNormalizationHeap<NormArchiveFile, const lld::File *>
- keys(io, file, &info->_file->allocator());
-
- io.mapOptional("path", keys->_path);
- io.mapOptional("members", keys->_members);
- }
-};
-
-// YAML conversion for const lld::Reference*
-template <> struct MappingTraits<const lld::Reference *> {
- class NormalizedReference : public lld::Reference {
- public:
- NormalizedReference(IO &io)
- : lld::Reference(lld::Reference::KindNamespace::all,
- lld::Reference::KindArch::all, 0),
- _target(nullptr), _offset(0), _addend(0), _tag(0) {}
-
- NormalizedReference(IO &io, const lld::Reference *ref)
- : lld::Reference(ref->kindNamespace(), ref->kindArch(),
- ref->kindValue()),
- _target(nullptr), _targetName(targetName(io, ref)),
- _offset(ref->offsetInAtom()), _addend(ref->addend()),
- _tag(ref->tag()) {
- _mappedKind.ns = ref->kindNamespace();
- _mappedKind.arch = ref->kindArch();
- _mappedKind.value = ref->kindValue();
- }
-
- const lld::Reference *denormalize(IO &io) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
- NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
- if (!_targetName.empty())
- _targetName = f->copyString(_targetName);
- DEBUG_WITH_TYPE("WriterYAML", llvm::dbgs()
- << "created Reference to name: '"
- << _targetName << "' ("
- << (const void *)_targetName.data()
- << ", " << _targetName.size() << ")\n");
- setKindNamespace(_mappedKind.ns);
- setKindArch(_mappedKind.arch);
- setKindValue(_mappedKind.value);
- return this;
- }
-
- void bind(const RefNameResolver &);
- static StringRef targetName(IO &io, const lld::Reference *ref);
-
- uint64_t offsetInAtom() const override { return _offset; }
- const lld::Atom *target() const override { return _target; }
- Addend addend() const override { return _addend; }
- void setAddend(Addend a) override { _addend = a; }
- void setTarget(const lld::Atom *a) override { _target = a; }
-
- const lld::Atom *_target;
- StringRef _targetName;
- uint32_t _offset;
- Addend _addend;
- RefKind _mappedKind;
- uint32_t _tag;
- };
-
- static void mapping(IO &io, const lld::Reference *&ref) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- MappingNormalizationHeap<NormalizedReference, const lld::Reference *> keys(
- io, ref, &info->_file->allocator());
-
- io.mapRequired("kind", keys->_mappedKind);
- io.mapOptional("offset", keys->_offset);
- io.mapOptional("target", keys->_targetName);
- io.mapOptional("addend", keys->_addend, (lld::Reference::Addend)0);
- io.mapOptional("tag", keys->_tag, 0u);
- }
-};
-
-// YAML conversion for const lld::DefinedAtom*
-template <> struct MappingTraits<const lld::DefinedAtom *> {
-
- class NormalizedAtom : public lld::DefinedAtom {
- public:
- NormalizedAtom(IO &io)
- : _file(fileFromContext(io)), _contentType(), _alignment(1) {
- static uint32_t ordinalCounter = 1;
- _ordinal = ordinalCounter++;
- }
-
- NormalizedAtom(IO &io, const lld::DefinedAtom *atom)
- : _file(fileFromContext(io)), _name(atom->name()),
- _scope(atom->scope()), _interpose(atom->interposable()),
- _merge(atom->merge()), _contentType(atom->contentType()),
- _alignment(atom->alignment()), _sectionChoice(atom->sectionChoice()),
- _deadStrip(atom->deadStrip()), _dynamicExport(atom->dynamicExport()),
- _codeModel(atom->codeModel()),
- _permissions(atom->permissions()), _size(atom->size()),
- _sectionName(atom->customSectionName()),
- _sectionSize(atom->sectionSize()) {
- for (const lld::Reference *r : *atom)
- _references.push_back(r);
- if (!atom->occupiesDiskSpace())
- return;
- ArrayRef<uint8_t> cont = atom->rawContent();
- _content.reserve(cont.size());
- for (uint8_t x : cont)
- _content.push_back(x);
- }
-
- ~NormalizedAtom() override = default;
-
- const lld::DefinedAtom *denormalize(IO &io) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
- NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
- if (!_name.empty())
- _name = f->copyString(_name);
- if (!_refName.empty())
- _refName = f->copyString(_refName);
- if (!_sectionName.empty())
- _sectionName = f->copyString(_sectionName);
- DEBUG_WITH_TYPE("WriterYAML",
- llvm::dbgs() << "created DefinedAtom named: '" << _name
- << "' (" << (const void *)_name.data()
- << ", " << _name.size() << ")\n");
- return this;
- }
-
- void bind(const RefNameResolver &);
-
- // Extract current File object from YAML I/O parsing context
- const lld::File &fileFromContext(IO &io) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- assert(info->_file != nullptr);
- return *info->_file;
- }
-
- const lld::File &file() const override { return _file; }
- StringRef name() const override { return _name; }
- uint64_t size() const override { return _size; }
- Scope scope() const override { return _scope; }
- Interposable interposable() const override { return _interpose; }
- Merge merge() const override { return _merge; }
- ContentType contentType() const override { return _contentType; }
- Alignment alignment() const override { return _alignment; }
- SectionChoice sectionChoice() const override { return _sectionChoice; }
- StringRef customSectionName() const override { return _sectionName; }
- uint64_t sectionSize() const override { return _sectionSize; }
- DeadStripKind deadStrip() const override { return _deadStrip; }
- DynamicExport dynamicExport() const override { return _dynamicExport; }
- CodeModel codeModel() const override { return _codeModel; }
- ContentPermissions permissions() const override { return _permissions; }
- ArrayRef<uint8_t> rawContent() const override {
- if (!occupiesDiskSpace())
- return ArrayRef<uint8_t>();
- return ArrayRef<uint8_t>(
- reinterpret_cast<const uint8_t *>(_content.data()), _content.size());
- }
-
- uint64_t ordinal() const override { return _ordinal; }
-
- reference_iterator begin() const override {
- uintptr_t index = 0;
- const void *it = reinterpret_cast<const void *>(index);
- return reference_iterator(*this, it);
- }
- reference_iterator end() const override {
- uintptr_t index = _references.size();
- const void *it = reinterpret_cast<const void *>(index);
- return reference_iterator(*this, it);
- }
- const lld::Reference *derefIterator(const void *it) const override {
- uintptr_t index = reinterpret_cast<uintptr_t>(it);
- assert(index < _references.size());
- return _references[index];
- }
- void incrementIterator(const void *&it) const override {
- uintptr_t index = reinterpret_cast<uintptr_t>(it);
- ++index;
- it = reinterpret_cast<const void *>(index);
- }
-
- void addReference(Reference::KindNamespace ns,
- Reference::KindArch arch,
- Reference::KindValue kindValue, uint64_t off,
- const Atom *target, Reference::Addend a) override {
- assert(target && "trying to create reference to nothing");
- auto node = new (file().allocator()) SimpleReference(ns, arch, kindValue,
- off, target, a);
- _references.push_back(node);
- }
-
- const lld::File &_file;
- StringRef _name;
- StringRef _refName;
- Scope _scope;
- Interposable _interpose;
- Merge _merge;
- ContentType _contentType;
- Alignment _alignment;
- SectionChoice _sectionChoice;
- DeadStripKind _deadStrip;
- DynamicExport _dynamicExport;
- CodeModel _codeModel;
- ContentPermissions _permissions;
- uint32_t _ordinal;
- std::vector<ImplicitHex8> _content;
- uint64_t _size;
- StringRef _sectionName;
- uint64_t _sectionSize;
- std::vector<const lld::Reference *> _references;
- };
-
- static void mapping(IO &io, const lld::DefinedAtom *&atom) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- MappingNormalizationHeap<NormalizedAtom, const lld::DefinedAtom *> keys(
- io, atom, &info->_file->allocator());
- if (io.outputting()) {
- // If writing YAML, check if atom needs a ref-name.
- typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
- assert(info != nullptr);
- NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
- assert(f);
- assert(f->_rnb);
- if (f->_rnb->hasRefName(atom)) {
- keys->_refName = f->_rnb->refName(atom);
- }
- }
-
- io.mapOptional("name", keys->_name, StringRef());
- io.mapOptional("ref-name", keys->_refName, StringRef());
- io.mapOptional("scope", keys->_scope,
- DefinedAtom::scopeTranslationUnit);
- io.mapOptional("type", keys->_contentType,
- DefinedAtom::typeCode);
- io.mapOptional("content", keys->_content);
- io.mapOptional("size", keys->_size, (uint64_t)keys->_content.size());
- io.mapOptional("interposable", keys->_interpose,
- DefinedAtom::interposeNo);
- io.mapOptional("merge", keys->_merge, DefinedAtom::mergeNo);
- io.mapOptional("alignment", keys->_alignment,
- DefinedAtom::Alignment(1));
- io.mapOptional("section-choice", keys->_sectionChoice,
- DefinedAtom::sectionBasedOnContent);
- io.mapOptional("section-name", keys->_sectionName, StringRef());
- io.mapOptional("section-size", keys->_sectionSize, (uint64_t)0);
- io.mapOptional("dead-strip", keys->_deadStrip,
- DefinedAtom::deadStripNormal);
- io.mapOptional("dynamic-export", keys->_dynamicExport,
- DefinedAtom::dynamicExportNormal);
- io.mapOptional("code-model", keys->_codeModel, DefinedAtom::codeNA);
- // default permissions based on content type
- io.mapOptional("permissions", keys->_permissions,
- DefinedAtom::permissions(
- keys->_contentType));
- io.mapOptional("references", keys->_references);
- }
-};
-
-template <> struct MappingTraits<lld::DefinedAtom *> {
- static void mapping(IO &io, lld::DefinedAtom *&atom) {
- const lld::DefinedAtom *atomPtr = atom;
- MappingTraits<const lld::DefinedAtom *>::mapping(io, atomPtr);
- atom = const_cast<lld::DefinedAtom *>(atomPtr);
- }
-};
-
-// YAML conversion for const lld::UndefinedAtom*
-template <> struct MappingTraits<const lld::UndefinedAtom *> {
- class NormalizedAtom : public lld::UndefinedAtom {
- public:
- NormalizedAtom(IO &io)
- : _file(fileFromContext(io)), _canBeNull(canBeNullNever) {}
-
- NormalizedAtom(IO &io, const lld::UndefinedAtom *atom)
- : _file(fileFromContext(io)), _name(atom->name()),
- _canBeNull(atom->canBeNull()) {}
-
- ~NormalizedAtom() override = default;
-
- const lld::UndefinedAtom *denormalize(IO &io) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
- NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
- if (!_name.empty())
- _name = f->copyString(_name);
-
- DEBUG_WITH_TYPE("WriterYAML",
- llvm::dbgs() << "created UndefinedAtom named: '" << _name
- << "' (" << (const void *)_name.data() << ", "
- << _name.size() << ")\n");
- return this;
- }
-
- // Extract current File object from YAML I/O parsing context
- const lld::File &fileFromContext(IO &io) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- assert(info->_file != nullptr);
- return *info->_file;
- }
-
- const lld::File &file() const override { return _file; }
- StringRef name() const override { return _name; }
- CanBeNull canBeNull() const override { return _canBeNull; }
-
- const lld::File &_file;
- StringRef _name;
- CanBeNull _canBeNull;
- };
-
- static void mapping(IO &io, const lld::UndefinedAtom *&atom) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- MappingNormalizationHeap<NormalizedAtom, const lld::UndefinedAtom *> keys(
- io, atom, &info->_file->allocator());
-
- io.mapRequired("name", keys->_name);
- io.mapOptional("can-be-null", keys->_canBeNull,
- lld::UndefinedAtom::canBeNullNever);
- }
-};
-
-template <> struct MappingTraits<lld::UndefinedAtom *> {
- static void mapping(IO &io, lld::UndefinedAtom *&atom) {
- const lld::UndefinedAtom *atomPtr = atom;
- MappingTraits<const lld::UndefinedAtom *>::mapping(io, atomPtr);
- atom = const_cast<lld::UndefinedAtom *>(atomPtr);
- }
-};
-
-// YAML conversion for const lld::SharedLibraryAtom*
-template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
- class NormalizedAtom : public lld::SharedLibraryAtom {
- public:
- NormalizedAtom(IO &io)
- : _file(fileFromContext(io)), _canBeNull(false),
- _type(Type::Unknown), _size(0) {}
-
- NormalizedAtom(IO &io, const lld::SharedLibraryAtom *atom)
- : _file(fileFromContext(io)), _name(atom->name()),
- _loadName(atom->loadName()), _canBeNull(atom->canBeNullAtRuntime()),
- _type(atom->type()), _size(atom->size()) {}
-
- ~NormalizedAtom() override = default;
-
- const lld::SharedLibraryAtom *denormalize(IO &io) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
- NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
- if (!_name.empty())
- _name = f->copyString(_name);
- if (!_loadName.empty())
- _loadName = f->copyString(_loadName);
-
- DEBUG_WITH_TYPE("WriterYAML",
- llvm::dbgs() << "created SharedLibraryAtom named: '"
- << _name << "' ("
- << (const void *)_name.data()
- << ", " << _name.size() << ")\n");
- return this;
- }
-
- // Extract current File object from YAML I/O parsing context
- const lld::File &fileFromContext(IO &io) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- assert(info->_file != nullptr);
- return *info->_file;
- }
-
- const lld::File &file() const override { return _file; }
- StringRef name() const override { return _name; }
- StringRef loadName() const override { return _loadName; }
- bool canBeNullAtRuntime() const override { return _canBeNull; }
- Type type() const override { return _type; }
- uint64_t size() const override { return _size; }
-
- const lld::File &_file;
- StringRef _name;
- StringRef _loadName;
- ShlibCanBeNull _canBeNull;
- Type _type;
- uint64_t _size;
- };
-
- static void mapping(IO &io, const lld::SharedLibraryAtom *&atom) {
-
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- MappingNormalizationHeap<NormalizedAtom, const lld::SharedLibraryAtom *>
- keys(io, atom, &info->_file->allocator());
-
- io.mapRequired("name", keys->_name);
- io.mapOptional("load-name", keys->_loadName);
- io.mapOptional("can-be-null", keys->_canBeNull, (ShlibCanBeNull) false);
- io.mapOptional("type", keys->_type, SharedLibraryAtom::Type::Code);
- io.mapOptional("size", keys->_size, uint64_t(0));
- }
-};
-
-template <> struct MappingTraits<lld::SharedLibraryAtom *> {
- static void mapping(IO &io, lld::SharedLibraryAtom *&atom) {
- const lld::SharedLibraryAtom *atomPtr = atom;
- MappingTraits<const lld::SharedLibraryAtom *>::mapping(io, atomPtr);
- atom = const_cast<lld::SharedLibraryAtom *>(atomPtr);
- }
-};
-
-// YAML conversion for const lld::AbsoluteAtom*
-template <> struct MappingTraits<const lld::AbsoluteAtom *> {
- class NormalizedAtom : public lld::AbsoluteAtom {
- public:
- NormalizedAtom(IO &io)
- : _file(fileFromContext(io)), _scope(), _value(0) {}
-
- NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom)
- : _file(fileFromContext(io)), _name(atom->name()),
- _scope(atom->scope()), _value(atom->value()) {}
-
- ~NormalizedAtom() override = default;
-
- const lld::AbsoluteAtom *denormalize(IO &io) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
- NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
- if (!_name.empty())
- _name = f->copyString(_name);
-
- DEBUG_WITH_TYPE("WriterYAML",
- llvm::dbgs() << "created AbsoluteAtom named: '" << _name
- << "' (" << (const void *)_name.data()
- << ", " << _name.size() << ")\n");
- return this;
- }
-
- // Extract current File object from YAML I/O parsing context
- const lld::File &fileFromContext(IO &io) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- assert(info->_file != nullptr);
- return *info->_file;
- }
-
- const lld::File &file() const override { return _file; }
- StringRef name() const override { return _name; }
- uint64_t value() const override { return _value; }
- Scope scope() const override { return _scope; }
-
- const lld::File &_file;
- StringRef _name;
- StringRef _refName;
- Scope _scope;
- Hex64 _value;
- };
-
- static void mapping(IO &io, const lld::AbsoluteAtom *&atom) {
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- MappingNormalizationHeap<NormalizedAtom, const lld::AbsoluteAtom *> keys(
- io, atom, &info->_file->allocator());
-
- if (io.outputting()) {
- typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
- assert(f);
- assert(f->_rnb);
- if (f->_rnb->hasRefName(atom)) {
- keys->_refName = f->_rnb->refName(atom);
- }
- }
-
- io.mapRequired("name", keys->_name);
- io.mapOptional("ref-name", keys->_refName, StringRef());
- io.mapOptional("scope", keys->_scope);
- io.mapRequired("value", keys->_value);
- }
-};
-
-template <> struct MappingTraits<lld::AbsoluteAtom *> {
- static void mapping(IO &io, lld::AbsoluteAtom *&atom) {
- const lld::AbsoluteAtom *atomPtr = atom;
- MappingTraits<const lld::AbsoluteAtom *>::mapping(io, atomPtr);
- atom = const_cast<lld::AbsoluteAtom *>(atomPtr);
- }
-};
-
-} // end namespace llvm
-} // end namespace yaml
-
-RefNameResolver::RefNameResolver(const lld::File *file, IO &io) : _io(io) {
- typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
- NormalizedAtom;
- for (const lld::DefinedAtom *a : file->defined()) {
- const auto *na = (const NormalizedAtom *)a;
- if (!na->_refName.empty())
- add(na->_refName, a);
- else if (!na->_name.empty())
- add(na->_name, a);
- }
-
- for (const lld::UndefinedAtom *a : file->undefined())
- add(a->name(), a);
-
- for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
- add(a->name(), a);
-
- typedef MappingTraits<const lld::AbsoluteAtom *>::NormalizedAtom NormAbsAtom;
- for (const lld::AbsoluteAtom *a : file->absolute()) {
- const auto *na = (const NormAbsAtom *)a;
- if (na->_refName.empty())
- add(na->_name, a);
- else
- add(na->_refName, a);
- }
-}
-
-inline const lld::File *
-MappingTraits<const lld::File *>::NormalizedFile::denormalize(IO &io) {
- typedef MappingTraits<const lld::DefinedAtom *>::NormalizedAtom
- NormalizedAtom;
-
- RefNameResolver nameResolver(this, io);
- // Now that all atoms are parsed, references can be bound.
- for (const lld::DefinedAtom *a : this->defined()) {
- auto *normAtom = (NormalizedAtom *)const_cast<DefinedAtom *>(a);
- normAtom->bind(nameResolver);
- }
-
- return this;
-}
-
-inline void MappingTraits<const lld::DefinedAtom *>::NormalizedAtom::bind(
- const RefNameResolver &resolver) {
- typedef MappingTraits<const lld::Reference *>::NormalizedReference
- NormalizedReference;
- for (const lld::Reference *ref : _references) {
- auto *normRef = (NormalizedReference *)const_cast<Reference *>(ref);
- normRef->bind(resolver);
- }
-}
-
-inline void MappingTraits<const lld::Reference *>::NormalizedReference::bind(
- const RefNameResolver &resolver) {
- _target = resolver.lookup(_targetName);
-}
-
-inline StringRef
-MappingTraits<const lld::Reference *>::NormalizedReference::targetName(
- IO &io, const lld::Reference *ref) {
- if (ref->target() == nullptr)
- return StringRef();
- YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
- assert(info != nullptr);
- typedef MappingTraits<const lld::File *>::NormalizedFile NormalizedFile;
- NormalizedFile *f = reinterpret_cast<NormalizedFile *>(info->_file);
- RefNameBuilder &rnb = *f->_rnb;
- if (rnb.hasRefName(ref->target()))
- return rnb.refName(ref->target());
- return ref->target()->name();
-}
-
-namespace lld {
-namespace yaml {
-
-class Writer : public lld::Writer {
-public:
- Writer(const LinkingContext &context) : _ctx(context) {}
-
- llvm::Error writeFile(const lld::File &file, StringRef outPath) override {
- // Create stream to path.
- std::error_code ec;
- llvm::raw_fd_ostream out(outPath, ec, llvm::sys::fs::OF_TextWithCRLF);
- if (ec)
- return llvm::errorCodeToError(ec);
-
- // Create yaml Output writer, using yaml options for context.
- YamlContext yamlContext;
- yamlContext._ctx = &_ctx;
- yamlContext._registry = &_ctx.registry();
- llvm::yaml::Output yout(out, &yamlContext);
-
- // Write yaml output.
- const lld::File *fileRef = &file;
- yout << fileRef;
-
- return llvm::Error::success();
- }
-
-private:
- const LinkingContext &_ctx;
-};
-
-} // end namespace yaml
-
-namespace {
-
-/// Handles !native tagged yaml documents.
-class NativeYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
- bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
- if (io.mapTag("!native")) {
- MappingTraits<const lld::File *>::mappingAtoms(io, file);
- return true;
- }
- return false;
- }
-};
-
-/// Handles !archive tagged yaml documents.
-class ArchiveYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
- bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
- if (io.mapTag("!archive")) {
- MappingTraits<const lld::File *>::mappingArchive(io, file);
- return true;
- }
- return false;
- }
-};
-
-class YAMLReader : public Reader {
-public:
- YAMLReader(const Registry ®istry) : _registry(registry) {}
-
- bool canParse(file_magic magic, MemoryBufferRef mb) const override {
- StringRef name = mb.getBufferIdentifier();
- return name.endswith(".objtxt") || name.endswith(".yaml");
- }
-
- ErrorOr<std::unique_ptr<File>>
- loadFile(std::unique_ptr<MemoryBuffer> mb,
- const class Registry &) const override {
- // Create YAML Input Reader.
- YamlContext yamlContext;
- yamlContext._registry = &_registry;
- yamlContext._path = mb->getBufferIdentifier();
- llvm::yaml::Input yin(mb->getBuffer(), &yamlContext);
-
- // Fill vector with File objects created by parsing yaml.
- std::vector<const lld::File *> createdFiles;
- yin >> createdFiles;
- assert(createdFiles.size() == 1);
-
- // Error out now if there were parsing errors.
- if (yin.error())
- return make_error_code(lld::YamlReaderError::illegal_value);
-
- std::shared_ptr<MemoryBuffer> smb(mb.release());
- const File *file = createdFiles[0];
- // Note: loadFile() should return vector of *const* File
- File *f = const_cast<File *>(file);
- f->setLastError(std::error_code());
- f->setSharedMemoryBuffer(smb);
- return std::unique_ptr<File>(f);
- }
-
-private:
- const Registry &_registry;
-};
-
-} // end anonymous namespace
-
-void Registry::addSupportYamlFiles() {
- add(std::unique_ptr<Reader>(new YAMLReader(*this)));
- add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
- new NativeYamlIOTaggedDocumentHandler()));
- add(std::unique_ptr<YamlIOTaggedDocumentHandler>(
- new ArchiveYamlIOTaggedDocumentHandler()));
-}
-
-std::unique_ptr<Writer> createWriterYAML(const LinkingContext &context) {
- return std::unique_ptr<Writer>(new lld::yaml::Writer(context));
-}
-
-} // end namespace lld
)
endif()
-if (LLVM_INCLUDE_TESTS)
- list(APPEND LLD_TEST_DEPS LLDUnitTests)
-endif()
-
add_lit_testsuite(check-lld "Running lld test suite"
${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${LLD_TEST_DEPS}
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
- address: 0
- content: [ 0xC3 ]
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ ]
- value: 0
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ ]
-install-name: /usr/lib/libSystem.B.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55 ]
-
-global-symbols:
- - name: dyld_stub_binder
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -lto_library %t -print-atoms -r %s 2>&1 | FileCheck %s
-#
-# Test that the -lto_library option does not result in an error.
-#
-
-# CHECK-NOT: -lto_library
-
---- !native
-defined-atoms:
- - name: _foo
-...
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -objc_gc %s 2>&1 | FileCheck %s
-#
-# Test that the -objc_gc is rejected.
-#
-
-# CHECK: error: -objc_gc is not supported
-
---- !native
-defined-atoms:
- - name: _main
- type: code
- scope: global
- content: [ 0x90 ]
-
-...
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -objc_gc_compaction %s 2>&1 | FileCheck %s
-#
-# Test that the -objc_gc_compaction is rejected.
-#
-
-# CHECK: error: -objc_gc_compaction is not supported
-
---- !native
-defined-atoms:
- - name: _main
- type: code
- scope: global
- content: [ 0x90 ]
-
-...
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -objc_gc_only %s 2>&1 | FileCheck %s
-#
-# Test that the -objc_gc_only is rejected.
-#
-
-# CHECK: error: -objc_gc_only is not supported
-
---- !native
-defined-atoms:
- - name: _main
- type: code
- scope: global
- content: [ 0x90 ]
-
-...
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s \
-# RUN: %p/Inputs/native-and-mach-o.objtxt \
-# RUN: %p/Inputs/native-and-mach-o2.objtxt -o %t && \
-# RUN: llvm-nm %t | FileCheck %s
-#
-# Test a mix of atoms and mach-o both encoded in yaml
-#
-
---- !native
-defined-atoms:
- - name: _main
- type: code
- scope: global
- content: [ 55, 48, 89, E5, 30, C0, E8, 00,
- 00, 00, 00, 31, C0, 5D, C3 ]
- references:
- - offset: 7
- kind: branch32
- target: _foo
-
-undefined-atoms:
- - name: _foo
-
-...
-
-# CHECK: {{[0-9a-f]+}} T _foo
-# CHECK: {{[0-9a-f]+}} T _main
+++ /dev/null
-# -*- Python -*-
-
-
-#
-# Dump out Xcode binary dependency file.
-#
-
-import sys
-
-f = open(sys.argv[1], "rb")
-byte = f.read(1)
-while byte != b'':
- if byte == b'\000':
- sys.stdout.write("linker-vers: ")
- elif byte == b'\020':
- sys.stdout.write("input-file: ")
- elif byte == b'\021':
- sys.stdout.write("not-found: ")
- elif byte == b'\100':
- sys.stdout.write("output-file: ")
- byte = f.read(1)
- while byte != b'\000':
- if byte != b'\012':
- sys.stdout.write(byte.decode("ascii"))
- byte = f.read(1)
- sys.stdout.write("\n")
- byte = f.read(1)
-
-f.close()
-
+++ /dev/null
---- !tapi-tbd-v3
-archs: [ x86_64 ]
-uuids: [ 'x86_64: 00000000-0000-0000-0000-000000000000' ]
-platform: macosx
-install-name: '/usr/lib/libSystem.B.dylib'
-current-version: 0001.001.1
-exports:
- - archs: [ 'x86_64' ]
- re-exports: [ '/usr/lib/system/libdyld.dylib',
- '/usr/lib/system/libsystem_c.dylib',
- '/usr/lib/system/libsystem_m.dylib' ]
---- !tapi-tbd-v3
-archs: [ x86_64 ]
-uuids: [ 'x86_64: 00000000-0000-0000-0000-000000000001' ]
-platform: macosx
-install-name: '/usr/lib/system/libdyld.dylib'
-current-version: 0001.001.1
-parent-umbrella: System
-exports:
- - archs: [ 'x86_64' ]
- symbols: [ dyld_stub_binder ]
---- !tapi-tbd-v3
-archs: [ x86_64 ]
-uuids: [ 'x86_64: 00000000-0000-0000-0000-000000000002' ]
-platform: macosx
-install-name: '/usr/lib/system/libsystem_c.dylib'
-current-version: 0001.001.1
-parent-umbrella: System
-exports:
- - archs: [ 'x86_64' ]
- symbols: [ ]
---- !tapi-tbd-v3
-archs: [ x86_64 ]
-uuids: [ 'x86_64: 00000000-0000-0000-0000-000000000003' ]
-platform: macosx
-install-name: '/usr/lib/system/libsystem_m.dylib'
-current-version: 0001.001.1
-parent-umbrella: System
-exports:
- - archs: [ 'x86_64' ]
- symbols: [ ___nan ]
-...
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: dyld_stub_binder
+++ /dev/null
---- !mach-o
-arch: armv7
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0xFE, 0xFF, 0xFF, 0xEB, 0x02, 0x00, 0x00, 0xFA,
- 0xFC, 0xFF, 0xFF, 0xEB, 0xFB, 0xFF, 0xFF, 0xFA,
- 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1 ]
- relocations:
- - offset: 0x0000000C
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x00000008
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000004
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x0000000000000018
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000004
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 3
-local-symbols:
- - name: _d2
- type: N_SECT
- sect: 2
- value: 0x0000000000000018
-global-symbols:
- - name: _a1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _a2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000014
-undefined-symbols:
- - name: _t1
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _t2
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
+++ /dev/null
---- !mach-o
-arch: armv7
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x00, 0xBF, 0xFF, 0xF7, 0xFE, 0xEF, 0xFF, 0xF7,
- 0xFB, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3,
- 0xFA, 0xFF, 0xFF, 0xFA, 0xF9, 0xFF, 0xFF, 0xEA ]
- relocations:
- - offset: 0x00000014
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000010
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000006
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x00000002
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
-global-symbols:
- - name: _a2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000C
- - name: _t2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000000
-undefined-symbols:
- - name: _a1
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _t1
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
+++ /dev/null
-#
-# For use by test cases that create dynamic output types which may needs stubs
-# and therefore will need a dylib definition of dyld_stub_binder.
-#
-
---- !mach-o
-arch: arm64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: dyld_stub_binder
-
-...
+++ /dev/null
-#
-# For use by test cases that create dynamic output types which may needs stubs
-# and therefore will need a dylib definition of dyld_stub_binder.
-#
-
---- !mach-o
-arch: armv7
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: dyld_stub_binder
-
-...
+++ /dev/null
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xC3 ]
-global-symbols:
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __objc_methname
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000000
- content: [ 0x61, 0x62, 0x63, 0x00 ]
- - segment: __TEXT
- section: __objc_classname
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000006
- content: [ 0x61, 0x62, 0x63, 0x00 ]
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x000000000000000A
- content: [ 0x61, 0x62, 0x63, 0x00 ]
+++ /dev/null
-#
-# For use with exported_symbols_list.yaml
-#
-_foo
-_b
-
+++ /dev/null
-/foo/bar/a.o
-/foo/bar/b.o
-/foo/x.a
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x0D, 0x00,
- 0x00, 0x00, 0x00, 0x48, 0x8B, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0x8B, 0x00, 0x03, 0x01, 0x48, 0x8B,
- 0x0D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x5D,
- 0xC3 ]
- relocations:
- - offset: 0x00000019
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x0000000E
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000007
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _bar
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _zazzle
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libfoobar.dylib
-exports:
- - name: _bar
- - name: _zazzle
- - name: _foo
- - name: _aaa
- - name: _fff
- - name: _zzz
+++ /dev/null
---- !mach-o
-arch: arm64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _fprintf
- - name: ___stdoutp
- - name: dyld_stub_binder
+++ /dev/null
---- !mach-o
-arch: armv6
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _printf
- - name: dyld_stub_binder
+++ /dev/null
---- !mach-o
-arch: armv7
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _printf
- - name: dyld_stub_binder
+++ /dev/null
---- !mach-o
-arch: x86
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _printf
- - name: dyld_stub_binder
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _fprintf
- - name: dyld_stub_binder
- - name: ___stdoutp
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _open
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libfoo.dylib
-compat-version: 2.0
-current-version: 3.4
-exports:
- - name: _foo
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libbaz.dylib
-compat-version: 3.0
-current-version: 4.5
-exports:
- - name: _baz
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libbar.dylib
-compat-version: 1.0
-current-version: 2.3
-exports:
- - name: _bar
+++ /dev/null
-
-# This object file has no version min and so will prevent any -r link from emitting
-# a version min.
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _main2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
+++ /dev/null
-
-# input file for order_file-basic.yaml
-
-_func2
-libfoo.a(foo.o):_foo # tests file specific ordering within archive
-i386:_func3 # wrong arch, so ignored
-armv7:_func3 # wrong arch, so ignored
-_func1
-_notfound # unknown symbol silently ignored
-_data3 # data symbols should be orderable
-
+++ /dev/null
-bar/a.o
-bar/b.o
-x.a
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ MH_TWOLEVEL ]
-install-name: /junk/libfoo.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000F9A
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3 ]
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000F9A
-dependents:
- - path: /junk/libbar.dylib
- kind: LC_REEXPORT_DYLIB
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ MH_TWOLEVEL ]
-install-name: /junk/libbar.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000F9A
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3 ]
-global-symbols:
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000F9A
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ MH_TWOLEVEL ]
-install-name: /usr/lib/libSystem.B.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55 ]
-
-global-symbols:
- - name: dyld_stub_binder
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -r %s %p/Inputs/hello-world-x86_64.yaml 2>&1 | FileCheck %s
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_imageinfo
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 ]
-...
+++ /dev/null
---- !mach-o
-arch: arm64
-file-type: MH_DYLIB
-install-name: /usr/lib/libc++.dylib
-exports:
- - name: __Unwind_Resume
- - name: __ZTIl
- - name: __ZTIi
- - name: ___cxa_end_catch
- - name: ___cxa_begin_catch
- - name: ___cxa_allocate_exception
- - name: ___cxa_throw
- - name: ___gxx_personality_v0
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00,
- 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00,
- 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xE9, 0x00,
- 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _myGlobal
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xCC, 0xC3, 0x90, 0xC3, 0x90, 0x90, 0xC3, 0x90,
- 0x90, 0x90, 0xC3, 0x90, 0x90, 0x90, 0x90, 0xC3,
- 0x31, 0xC0, 0xC3 ]
-local-symbols:
- - name: _myStatic
- type: N_SECT
- sect: 1
- value: 0x000000000000000B
- - name: _myVariablePreviouslyKnownAsPrivateExtern
- type: N_SECT
- scope: [ N_PEXT ]
- sect: 1
- desc: [ N_SYMBOL_RESOLVER ]
- value: 0x0000000000000011
-global-symbols:
- - name: _myGlobal
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myGlobalWeak
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_WEAK_DEF ]
- value: 0x0000000000000002
- - name: _myHidden
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000004
- - name: _myHiddenWeak
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- desc: [ N_WEAK_DEF ]
- value: 0x0000000000000007
- - name: _myResolver
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_SYMBOL_RESOLVER ]
- value: 0x0000000000000010
-
-install-name: libspecial.dylib
+++ /dev/null
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ ]
-install-name: /usr/lib/libSystem.B.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55 ]
-
-global-symbols:
- - name: dyld_stub_binder
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -r %s 2> %t.err
-# RUN: FileCheck %s < %t.err
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xC3 ]
-
-global-symbols:
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
+++ /dev/null
-#
-# For use by test cases that create dynamic output types which may needs stubs
-# and therefore will need a dylib definition of dyld_stub_binder.
-#
-
---- !mach-o
-arch: x86
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: dyld_stub_binder
-
-...
+++ /dev/null
-#
-# For use by test cases that create dynamic output types which may needs stubs
-# and therefore will need a dylib definition of dyld_stub_binder.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: dyld_stub_binder
-
-...
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s \
-# RUN: %p/Inputs/PIE.yaml -o %t && \
-# RUN: llvm-objdump --macho --private-headers %t | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s \
-# RUN: %p/Inputs/PIE.yaml -pie -o %t\
-# RUN: && llvm-objdump --macho --private-headers %t | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s \
-# RUN: %p/Inputs/PIE.yaml -no_pie -o %t\
-# RUN: && llvm-objdump --macho --private-headers %t \
-# RUN: | FileCheck --check-prefix=CHECK_NO_PIE %s
-#
-# Test various PIE options.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xC3 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
-...
-
-# CHECK: MH_MAGIC_64 {{[0-9a-zA-Z _]+}} TWOLEVEL PIE
-# CHECK_NO_PIE-NOT: MH_MAGIC_64 {{[0-9a-zA-Z _]+}} TWOLEVEL PIE
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -o %t -print_atoms | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -r %t -o %t2 -print_atoms | FileCheck %s
-#
-# Test that alignment info round trips through -r
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 16
- address: 0x0000000000000000
- content: [ 0x90, 0x90, 0x90, 0xC3, 0xC3, 0xC3 ]
-local-symbols:
- - name: _f1
- type: N_SECT
- sect: 1
- value: 0x0000000000000003
- - name: _f2
- type: N_SECT
- sect: 1
- value: 0x0000000000000004
- - name: _f3
- type: N_SECT
- sect: 1
- value: 0x0000000000000005
-...
-
-# CHECK: defined-atoms:
-# CHECK: - content: [ 90, 90, 90 ]
-# CHECK: alignment: 16
-# CHECK: - name: _f1
-# CHECK: content: [ C3 ]
-# CHECK: alignment: 3 mod 16
-# CHECK: - name: _f2
-# CHECK: content: [ C3 ]
-# CHECK: alignment: 4 mod 16
-# CHECK: - name: _f3
-# CHECK: content: [ C3 ]
-# CHECK: alignment: 5 mod 16
+++ /dev/null
-# REQUIRES: arm
-# RUN: ld64.lld.darwinold -arch armv7 -r -print_atoms %s -o %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch armv7 -dylib -print_atoms %t -o %t2 \
-# RUN: %p/Inputs/armv7/libSystem.yaml -sectalign __TEXT __text 0x1000 | FileCheck %s
-# RUN: llvm-objdump -d --macho --no-symbolic-operands %t2 | FileCheck --check-prefix=CODE %s
-#
-# Test thumb and arm branches round trip through -r.
-# Test movw/movt pairs have low bit set properly for thumb vs arm.
-#
-#
-
---- !mach-o
-arch: armv7
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x40, 0xF2, 0x25, 0x00, 0xC0, 0xF2, 0x00, 0x00,
- 0x40, 0xF2, 0x01, 0x01, 0xC0, 0xF2, 0x00, 0x01,
- 0x40, 0xF2, 0x4E, 0x02, 0xC0, 0xF2, 0x00, 0x02,
- 0x40, 0xF2, 0x2A, 0x03, 0xC0, 0xF2, 0x00, 0x03,
- 0x78, 0x44, 0x70, 0x47, 0x70, 0x47, 0x25, 0x00,
- 0x00, 0xE3, 0x00, 0x00, 0x40, 0xE3, 0xD7, 0x1F,
- 0x0F, 0xE3, 0xFF, 0x1F, 0x4F, 0xE3, 0x4E, 0x20,
- 0x00, 0xE3, 0x00, 0x20, 0x40, 0xE3, 0x00, 0x30,
- 0x00, 0xE3, 0x00, 0x30, 0x40, 0xE3, 0x0F, 0x00,
- 0x80, 0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF,
- 0x2F, 0xE1 ]
- relocations:
- - offset: 0x00000042
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 1
- pc-rel: false
- value: 0x0000004E
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- value: 0x00000046
- - offset: 0x0000003E
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 0
- pc-rel: false
- value: 0x0000004E
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- value: 0x00000046
- - offset: 0x0000003A
- type: ARM_RELOC_HALF
- length: 1
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x0000004E
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000036
- type: ARM_RELOC_HALF
- length: 0
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000032
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 1
- pc-rel: false
- value: 0x00000024
- - offset: 0x0000FFD6
- scattered: true
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- value: 0x00000046
- - offset: 0x0000002E
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 0
- pc-rel: false
- value: 0x00000024
- - offset: 0x0000FFFF
- scattered: true
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- value: 0x00000046
- - offset: 0x0000002A
- type: ARM_RELOC_HALF
- length: 1
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000025
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000026
- type: ARM_RELOC_HALF
- length: 0
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x0000001C
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 3
- pc-rel: false
- value: 0x0000004E
- - offset: 0x0000002A
- scattered: true
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- value: 0x00000020
- - offset: 0x00000018
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x0000004E
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000020
- - offset: 0x00000014
- type: ARM_RELOC_HALF
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x0000004E
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000010
- type: ARM_RELOC_HALF
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x0000000C
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 3
- pc-rel: false
- value: 0x00000024
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- value: 0x00000020
- - offset: 0x00000008
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000024
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000020
- - offset: 0x00000004
- type: ARM_RELOC_HALF
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000025
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000000
- type: ARM_RELOC_HALF
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- extern: false
- symbol: 16777215
-local-symbols:
- - name: _t1
- type: N_SECT
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000000
- - name: _t2
- type: N_SECT
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000024
- - name: _a2
- type: N_SECT
- sect: 1
- value: 0x000000000000004E
- - name: _a1
- type: N_SECT
- sect: 1
- value: 0x0000000000000026
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: _t1
-# CHECK: references:
-# CHECK: - kind: modeThumbCode
-# CHECK: offset: 0
-# CHECK: target: _t1
-# CHECK: - kind: thumb_movw
-# CHECK: offset: 0
-# CHECK: target: _t2
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movt
-# CHECK: offset: 4
-# CHECK: target: _t2
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movw_funcRel
-# CHECK: offset: 8
-# CHECK: target: _t2
-# CHECK: addend: -36
-# CHECK: - kind: thumb_movt_funcRel
-# CHECK: offset: 12
-# CHECK: target: _t2
-# CHECK: addend: -36
-# CHECK: - kind: thumb_movw
-# CHECK: offset: 16
-# CHECK: target: _a2
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movt
-# CHECK: offset: 20
-# CHECK: target: _a2
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movw_funcRel
-# CHECK: offset: 24
-# CHECK: target: _a2
-# CHECK: addend: -36
-# CHECK: - kind: thumb_movt_funcRel
-# CHECK: offset: 28
-# CHECK: target: _a2
-# CHECK: addend: -36
-# CHECK: - name: _t2
-# CHECK: references:
-# CHECK: - kind: modeThumbCode
-# CHECK: offset: 0
-# CHECK: target: _t2
-# CHECK: - name: _a1
-# CHECK: references:
-# CHECK: - kind: arm_movw
-# CHECK: offset: 0
-# CHECK: target: _t2
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_movt
-# CHECK: offset: 4
-# CHECK: target: _t2
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_movw_funcRel
-# CHECK: offset: 8
-# CHECK: target: _t2
-# CHECK: addend: -40
-# CHECK: - kind: arm_movt_funcRel
-# CHECK: offset: 12
-# CHECK: target: _t2
-# CHECK: addend: -40
-# CHECK: - kind: arm_movw
-# CHECK: offset: 16
-# CHECK: target: _a2
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_movt
-# CHECK: offset: 20
-# CHECK: target: _a2
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_movw_funcRel
-# CHECK: offset: 24
-# CHECK: target: _a2
-# CHECK: addend: -40
-# CHECK: - kind: arm_movt_funcRel
-# CHECK: offset: 28
-# CHECK: target: _a2
-# CHECK: addend: -40
-# CHECK: - name: _a2
-
-
-# CODE: _t1:
-# CODE-NEXT: movw r0, #4133
-# CODE-NEXT: movt r0, #0
-# CODE-NEXT: movw r1, #1
-# CODE-NEXT: movt r1, #0
-# CODE-NEXT: movw r2, #4174
-# CODE-NEXT: movt r2, #0
-# CODE-NEXT: movw r3, #42
-# CODE-NEXT: movt r3, #0
-
-
-# CODE: _a1:
-# CODE-NEXT: movw r0, #4133
-# CODE-NEXT: movt r0, #0
-# CODE-NEXT: movw r1, #65495
-# CODE-NEXT: movt r1, #65535
-# CODE-NEXT: movw r2, #4174
-# CODE-NEXT: movt r2, #0
-# CODE-NEXT: movw r3, #0
-# CODE-NEXT: movt r3, #0
-
-
-
-# .syntax unified
-# .align 2
-#
-# .code 16
-# .thumb_func _t1
-#_t1:
-# movw r0, :lower16:(_t2)
-# movt r0, :upper16:(_t2)
-# movw r1, :lower16:(_t2-(L0+4))
-# movt r1, :upper16:(_t2-(L0+4))
-# movw r2, :lower16:(_a2)
-# movt r2, :upper16:(_a2)
-# movw r3, :lower16:(_a2-(L0+4))
-# movt r3, :upper16:(_a2-(L0+4))
-#L0:
-# add r0, pc
-# bx lr
-#
-#
-# .code 16
-# .thumb_func _t2
-#_t2:
-# bx lr
-#
-#
-#
-# .code 32
-#_a1:
-# movw r0, :lower16:(_t2)
-# movt r0, :upper16:(_t2)
-# movw r1, :lower16:(_t2-(L1+8))
-# movt r1, :upper16:(_t2-(L1+8))
-# movw r2, :lower16:(_a2)
-# movt r2, :upper16:(_a2)
-# movw r3, :lower16:(_a2-(L1+8))
-# movt r3, :upper16:(_a2-(L1+8))
-#L1:
-# add r0, pc
-# bx lr
-#
-#_a2:
-# bx lr
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch armv7 -r -print_atoms %s \
-# RUN: %p/Inputs/arm-interworking.yaml -o %t | FileCheck %s \
-# RUN: && ld64.lld.darwinold -arch armv7 -dylib -print_atoms \
-# RUN: %p/Inputs/armv7/libSystem.yaml %t -o %t2 | FileCheck %s \
-# RUN: && llvm-readobj -S --section-data %t2 | FileCheck -check-prefix=CODE %s
-#
-# Test thumb and arm branches round trip through -r.
-# Test bl/blx instructions are fixed up properly.
-#
-#
-
---- !mach-o
-arch: armv7
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0xFF, 0xF7, 0xFE, 0xFF, 0xC0, 0x46, 0xFF, 0xF7,
- 0xFC, 0xEF, 0xC0, 0x46, 0xFF, 0xF7, 0xF8, 0xEF,
- 0xFF, 0xF7, 0xF6, 0xFF, 0xC0, 0x46, 0xFF, 0xF7,
- 0xF3, 0xFF, 0xC0, 0x46, 0x00, 0xF0, 0x06, 0xE8,
- 0xC0, 0x46, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xF0,
- 0x02, 0xF8, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47 ]
- relocations:
- - offset: 0x00000026
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x00000022
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x0000001C
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x00000016
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x00000010
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x0000000C
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 5
- - offset: 0x00000006
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 5
- - offset: 0x00000000
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x0000000000000030
- content: [ 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000004
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000000
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
-local-symbols:
- - name: _t3
- type: N_SECT
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x000000000000002E
- - name: _d1
- type: N_SECT
- sect: 2
- value: 0x0000000000000030
-global-symbols:
- - name: _t1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000000
- - name: _t2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x000000000000002C
-undefined-symbols:
- - name: _a1
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _a2
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-
-# CHECK: defined-atoms:
-# CHECK: - name: _d1
-# CHECK: type: data
-# CHECK: references:
-# CHECK: - kind: pointer32
-# CHECK: offset: 0
-# CHECK: target: _t2
-# CHECK: - kind: pointer32
-# CHECK: offset: 4
-# CHECK: target: _a1
-# CHECK: - name: _d2
-# CHECK: type: data
-# CHECK: references:
-# CHECK: - kind: pointer32
-# CHECK: offset: 0
-# CHECK: target: _t1
-# CHECK: - kind: pointer32
-# CHECK: offset: 4
-# CHECK: target: _a1
-# CHECK: - name: _t1
-# CHECK: scope: global
-# CHECK: references:
-# CHECK: - kind: modeThumbCode
-# CHECK: offset: 0
-# CHECK: target: _t1
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 0
-# CHECK: target: _a1
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 6
-# CHECK: target: _a2
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 12
-# CHECK: target: _a2
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 16
-# CHECK: target: _t1
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 22
-# CHECK: target: _t1
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 28
-# CHECK: target: _t2
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 34
-# CHECK: target: _t2
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 38
-# CHECK: target: _t3
-# CHECK: - name: _t2
-# CHECK: scope: global
-# CHECK: content: [ 70, 47 ]
-# CHECK: references:
-# CHECK: - kind: modeThumbCode
-# CHECK: offset: 0
-# CHECK: target: _t2
-# CHECK: - name: _t3
-# CHECK: content: [ 70, 47 ]
-# CHECK: references:
-# CHECK: - kind: modeThumbCode
-# CHECK: offset: 0
-# CHECK: target: _t3
-# CHECK: - name: _a1
-# CHECK: scope: global
-# CHECK: references:
-# CHECK: - kind: arm_bl24
-# CHECK: offset: 0
-# CHECK: target: _a1
-# CHECK: - kind: arm_bl24
-# CHECK: offset: 4
-# CHECK: target: _a2
-# CHECK: - kind: arm_bl24
-# CHECK: offset: 8
-# CHECK: target: _t1
-# CHECK: - kind: arm_bl24
-# CHECK: offset: 12
-# CHECK: target: _t2
-# CHECK: - name: _a2
-# CHECK: scope: global
-
-# CODE: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
-# CODE: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
-# CODE: SectionData (
-# CODE: 0000: 00F016E8 C04600F0 1EE8C046 00F01AE8
-# CODE: 0010: FFF7F6FF C046FFF7 F3FFC046 00F006F8
-# CODE: 0020: C04600F0 03F800F0 02F87047 70477047
-# CODE: 0030: FEFFFFEB 020000EB F0FFFFFA FAFFFFFA
-# CODE: 0040: 1EFF2FE1 1EFF2FE1
-# CODE: )
-
-# CODE: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00)
-# CODE: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00)
-# CODE: SectionData (
-# CODE: 0000: E50F0000 E80F0000 B90F0000 E80F0000
-# CODE: )
-
-# When we get a good mach-o disassembler the above __text section content check can be change to be symbolic.
-# Verify the low (thumb) bit is set on the first and third pointers but not the second and fourth.
-
-
-
-# Input file one:
-#
-# .align 2
-# .code 16
-# .globl _t1
-# .thumb_func _t1
-#_t1:
-# bl _a1
-# nop
-# blx _a2
-# nop
-# blx _a2
-# bl _t1
-# nop
-# bl _t1
-# nop
-# blx _t2
-# nop
-# blx _t2
-# bx lr
-#
-# .globl _t2
-# .thumb_func _t2
-#_t2:
-# bx lr
-#
-# .data
-#_d1: .long _t2
-# .long _a1
-
-
-
-# Input file two:
-#
-# .align 2
-# .code 32
-# .globl _a1
-#_a1:
-# bl _a1
-# blx _a2
-# bl _t1
-# blx _t2
-# bx lr
-#
-# .globl _a2
-#_a2:
-# bx lr
-#
-# .data
-#_d2: .long _t1
-# .long _a1
-
-
-
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch armv7 %s %p/Inputs/arm-shims.yaml \
-# RUN: -dylib %p/Inputs/armv7/libSystem.yaml -o %t
-# RUN: llvm-readobj -S --section-data %t | FileCheck %s
-#
-# Test b from arm to thumb or vice versa has shims added.s
-#
-#
-
---- !mach-o
-arch: armv7
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x00, 0xBF, 0xFF, 0xF7, 0xFE, 0xEF, 0xFF, 0xF7,
- 0xFB, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3,
- 0xFA, 0xFF, 0xFF, 0xFA, 0xF9, 0xFF, 0xFF, 0xEA ]
- relocations:
- - offset: 0x00000014
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000010
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000006
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x00000002
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
-global-symbols:
- - name: _a1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000C
- - name: _t1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000000
-undefined-symbols:
- - name: _a2
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _t2
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-# CHECK: Section {
-# CHECK: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
-# CHECK: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
-# CHECK: SectionData (
-# CHECK: 0000: 00BF00F0 10E800F0 19B80000 00F020E3
-# CHECK: 0010: 000000FA 0F0000EA 00BFFFF7 F8EF00F0
-# CHECK: 0020: 07B80000 00F020E3 F4FFFFFA 050000EA
-# CHECK: 0030: DFF804C0 FF446047 D4FFFFFF DFF804C0
-# CHECK: 0040: FF446047 E0FFFFFF 04C09FE5 0CC08FE0
-# CHECK: 0050: 1CFF2FE1 ADFFFFFF 04C09FE5 0CC08FE0
-# CHECK: 0060: 1CFF2FE1 B5FFFFFF
-# CHECK: )
-
-# When we get a good mach-o disassembler the above __text section content check can be change to be symbolic.
-
-
-# Input file one:
-#
-# .align 2
-# .code 16
-# .globl _t1
-# .thumb_func _t1
-#_t1:
-# nop
-# blx _a2
-# b _a2
-#
-# .code 32
-# .align 2
-# .globl _a1
-#_a1:
-# nop
-# blx _t2
-# b _t2
-
-
-
-# Input file two:
-#
-# .align 2
-# .code 16
-# .globl _t2
-# .thumb_func _t2
-#_t2:
-# nop
-# blx _a1
-# b _a1
-#
-# .code 32
-# .align 2
-# .globl _a2
-#_a2:
-# nop
-# blx _t1
-# b _t1
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch armv7 %s -r -print_atoms -o %t | FileCheck %s
-#
-# Test that assembly written without .subsections_via_symbols is parsed so
-# that atoms are non-dead-strip and there is a layout-after references
-# chaining atoms together.
-#
-
---- !mach-o
-arch: armv7
-file-type: MH_OBJECT
-flags: [ ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x04, 0x10, 0x9F, 0xE5, 0x04, 0x20, 0x9F, 0xE5,
- 0x1E, 0xFF, 0x2F, 0xE1, 0x78, 0x56, 0x34, 0x12,
- 0x21, 0x43, 0x65, 0x87 ]
-local-symbols:
- - name: constants1
- type: N_SECT
- sect: 1
- value: 0x000000000000000C
- - name: constants2
- type: N_SECT
- sect: 1
- value: 0x0000000000000010
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-
-# CHECK:defined-atoms:
-# CHECK: - name: _foo
-# CHECK: scope: global
-# CHECK: content: [ 04, 10, 9F, E5, 04, 20, 9F, E5, 1E, FF, 2F, E1 ]
-# CHECK: dead-strip: never
-# CHECK: references:
-# CHECK: - kind: layout-after
-# CHECK: offset: 0
-# CHECK: target: constants1
-# CHECK: - name: constants1
-# CHECK: content: [ 78, 56, 34, 12 ]
-# CHECK: dead-strip: never
-# CHECK: references:
-# CHECK: - kind: layout-after
-# CHECK: offset: 0
-# CHECK: target: constants2
-# CHECK: - name: constants2
-# CHECK: content: [ 21, 43, 65, 87 ]
-# CHECK: dead-strip: never
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 -r %s -o %t
-# RUN: ld64.lld.darwinold -arch arm64 -r %t -o %t2
-# RUN: llvm-objdump -s --section="__eh_frame" %t | FileCheck %s
-# RUN: llvm-objdump -s --section="__eh_frame" %t2 | FileCheck %s
-
-# The reference from FDE->CIE is implicitly created as a negDelta32.
-# We don't emit these in to the binary as relocations, so we need to
-# make sure that the offset in the FDE to the CIE is the correct value.
-# CHECK: {{[0-9abcdef]*}} 10000000 00000000 017a5200 01781e01
-# CHECK: {{[0-9abcdef]*}} 100c1f00 20000000 18000000 b8ffffff
-# Note, this one that matters ^~~~~~~~
-# It needs to be 0x18 as that is the offset back to 0 where the CIE is.
-# CHECK: {{[0-9abcdef]*}} ffffffff 20000000 00000000 00480e10
-# CHECK: {{[0-9abcdef]*}} 9e019d02 00000000
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
- 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91,
- 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x80, 0x52,
- 0xFD, 0x7B, 0xC1, 0xA8, 0xC0, 0x03, 0x5F, 0xD6 ]
- relocations:
- - offset: 0x00000010
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 6
- - offset: 0x0000000C
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 1
- - offset: 0x00000008
- type: ARM64_RELOC_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000020
- content: [ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F,
- 0x72, 0x6C, 0x64, 0x00 ]
- - segment: __LD
- section: __compact_unwind
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000030
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - segment: __TEXT
- section: __eh_frame
- type: S_COALESCED
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000050
- content: [ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x1E, 0x01,
- 0x10, 0x0C, 0x1F, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0E, 0x10,
- 0x9E, 0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00 ]
-local-symbols:
- - name: ltmp0
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: L_str
- type: N_SECT
- sect: 2
- value: 0x0000000000000020
- - name: ltmp1
- type: N_SECT
- sect: 2
- value: 0x0000000000000020
- - name: ltmp2
- type: N_SECT
- sect: 3
- value: 0x0000000000000030
- - name: ltmp3
- type: N_SECT
- sect: 4
- value: 0x0000000000000050
-global-symbols:
- - name: __Z3fooi
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _puts
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-page-size: 0x00000000
-...
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch arm64 %s -r \
-# RUN: 2> %t.err
-# RUN: FileCheck %s < %t.err
-
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xFF, 0x83, 0x00, 0xD1, 0xE0, 0x0B, 0x00, 0xF9,
- 0x08, 0x00, 0x40, 0xB9, 0x08, 0x0D, 0x00, 0x71,
- 0x08, 0x09, 0x00, 0x71, 0xE8, 0x0F, 0x00, 0xB9,
- 0xC8, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x14,
- 0xE8, 0x03, 0x00, 0x32, 0x08, 0x01, 0x00, 0x12,
- 0xE8, 0x7F, 0x00, 0x39, 0x02, 0x00, 0x00, 0x14 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x000000000001C348
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
-
-# Make sure that the offsets of the subtractor and unsigned both match.
-# CHECK: bad relocation (paired relocs must have the same offset) in section __DATA/__data (r1_address=1, r1_type=1, r1_extern=1, r1_length=3, r1_pcrel=0, r1_symbolnum=1), (r2_address=0, r2_type=0, r2_extern=1, r2_length=3, r2_pcrel=0, r2_symbolnum=1)
- - offset: 0x00000001
- type: ARM64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 1
- - offset: 0x00000000
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 1
-global-symbols:
- - name: _f1
- type: N_SECT
- sect: 2
- value: 0x000000000001C348
- - name: _f2
- type: N_SECT
- sect: 1
- value: 0x0000000000000010
- - name: _f3
- type: N_SECT
- sect: 1
- value: 0x0000000000000020
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 -r -print_atoms %s -o %t
-# RUN: ld64.lld.darwinold -arch arm64 -r -print_atoms %t -o %t2
-# RUN: llvm-objdump --section-headers %t | FileCheck %s
-# RUN: llvm-objdump --section-headers %t2 | FileCheck %s
-
-# Make sure that the sections are sorted. Currently we want this order:
-# __text, __unwind_info
-
-# CHECK: Sections:
-# CHECK: 0 __text {{.*}} TEXT
-# CHECK: 1 __compact_unwind {{.*}}
-
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 8
- address: 0x0000000000000000
- content: [ 0xC0, 0x03, 0x5F, 0xD6, 0xC0, 0x03, 0x5F, 0xD6 ]
- - segment: __LD
- section: __compact_unwind
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000008
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000020
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
-global-symbols:
- - name: __Z3fooi
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: __Z4foo2i
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000004
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 %s %p/Inputs/hello-world-arm64.yaml -o %t
-# RUN: obj2yaml %t | FileCheck %s
-#
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
- 0x08, 0x00, 0x00, 0x90, 0x08, 0x01, 0x40, 0xF9,
- 0x00, 0x01, 0x40, 0xF9, 0x01, 0x00, 0x00, 0x90,
- 0x21, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x94,
- 0x00, 0x00, 0x80, 0x52, 0xFD, 0x7B, 0xC1, 0xA8,
- 0xC0, 0x03, 0x5F, 0xD6 ]
- relocations:
- - offset: 0x0000001C
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 5
- - offset: 0x00000018
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 1
- - offset: 0x00000014
- type: ARM64_RELOC_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x0000000C
- type: ARM64_RELOC_GOT_LOAD_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000008
- type: ARM64_RELOC_GOT_LOAD_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x000000000000002C
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
-local-symbols:
- - name: ltmp0
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: l_.str
- type: N_SECT
- sect: 2
- value: 0x000000000000002C
- - name: ltmp1
- type: N_SECT
- sect: 2
- value: 0x000000000000002C
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: ___stdoutp
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _fprintf
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-
-# CHECK: BindOpcodes:
-# CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
-# CHECK: Imm: 1
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
-# CHECK: Imm: 0
-# CHECK: Symbol: dyld_stub_binder
-# CHECK: - Opcode: BIND_OPCODE_SET_TYPE_IMM
-# CHECK: Imm: 1
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
-# CHECK: Imm: 2
-# CHECK: ULEBExtraData: [ 0x0 ]
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_DO_BIND
-# CHECK: Imm: 0
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
-# CHECK: Imm: 0
-# CHECK: Symbol: ___stdoutp
-# CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
-# CHECK: Imm: 2
-# CHECK: ULEBExtraData: [ 0x10 ]
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_DO_BIND
-# CHECK: Imm: 0
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_DONE
-# CHECK: Imm: 0
-# CHECK: Symbol: ''
-
-# CHECK: LazyBindOpcodes:
-# CHECK: - Opcode: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
-# CHECK: Imm: 2
-# CHECK: ULEBExtraData: [ 0x18 ]
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
-# CHECK: Imm: 1
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
-# CHECK: Imm: 0
-# CHECK: Symbol: _fprintf
-# CHECK: - Opcode: BIND_OPCODE_DO_BIND
-# CHECK: Imm: 0
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_DONE
-# CHECK: Imm: 0
-# CHECK: Symbol: ''
-# CHECK: - Opcode: BIND_OPCODE_DONE
-# CHECK: Imm: 0
-# CHECK: Symbol: ''
\ No newline at end of file
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -o %t -print_atoms | FileCheck %s
-#
-# Test -keep_private_externs in -r mode.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __objc_methname
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000000
- content: [ 0x61, 0x62, 0x63, 0x00, 0x64, 0x65, 0x66, 0x00 ]
- - segment: __TEXT
- section: __objc_classname
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000006
- content: [ 0x61, 0x62, 0x63, 0x00, 0x67, 0x68, 0x69, 0x00 ]
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x000000000000000A
- content: [ 0x61, 0x62, 0x63, 0x00, 0x6A, 0x6B, 0x6C, 0x00 ]
-
-
-...
-
-# CHECK: defined-atoms:
-# CHECK: - scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 61, 62, 63, 00 ]
-# CHECK: merge: by-content
-# CHECK: section-choice: custom-required
-# CHECK: section-name: '__TEXT/__objc_methname'
-# CHECK: - scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 64, 65, 66, 00 ]
-# CHECK: merge: by-content
-# CHECK: section-choice: custom-required
-# CHECK: section-name: '__TEXT/__objc_methname'
-# CHECK: - scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 61, 62, 63, 00 ]
-# CHECK: merge: by-content
-# CHECK: section-choice: custom-required
-# CHECK: section-name: '__TEXT/__objc_classname'
-# CHECK: - scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 67, 68, 69, 00 ]
-# CHECK: merge: by-content
-# CHECK: section-choice: custom-required
-# CHECK: section-name: '__TEXT/__objc_classname'
-# CHECK: - scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 61, 62, 63, 00 ]
-# CHECK: merge: by-content
-# CHECK: - scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 6A, 6B, 6C, 00 ]
-# CHECK: merge: by-content
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -static -data_in_code_info && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -no_data_in_code_info && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -static -data_in_code_info -no_data_in_code_info && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -static && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -r && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -r -data_in_code_info && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -r -no_data_in_code_info && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_DATA_IN_CODE_INFO
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# CHECK: Load command {{[0-9]*}}
-# CHECK: cmd LC_DATA_IN_CODE
-# CHECK: cmdsize 16
-# CHECK: dataoff
-# CHECK: datasize
-
-# NO_DATA_IN_CODE_INFO-NOT: LC_DATA_IN_CODE
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -dylib %s -o %t %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-nm %t | FileCheck %s
-#
-# Test that a data-only dylib can be built.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _myData
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# CHECK: _myData
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -dead_strip -export_dynamic %s -dylib %p/Inputs/x86_64/libSystem.yaml -o %t.dylib -print_atoms | FileCheck -check-prefix=CHECK1 %s
-# RUN: ld64.lld.darwinold -arch x86_64 -export_dynamic -dead_strip %s -dylib %p/Inputs/x86_64/libSystem.yaml -o %t.dylib -print_atoms | FileCheck -check-prefix=CHECK1 %s
-# RUN: ld64.lld.darwinold -arch x86_64 -dead_strip %s -dylib %p/Inputs/x86_64/libSystem.yaml -o %t2.dylib -print_atoms | FileCheck -check-prefix=CHECK2 %s
-
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -dylib %p/Inputs/x86_64/libSystem.yaml -o %t3.o
-# RUN: llvm-nm -m %t3.o | FileCheck -check-prefix=RELOCATABLE_SYMBOLS %s
-
-#
-# Test that -export_dynamic -dead-strip from removing globals.
-#
-
----
-defined-atoms:
- - name: def
- scope: global
- dead-strip: never
- - name: dead
- scope: global
-shared-library-atoms:
- - name: dyld_stub_binder
- load-name: /usr/lib/libSystem.B.dylib
- type: unknown
-...
-
-# CHECK1: name: def
-# CHECK1: name: dead
-
-# CHECK2: name: def
-# CHECK2-NOT: name: dead
-
-# RELOCATABLE_SYMBOLS: external def
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -o %t %s -dylib %p/Inputs/x86_64/libSystem.yaml && \
-# RUN: llvm-nm --no-sort --debug-syms %t | FileCheck %s
-
-# CHECK: 0000000000000000 - 00 0000 SO /Users/lhames/Projects/lld/lld-svn-tot/scratch/
-# CHECK-NEXT: 0000000000000000 - 00 0000 SO hw.c
-# CHECK-NEXT: {{[0-9a-f]+}} - 03 0001 OSO {{.*}}{{/|\\}}test{{/|\\}}mach-o{{/|\\}}debug-syms.yaml
-# CHECK-NEXT: 0000000000000fa0 - 01 0000 BNSYM
-# CHECK-NEXT: 0000000000000fa0 - 01 0000 FUN _main
-# CHECK-NEXT: 0000000000000016 - 00 0000 FUN
-# CHECK-NEXT: 0000000000000016 - 01 0000 ENSYM
-# CHECK-NEXT: 0000000000000000 - 01 0000 SO
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-min-os-version-kind: LC_VERSION_MIN_MACOSX
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 16
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0xC7, 0x45,
- 0xFC, 0x00, 0x00, 0x00, 0x00, 0x89, 0x7D, 0xF8,
- 0x48, 0x89, 0x75, 0xF0, 0x5D, 0xC3 ]
- - segment: __DWARF
- section: __debug_str
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x0000000000000016
- content: [ 0x41, 0x70, 0x70, 0x6C, 0x65, 0x20, 0x4C, 0x4C,
- 0x56, 0x4D, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
- 0x6F, 0x6E, 0x20, 0x38, 0x2E, 0x30, 0x2E, 0x30,
- 0x20, 0x28, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x2D,
- 0x38, 0x30, 0x30, 0x2E, 0x30, 0x2E, 0x32, 0x34,
- 0x2E, 0x31, 0x29, 0x00, 0x68, 0x77, 0x2E, 0x63,
- 0x00, 0x2F, 0x55, 0x73, 0x65, 0x72, 0x73, 0x2F,
- 0x6C, 0x68, 0x61, 0x6D, 0x65, 0x73, 0x2F, 0x50,
- 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x2F,
- 0x6C, 0x6C, 0x64, 0x2F, 0x6C, 0x6C, 0x64, 0x2D,
- 0x73, 0x76, 0x6E, 0x2D, 0x74, 0x6F, 0x74, 0x2F,
- 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x00,
- 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x69, 0x6E, 0x74,
- 0x00, 0x61, 0x72, 0x67, 0x63, 0x00, 0x61, 0x72,
- 0x67, 0x76, 0x00, 0x63, 0x68, 0x61, 0x72, 0x00 ]
- - segment: __DWARF
- section: __debug_loc
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x000000000000008E
- - segment: __DWARF
- section: __debug_abbrev
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x000000000000008E
- content: [ 0x01, 0x11, 0x01, 0x25, 0x0E, 0x13, 0x05, 0x03,
- 0x0E, 0x10, 0x06, 0x1B, 0x0E, 0x11, 0x01, 0x12,
- 0x01, 0x00, 0x00, 0x02, 0x2E, 0x01, 0x11, 0x01,
- 0x12, 0x01, 0x40, 0x0A, 0x03, 0x0E, 0x3A, 0x0B,
- 0x3B, 0x0B, 0x27, 0x0C, 0x49, 0x13, 0x3F, 0x0C,
- 0x00, 0x00, 0x03, 0x05, 0x00, 0x02, 0x0A, 0x03,
- 0x0E, 0x3A, 0x0B, 0x3B, 0x0B, 0x49, 0x13, 0x00,
- 0x00, 0x04, 0x24, 0x00, 0x03, 0x0E, 0x3E, 0x0B,
- 0x0B, 0x0B, 0x00, 0x00, 0x05, 0x0F, 0x00, 0x49,
- 0x13, 0x00, 0x00, 0x00 ]
- - segment: __DWARF
- section: __debug_info
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x00000000000000DA
- content: [ 0x7F, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x0C, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x56, 0x60, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
- 0x6A, 0x00, 0x00, 0x00, 0x01, 0x03, 0x02, 0x91,
- 0x78, 0x69, 0x00, 0x00, 0x00, 0x01, 0x01, 0x6A,
- 0x00, 0x00, 0x00, 0x03, 0x02, 0x91, 0x70, 0x6E,
- 0x00, 0x00, 0x00, 0x01, 0x01, 0x71, 0x00, 0x00,
- 0x00, 0x00, 0x04, 0x65, 0x00, 0x00, 0x00, 0x05,
- 0x04, 0x05, 0x76, 0x00, 0x00, 0x00, 0x05, 0x7B,
- 0x00, 0x00, 0x00, 0x04, 0x73, 0x00, 0x00, 0x00,
- 0x06, 0x01, 0x00 ]
- relocations:
- - offset: 0x00000037
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x0000002F
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000026
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x0000001E
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - segment: __DWARF
- section: __debug_ranges
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x000000000000015D
- - segment: __DWARF
- section: __debug_macinfo
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x000000000000015D
- content: [ 0x00 ]
- - segment: __DWARF
- section: __apple_names
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x000000000000015E
- content: [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x6A, 0x7F, 0x9A, 0x7C,
- 0x2C, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00 ]
- - segment: __DWARF
- section: __apple_objc
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x000000000000019A
- content: [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF ]
- - segment: __DWARF
- section: __apple_namespac
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x00000000000001BE
- content: [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF ]
- - segment: __DWARF
- section: __apple_types
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x00000000000001E2
- content: [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00,
- 0x03, 0x00, 0x05, 0x00, 0x04, 0x00, 0x0B, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x30, 0x80, 0x88, 0x0B, 0x63, 0x20, 0x95, 0x7C,
- 0x40, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00,
- 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x6A, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x24,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- - segment: __DWARF
- section: __apple_exttypes
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x0000000000000248
- content: [ 0x48, 0x53, 0x41, 0x48, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF ]
- - segment: __LD
- section: __compact_unwind
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- alignment: 8
- address: 0x0000000000000270
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - segment: __TEXT
- section: __eh_frame
- type: S_COALESCED
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000290
- content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
- 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
- 0x50, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- - segment: __DWARF
- section: __debug_line
- type: S_REGULAR
- attributes: [ S_ATTR_DEBUG ]
- address: 0x00000000000002D0
- content: [ 0x37, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1B, 0x00,
- 0x00, 0x00, 0x01, 0x01, 0xFB, 0x0E, 0x0D, 0x00,
- 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x01, 0x00, 0x68, 0x77, 0x2E, 0x63,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x05, 0x03, 0x0A, 0x08, 0x3D, 0x02, 0x02,
- 0x00, 0x01, 0x01 ]
- relocations:
- - offset: 0x00000028
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-page-size: 0x00000000
-...
+++ /dev/null
-# REQUIRES: system-linker-mach-o
-#
-# RUN: not ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s \
-# RUN: -dylib -o %t %p/Inputs/x86_64/libSystem.yaml 2> %t.err
-# RUN: FileCheck %s < %t.err
-#
-# RUN: not ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s \
-# RUN: -dylib -o %t %p/Inputs/x86_64/libSystem.yaml -demangle 2> %t.err2
-# RUN: FileCheck %s --check-prefix=DCHECK < %t.err2
-#
-# Test -demangle option works on undefined symbol errors.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xE8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00,
- 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x0000000B
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x00000006
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000001
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
-global-symbols:
- - name: __Z1xv
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: __Znam
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: __Znotcpp
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-# CHECK: __Znotcpp
-# CHECK: __Znam
-# CHECK: _foo
-
-# DCHECK: __Znotcpp
-# DCHECK: operator new[](unsigned long)
-# DCHECK: _foo
-
+++ /dev/null
-# Test -dependency_info option
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -test_file_usage \
-# RUN: -dependency_info %t.info \
-# RUN: -path_exists /System/Library/Frameworks \
-# RUN: -path_exists /System/Library/Frameworks/Foo.framework/Foo \
-# RUN: -path_exists /Custom/Frameworks \
-# RUN: -path_exists /Custom/Frameworks/Bar.framework/Bar \
-# RUN: -F/Custom/Frameworks \
-# RUN: -framework Bar \
-# RUN: -framework Foo
-# RUN: %python %p/Inputs/DependencyDump.py %t.info | FileCheck %s
-
-
-# CHECK: linker-vers: lld
-# CHECK: input-file: /Custom/Frameworks{{[/\\]}}Bar.framework{{[/\\]}}Bar
-# CHECK: not-found: /Custom/Frameworks{{[/\\]}}Foo.framework{{[/\\]}}Foo
-# CHECK: input-file: /System/Library/Frameworks{{[/\\]}}Foo.framework{{[/\\]}}Foo
-# CHECK: output-file: a.out
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 -r -print_atoms %s -o %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
-# RUN: llvm-objdump -r -s --section="__eh_frame" --macho %t | FileCheck --check-prefix=CODE %s
-# RUN: llvm-objdump -r -s --section="__eh_frame" --macho %t2 | FileCheck --check-prefix=CODE %s
-
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
- 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91,
- 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x80, 0x52,
- 0xFD, 0x7B, 0xC1, 0xA8, 0xC0, 0x03, 0x5F, 0xD6 ]
- relocations:
- - offset: 0x00000010
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 9
- - offset: 0x0000000C
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 1
- - offset: 0x00000008
- type: ARM64_RELOC_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000020
- content: [ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F,
- 0x72, 0x6C, 0x64, 0x00 ]
- - segment: __LD
- section: __compact_unwind
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000030
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - segment: __TEXT
- section: __eh_frame
- type: S_COALESCED
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000050
- content: [ 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
- 0x1E, 0x07, 0x00, 0x9D, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0x00, 0x10, 0x0C, 0x1F, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x48, 0x0E, 0x10, 0x9E, 0x01, 0x9D, 0x02 ]
- - segment: __TEXT
- section: __gcc_except_tab
- type: S_REGULAR
- attributes: [ ]
- address: 0x00000000000000A0
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-local-symbols:
- - name: ltmp0
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: L_str
- type: N_SECT
- sect: 2
- value: 0x0000000000000020
- - name: ltmp1
- type: N_SECT
- sect: 2
- value: 0x0000000000000020
- - name: ltmp2
- type: N_SECT
- sect: 3
- value: 0x0000000000000030
- - name: ltmp3
- type: N_SECT
- sect: 4
- value: 0x0000000000000050
- - name: ltmp4
- type: N_SECT
- sect: 4
- value: 0x0000000000000070
-global-symbols:
- - name: __Z3fooi
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: __gxx_personality_v0
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _bar
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _puts
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-page-size: 0x00000000
-
-# CHECK: defined-atoms:
-# CHECK: - ref-name: L{{[0-9]*}}
-# CHECK: scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 48, 65, 6C, 6C, 6F, 20, 77, 6F, 72, 6C, 64, 00 ]
-# CHECK: merge: by-content
-# CHECK: - ref-name: L{{[0-9]*}}
-# CHECK: type: unwind-cfi
-# CHECK: content: [ 1C, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 50, 4C,
-# CHECK: 52, 00, 01, 78, 1E, 07, 00, {{..}}, {{..}}, {{..}}, {{..}}, {{..}},
-# CHECK: {{..}}, {{..}}, {{..}}, 00, 10, 0C, 1F, 00 ]
-# CHECK: - type: unwind-cfi
-# CHECK: content: [ 24, 00, 00, 00, 24, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}},
-# CHECK: {{..}}, {{..}}, {{..}}, {{..}}, 20, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 08, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, 48, 0E, 10,
-# CHECK: 9E, 01, 9D, 02 ]
-# CHECK: references:
-# CHECK: - kind: negDelta32
-# CHECK: offset: 4
-# CHECK: target: L{{[0-9]*}}
-# CHECK: - kind: unwindFDEToFunction
-# CHECK: offset: 8
-# CHECK: target: __Z3fooi
-# CHECK: - kind: unwindFDEToFunction
-# CHECK: offset: 25
-# CHECK: target: L{{[0-9]*}}
-# CHECK: - ref-name: L{{[0-9]*}}
-# CHECK: type: unwind-lsda
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: - type: compact-unwind
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 20, 00, 00, 00,
-# CHECK: 00, 00, 00, 03, 00, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: alignment: 8
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: __Z3fooi
-# CHECK: - name: __Z3fooi
-# CHECK: scope: global
-# CHECK: content: [ FD, 7B, BF, A9, FD, 03, 00, 91, 00, 00, 00, 90,
-# CHECK: 00, 00, 00, 91, 00, 00, 00, 94, 00, 00, 80, 52,
-# CHECK: FD, 7B, C1, A8, C0, 03, 5F, D6 ]
-# CHECK: alignment: 4
-# CHECK: references:
-# CHECK: - kind: page21
-# CHECK: offset: 8
-# CHECK: target: L{{[0-9]*}}
-# CHECK: - kind: offset12
-# CHECK: offset: 12
-# CHECK: target: L{{[0-9]*}}
-# CHECK: - kind: branch26
-# CHECK: offset: 16
-# CHECK: target: _puts
-
-# Make sure we don't have any relocations in the __eh_frame section
-# CODE-NOT: RELOCATION RECORDS FOR [__eh_frame]
-
-# Also make sure the reloc for the FDE->function is the correct offset
-# It should be the offset from the fixup location back to the address
-# of the function we are referencing
-# CODE: Contents of section __TEXT,__eh_frame:
-# This is the CIE:
-# CODE-NEXT: {{[0-9abcdef]*}} 1c000000 00000000 017a504c 52000178
-# CODE-NEXT: {{[0-9abcdef]*}} 1e0700bd ffffffff ffffff00 100c1f00
-# This is the FDE:
-# CODE-NEXT: {{[0-9abcdef]*}} 24000000 24000000 a8ffffff ffffffff
-# This is the important offset for FDE->func ^~~~~~~~ ~~~~~~~~
-
-# CODE-NEXT: {{[0-9abcdef]*}} 20000000 00000000 08c3ffff ffffffff
-# And this is the offset for FDE->lsda ^~~~~~~~ ~~~~~~
-# CODE-NEXT: {{[0-9abcdef]*}} ff480e10 9e019d02
-# And this byte ^~
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/x86_64/libSystem.yaml -o %t1
-# RUN: llvm-nm -m -n %t1 | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/x86_64/libSystem.yaml -dead_strip -o %t2
-# RUN: llvm-nm -m -n %t2 | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/x86_64/libSystem.yaml -dylib -o %t3
-# RUN: llvm-nm -m -n %t3 | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/x86_64/libSystem.yaml -bundle -o %t4
-# RUN: llvm-nm -m -n %t4 | FileCheck %s
-#
-# Test that ___dso_handle symbol is available for executables, bundles, and dylibs
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xC3 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000008
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
-global-symbols:
- - name: _d
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x0000000000000008
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: ___dso_handle
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-
-...
-
-# CHECK_NOT: ___dso_handle
-# CHECK: _main
+++ /dev/null
-# Check we accept -install_name correctly:
-# RUN: ld64.lld.darwinold -arch x86_64 -install_name libwibble.dylib -dylib \
-# RUN: -compatibility_version 2.0 -current_version 5.3 \
-# RUN: %p/Inputs/x86_64/libSystem.yaml %s -o %t.dylib
-# RUN: llvm-objdump --private-headers %t.dylib | FileCheck %s --check-prefix=CHECK-BINARY-WRITE
-
-# Check we read LC_ID_DYLIB correctly:
-# RUN: ld64.lld.darwinold -arch x86_64 %p/Inputs/use-dylib-install-names.yaml \
-# RUN: %p/Inputs/x86_64/libSystem.yaml %t.dylib -dylib -o %t2.dylib
-# RUN: llvm-objdump --private-headers %t2.dylib | FileCheck %s --check-prefix=CHECK-BINARY-READ
-
-# Check we default the install-name to the output file:
-# RUN: ld64.lld.darwinold -arch x86_64 -dylib %s -o libwibble.dylib \
-# RUN: -compatibility_version 2.0 -current_version 5.3 \
-# RUN: %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-objdump --private-headers libwibble.dylib | FileCheck %s --check-prefix=CHECK-BINARY-WRITE
-# RUN: rm -f libwibble.dylib
-
-# Check -single_module does nothing
-# RUN: ld64.lld.darwinold -arch x86_64 -dylib %s -install_name libwibble.dylib \
-# RUN: -compatibility_version 2.0 -current_version 5.3 \
-# RUN: -single_module -o %t2.dylib %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-objdump --private-headers %t2.dylib | FileCheck %s --check-prefix=CHECK-BINARY-WRITE
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xCC, 0xC3, 0x90, 0xC3, 0x90, 0x90, 0xC3, 0x90,
- 0x90, 0x90, 0xC3, 0x90, 0x90, 0x90, 0x90, 0xC3,
- 0x31, 0xC0, 0xC3 ]
-local-symbols:
- - name: _myStatic
- type: N_SECT
- sect: 1
- value: 0x000000000000000B
-global-symbols:
- - name: _myGlobal
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
-...
-
-
-# CHECK-BINARY-WRITE: cmd LC_ID_DYLIB
-# CHECK-BINARY-WRITE-NEXT: cmdsize 40
-# CHECK-BINARY-WRITE-NEXT: name libwibble.dylib (offset 24)
-# CHECK-BINARY-WRITE-NEXT: time stamp 1
-# CHECK-BINARY-WRITE-NEXT: current version 5.3.0
-# CHECK-BINARY-WRITE-NEXT: compatibility version 2.0.0
-
-# CHECK-BINARY-READ: cmd LC_LOAD_DYLIB
-# CHECK-BINARY-READ-NEXT: cmdsize 56
-# CHECK-BINARY-READ-NEXT: name /usr/lib/libSystem.B.dylib (offset 24)
-# CHECK-BINARY-READ-NEXT: time stamp 2
-# CHECK-BINARY-READ-NEXT: current version 1.0.0
-# CHECK-BINARY-READ-NEXT: compatibility version 1.0.0
-
-# CHECK-BINARY-READ: cmd LC_LOAD_DYLIB
-# CHECK-BINARY-READ-NEXT: cmdsize 40
-# CHECK-BINARY-READ-NEXT: name libwibble.dylib (offset 24)
-# CHECK-BINARY-READ-NEXT: time stamp 2
-# CHECK-BINARY-READ-NEXT: current version 5.3.0
-# CHECK-BINARY-READ-NEXT: compatibility version 2.0.0
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 -r -print_atoms %s -o %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
-# RUN: llvm-objdump -r -s --section="__eh_frame" --macho %t | FileCheck --check-prefix=CODE %s
-# RUN: llvm-objdump -r -s --section="__eh_frame" --macho %t2 | FileCheck --check-prefix=CODE %s
-
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xC0, 0x03, 0x5F, 0xD6, 0xC0, 0x03, 0x5F, 0xD6,
- 0xC0, 0x03, 0x5F, 0xD6 ]
- - segment: __TEXT
- section: __gcc_except_tab
- type: S_REGULAR
- attributes: [ ]
- address: 0x0000000000000014
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x000000000000001C
- content: [ 0x00, 0x00, 0x00, 0x00 ]
- - segment: __LD
- section: __compact_unwind
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000020
- content: [ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000020
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - segment: __TEXT
- section: __eh_frame
- type: S_COALESCED
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000060
- content: [ 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
- 0x1E, 0x07, 0x9B, 0xED, 0xFF, 0xFF, 0xFF, 0x10,
- 0x10, 0x0C, 0x1F, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0xDC, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0xCB, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x10, 0x9E,
- 0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
- 0x1E, 0x07, 0x9B, 0xA9, 0xFF, 0xFF, 0xFF, 0x10,
- 0x10, 0x0C, 0x1F, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x83, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x10, 0x9E,
- 0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x0000007D
- type: ARM64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 6
- - offset: 0x0000007D
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 3
- - offset: 0x0000006C
- type: ARM64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 6
- - offset: 0x0000006C
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 8
- - offset: 0x0000005B
- type: ARM64_RELOC_POINTER_TO_GOT
- length: 2
- pc-rel: true
- extern: true
- symbol: 10
- - offset: 0x00000035
- type: ARM64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 6
- - offset: 0x00000035
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000024
- type: ARM64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 6
- - offset: 0x00000024
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 7
- - offset: 0x00000013
- type: ARM64_RELOC_POINTER_TO_GOT
- length: 2
- pc-rel: true
- extern: true
- symbol: 9
-local-symbols:
- - name: ltmp0
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: ltmp1
- type: N_SECT
- sect: 2
- value: 0x0000000000000014
- - name: _bar1
- type: N_SECT
- sect: 2
- value: 0x0000000000000014
- - name: _bar2
- type: N_SECT
- sect: 2
- value: 0x0000000000000018
- - name: ltmp12
- type: N_SECT
- sect: 3
- value: 0x000000000000001C
- - name: ltmp13
- type: N_SECT
- sect: 4
- value: 0x0000000000000020
- - name: ltmp16
- type: N_SECT
- sect: 5
- value: 0x0000000000000060
-global-symbols:
- - name: __Z3fooi
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000008
- - name: __Z4foo2i
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000C
- - name: __gxx_personality_v0
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: __gxx_personality_v1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000004
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000010
- - name: _someData
- type: N_SECT
- scope: [ N_EXT ]
- sect: 3
- value: 0x000000000000001C
-page-size: 0x00000000
-...
-
-# CHECK: --- !native
-# CHECK: path: '<linker-internal>'
-# CHECK: defined-atoms:
-# CHECK: - ref-name: L000
-# CHECK: type: unwind-cfi
-# CHECK: content: [ 18, 00, 00, 00, 00, 00, 00, 00, 03, 7A, 50, 4C,
-# CHECK: 52, 00, 01, 78, 1E, 07, 9B, {{..}}, {{..}}, {{..}}, {{..}}, 10,
-# CHECK: 10, 0C, 1F, 00 ]
-# CHECK: alignment: 8
-# CHECK: references:
-# CHECK: - kind: unwindCIEToPersonalityFunction
-# CHECK: offset: 19
-# CHECK: target: __gxx_personality_v0
-# CHECK: - type: unwind-cfi
-# CHECK: content: [ 28, 00, 00, 00, 20, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}},
-# CHECK: {{..}}, {{..}}, {{..}}, {{..}}, 04, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 08, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, 0E, 10, 9E,
-# CHECK: 01, 9D, 02, 00, 00, 00, 00, 00 ]
-# CHECK: alignment: 4 mod 8
-# CHECK: references:
-# CHECK: - kind: negDelta32
-# CHECK: offset: 4
-# CHECK: target: L000
-# CHECK: - kind: unwindFDEToFunction
-# CHECK: offset: 8
-# CHECK: target: __Z3fooi
-# CHECK: - kind: unwindFDEToFunction
-# CHECK: offset: 25
-# CHECK: target: _bar1
-# CHECK: - ref-name: L001
-# CHECK: type: unwind-cfi
-# CHECK: content: [ 18, 00, 00, 00, 00, 00, 00, 00, 03, 7A, 50, 4C,
-# CHECK: 52, 00, 01, 78, 1E, 07, 9B, {{..}}, {{..}}, {{..}}, {{..}}, 10,
-# CHECK: 10, 0C, 1F, 00 ]
-# CHECK: alignment: 8
-# CHECK: references:
-# CHECK: - kind: unwindCIEToPersonalityFunction
-# CHECK: offset: 19
-# CHECK: target: __gxx_personality_v1
-# CHECK: - type: unwind-cfi
-# CHECK: content: [ 28, 00, 00, 00, 20, 00, 00, 00, {{..}}, {{..}}, {{..}}, {{..}},
-# CHECK: {{..}}, {{..}}, {{..}}, {{..}}, 04, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 08, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, 0E, 10, 9E,
-# CHECK: 01, 9D, 02, 00, 00, 00, 00, 00 ]
-# CHECK: alignment: 4 mod 8
-# CHECK: references:
-# CHECK: - kind: negDelta32
-# CHECK: offset: 4
-# CHECK: target: L001
-# CHECK: - kind: unwindFDEToFunction
-# CHECK: offset: 8
-# CHECK: target: __Z4foo2i
-# CHECK: - kind: unwindFDEToFunction
-# CHECK: offset: 25
-# CHECK: target: _bar2
-# CHECK: - name: _bar1
-# CHECK: type: unwind-lsda
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: - name: _bar2
-# CHECK: type: unwind-lsda
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: - name: _someData
-# CHECK: scope: global
-# CHECK: type: data
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: - name: __gxx_personality_v0
-# CHECK: scope: global
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: alignment: 4
-# CHECK: - name: __gxx_personality_v1
-# CHECK: scope: global
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: alignment: 4
-# CHECK: - name: __Z3fooi
-# CHECK: scope: global
-# CHECK: content: [ C0, 03, 5F, D6 ]
-# CHECK: alignment: 4
-# CHECK: - name: __Z4foo2i
-# CHECK: scope: global
-# CHECK: content: [ C0, 03, 5F, D6 ]
-# CHECK: alignment: 4
-# CHECK: - name: _main
-# CHECK: scope: global
-# CHECK: content: [ C0, 03, 5F, D6 ]
-# CHECK: alignment: 4
-# CHECK: ...
-
-# # Make sure we don't have any relocations in the __eh_frame section
-# CODE-NOT: RELOCATION RECORDS FOR [__eh_frame]
-
-# Also make sure the reloc for the CIE->personality function is the
-# correct offset
-# It should be the offset from the fixup location back to the address
-# of the function we are referencing
-# CODE: Contents of section __TEXT,__eh_frame:
-# This is the CIE:
-# CODE-NEXT: {{[0-9abcdef]*}} 18000000 00000000 037a504c 52000178
-# CODE-NEXT: {{[0-9abcdef]*}} 1e079bd1 ffffff10 100c1f00 28000000
-# This is the important offset for CIE->pfunc
-# ^~~~~~~~~
-# Then we have an FDE starting from 28000000 above
-# CODE-NEXT: {{[0-9abcdef]*}} 20000000 c8ffffff ffffffff 04000000
-# CODE-NEXT: {{[0-9abcdef]*}} 00000000 08c3ffff ffffffff ff0e109e
-# And a new CIE starts at this 00000018 right below here
-# CODE-NEXT: {{[0-9abcdef]*}} 019d0200 00000000 18000000 00000000
-# CODE-NEXT: {{[0-9abcdef]*}} 037a504c 52000178 1e079b8d ffffff10
-# This is the important offset for its CIE->pfunc ^~~~~~~~~
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -o %t
-#
-# Test that writing empty mach-o sections does not segfault the linker.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-...
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -macosx_version_min 10.8 %s %p/Inputs/hello-world-x86.yaml -o %t && llvm-nm -m %t | FileCheck %s
-# RUN: not ld64.lld.darwinold -arch i386 -ios_simulator_version_min 5.0 %s %p/Inputs/hello-world-x86.yaml -o %t 2>&1 | FileCheck %s --check-prefix=ERROR
-#
-# Test that i386 can link with a macos version but gives an error with a simulator version.
-#
-
---- !mach-o
-arch: x86
-OS: Mac OS X
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x90 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
-# CHECK: (undefined) external dyld_stub_binder (from libSystem)
-
-# ERROR: cannot be linked due to incompatible operating systems
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s -o %t -e start %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-readobj --sections %t | FileCheck %s
-
-# Make sure data gets put at offset
-
---- !native
-defined-atoms:
- - name: start
- scope: global
- content: [ 90 ]
-
- - name: _s1
- type: data
- content: [ 31, 32, 33, 34 ]
-
- - name: _s2
- type: zero-fill
- size: 8192
-
- - name: _s3
- type: zero-fill
- size: 100
-
- - name: _s4
- type: data
- content: [ 01 ]
-
-
-# CHECK-LABEL: Section {
-# CHECK: Name: __text
-# CHECK: Segment: __TEXT
-# CHECK: Size: 0x1
-# CHECK: Offset: 0
-
-# CHECK-LABEL: Section {
-# CHECK: Name: __data
-# CHECK: Segment: __DATA
-# CHECK: Size: 0x5
-# CHECK: Offset: 4096
-
-# CHECK-LABEL: Section {
-# CHECK: Name: __bss
-# CHECK: Segment: __DATA
-# CHECK: Size: 0x2064
-# CHECK: Offset: 0
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s -o %t %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-readobj --sections --section-data %t | FileCheck %s
-
---- !native
-defined-atoms:
- - name: _main
- scope: global
- content: [ 90 ]
-
- - name: _s2
- type: data
- content: [ 31, 32, 33, 34 ]
-
- - name: _kustom
- scope: global
- type: unknown
- content: [ 01, 02, 03, 04, 05, 06, 07, 08 ]
- section-choice: custom-required
- section-name: __CUST/__custom
-
-
-# CHECK-LABEL: Section {
-# CHECK: Name: __text
-# CHECK: Segment: __TEXT
-# CHECK: Size: 0x1
-# CHECK: Offset: 4095
-
-# CHECK-LABEL: Section {
-# CHECK: Name: __data
-# CHECK: Segment: __DATA
-# CHECK: Size: 0x4
-# CHECK: Offset: 4096
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 31323334
-# CHECK-NEXT: )
-
-# CHECK-LABEL: Section {
-# CHECK: Name: __custom{{ }}
-# CHECK: Segment: __CUST{{ }}
-# CHECK: Size: 0x8
-# CHECK: Offset: 8192
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 01020304 05060708
-# CHECK-NEXT: )
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 \
-# RUN: %s %p/Inputs/x86_64/libSystem.yaml -o %t && \
-# RUN: llvm-objdump --macho --exports-trie %t | FileCheck %s
-#
-#
-# Tests that exports trie builds properly.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xC3, 0xC3, 0xC3, 0xC3 ]
-global-symbols:
- - name: _myHidden
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _myRegular
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myWeak
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_WEAK_DEF ]
- value: 0x0000000000000002
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000003
-...
-
-# CHECK-NOT: _myHidden
-# CHECK: 0x100000FFD _myRegular
-# CHECK: 0x100000FFE _myWeak [weak_def]
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 %s %p/Inputs/hello-world-x86.yaml -o %t
-# RUN: llvm-objdump --macho --exports-trie %t | FileCheck %s
-#
-# Test that the export trie is emitted in order.
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0x58, 0x8D, 0x80, 0x16, 0x00,
- 0x00, 0x00, 0x89, 0x04, 0x24, 0xE8, 0xE6, 0xFF,
- 0xFF, 0xFF, 0x31, 0xC0, 0x83, 0xC4, 0x08, 0x5D,
- 0xC3 ]
- relocations:
- - offset: 0x00000016
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x0000000E
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000021
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000000B
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000021
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _printf
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: Exports trie:
-# CHECK-NEXT: __mh_execute_header
-# CHECK-NEXT: _main
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 -dylib \
-# RUN: %s %p/Inputs/x86_64/libSystem.yaml -o %t \
-# RUN: -exported_symbols_list %p/Inputs/exported_symbols_list.exp && \
-# RUN: llvm-nm -m %t | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 -dylib \
-# RUN: %s %p/Inputs/x86_64/libSystem.yaml -o %t2 \
-# RUN: -exported_symbol _foo -exported_symbol _b && \
-# RUN: llvm-nm -m %t2 | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 -dylib \
-# RUN: %s %p/Inputs/x86_64/libSystem.yaml -o %t3 \
-# RUN: -unexported_symbol _bar -unexported_symbol _a && \
-# RUN: llvm-nm -m %t3 | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 -dylib \
-# RUN: %s %p/Inputs/x86_64/libSystem.yaml -dead_strip -o %t \
-# RUN: -exported_symbols_list %p/Inputs/exported_symbols_list.exp && \
-# RUN: llvm-nm -m %t | FileCheck -check-prefix=CHECK_DEAD %s
-#
-# Test -exported_symbols_list and -exported_symbol properly changes visibility.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
- 0x89, 0xE5, 0x5D, 0xC3 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x000000000000000C
- content: [ 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 ]
-
-global-symbols:
- - name: _a
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x000000000000000C
- - name: _b
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x0000000000000010
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000006
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
-
-...
-
-# CHECK: (__DATA,__data) non-external (was a private external) _a
-# CHECK: (__DATA,__data) external _b
-# CHECK: (__TEXT,__text) non-external (was a private external) _bar
-# CHECK: (__TEXT,__text) external _foo
-
-# CHECK_DEAD-NOT: (__DATA,__data) non-external (was a private external) _a
-# CHECK_DEAD: (__DATA,__data) external _b
-# CHECK_DEAD-NOT: (__TEXT,__text) non-external (was a private external) _bar
-# CHECK_DEAD: (__TEXT,__text) external _foo
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -o %t -exported_symbol _bar \
-# RUN: && llvm-nm -m %t | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -o %t2 -keep_private_externs \
-# RUN: -exported_symbol _bar && \
-# RUN: llvm-nm -m %t2 | FileCheck -check-prefix=CHECK_KPE %s
-#
-# RUN: not ld64.lld.darwinold -arch x86_64 -r %s -o %t3 \
-# RUN: -exported_symbol _foo 2> %t4
-
-# Test -exported_symbols_list properly changes visibility in -r mode.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
- 0x89, 0xE5, 0x5D, 0xC3 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x000000000000000C
- content: [ 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 ]
-
-global-symbols:
- - name: _a
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x000000000000000C
- - name: _b
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 2
- value: 0x0000000000000010
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000006
- - name: _foo
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000000
-
-
-...
-
-# CHECK: (__DATA,__data) non-external (was a private external) _a
-# CHECK: (__DATA,__data) non-external (was a private external) _b
-# CHECK: (__TEXT,__text) external _bar
-# CHECK: (__TEXT,__text) non-external (was a private external) _foo
-
-# CHECK_KPE: (__DATA,__data) non-external (was a private external) _a
-# CHECK_KPE: (__DATA,__data) private external _b
-# CHECK_KPE: (__TEXT,__text) external _bar
-# CHECK_KPE: (__TEXT,__text) private external _foo
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 -dylib \
-# RUN: %s %p/Inputs/x86_64/libSystem.yaml -o %t -exported_symbol _foobar 2> %t2
-#
-# Test -exported_symbol fails if exported symbol not found.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
- 0x89, 0xE5, 0x5D, 0xC3 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x000000000000000C
- content: [ 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 ]
-
-global-symbols:
- - name: _a
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x000000000000000C
- - name: _b
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x0000000000000010
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000006
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
-
-...
-
-# CHECK: (__DATA,__data) private external _a
-# CHECK: (__DATA,__data) external _b
-# CHECK: (__TEXT,__text) private external _bar
-# CHECK: (__TEXT,__text) external _foo
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t \
-# RUN: -L %p/Inputs -lfoo %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-nm -m -n %t | FileCheck %s
-#
-# Test that fat archives are handled.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
- 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0,
- 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0,
- 0x48, 0x83, 0xC4, 0x10, 0x5D, 0xC3 ]
- relocations:
- - offset: 0x00000012
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _foo
+++ /dev/null
-# RUN: ld64.lld.darwinold -test_file_usage \
-# RUN: -filelist %p/Inputs/full.filelist \
-# RUN: -path_exists /foo/bar/a.o \
-# RUN: -path_exists /foo/bar/b.o \
-# RUN: -path_exists /foo/x.a \
-# RUN: 2>&1 | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -test_file_usage -t \
-# RUN: -filelist %p/Inputs/partial.filelist,/foo \
-# RUN: -path_exists /foo/bar/a.o \
-# RUN: -path_exists /foo/bar/b.o \
-# RUN: -path_exists /foo/x.a \
-# RUN: 2>&1 | FileCheck %s
-
-
-# CHECK: Found filelist entry /foo/bar/a.o
-# CHECK: Found filelist entry /foo/bar/b.o
-# CHECK: Found filelist entry /foo/x.a
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.9 -flat_namespace -undefined error %s -o %t %p/Inputs/x86_64/libSystem.yaml 2>&1 | FileCheck %s
-
---- !native
-defined-atoms:
- - name: _main
- scope: global
- content: [ E9, 00, 00, 00, 00 ]
- alignment: 16
- references:
- - kind: branch32
- offset: 1
- target: _bar
-undefined-atoms:
- - name: _bar
-
-# Make sure we error out for -flat_namespace -undefined error.
-# CHECK: Undefined symbol: : _bar
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.9 -flat_namespace -undefined suppress %s -o %t %p/Inputs/x86_64/libSystem.yaml
-#
-# Sanity check '-flat_namespace -undefined suppress'.
-# This should pass without error, even though '_bar' is undefined.
-
---- !native
-defined-atoms:
- - name: _main
- scope: global
- content: [ E9, 00, 00, 00, 00 ]
- alignment: 16
- references:
- - kind: branch32
- offset: 1
- target: _bar
-undefined-atoms:
- - name: _bar
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -dylib %p/Inputs/bar.yaml \
-# RUN: -install_name /usr/lib/libbar.dylib %p/Inputs/x86_64/libSystem.yaml -o %t1.dylib
-# RUN: ld64.lld.darwinold -arch x86_64 -dylib %s -all_load %t1.dylib \
-# RUN: -install_name /usr/lib/libfoo.dylib %p/Inputs/x86_64/libSystem.yaml -o %t
-# RUN: llvm-nm -m %t | FileCheck %s
-#
-#
-# Test -all_load does not break linking with dylibs
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
- 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000008
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _bar
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-
-# CHECK: (__TEXT,__text) external _foo
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/x86_64/libSystem.yaml \
-# RUN: %p/Inputs/libfoo.a %p/Inputs/libbar.a -o %t1
-# RUN: llvm-nm -m -n %t1 | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/x86_64/libSystem.yaml \
-# RUN: -force_load %p/Inputs/libfoo.a %p/Inputs/libbar.a -o %t2
-# RUN: llvm-nm -m -n %t2 | FileCheck --check-prefix=CHECKF %s
-#
-# Test that -force_load causes members of static library to be loaded.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xC3 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
-# CHECK-NOT: {{[0-9a-f]+}} (__TEXT,__text) external _main
-
-# CHECKF: {{[0-9a-f]+}} (__TEXT,__text) external _main
-# CHECKF: {{[0-9a-f]+}} (__TEXT,__text) external _foo
-# CHECKF-NOT: {{[0-9a-f]+}} (__TEXT,__text) external _bar
+++ /dev/null
-#
-# Test framework and SDK search paths.
-# myFrameworks is not an absolute path, so it should not by found in SDK
-# /Custom/Frameworks should be found in SDK
-# /opt/Frameworks should not be found in SDK
-# /System/Library/Frameworks is implicit and should be in SDK
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -r -test_file_usage -v \
-# RUN: -path_exists myFrameworks \
-# RUN: -path_exists myFrameworks/my.framework/my \
-# RUN: -path_exists /opt/Frameworks \
-# RUN: -path_exists /opt/Frameworks/other.framework/other \
-# RUN: -path_exists /Custom/Frameworks \
-# RUN: -path_exists /Custom/Frameworks/Bar.framework/Bar \
-# RUN: -path_exists /System/Library/Frameworks \
-# RUN: -path_exists /System/Library/Frameworks/Foo.framework/Foo \
-# RUN: -path_exists /SDK/myFrameworks \
-# RUN: -path_exists /SDK/myFrameworks/my.framework/my \
-# RUN: -path_exists /SDK/Custom/Frameworks \
-# RUN: -path_exists /SDK/Custom/Frameworks/Bar.framework/Bar \
-# RUN: -path_exists /SDK/System/Library/Frameworks \
-# RUN: -path_exists /SDK/System/Library/Frameworks/Foo.framework/Foo \
-# RUN: -syslibroot /SDK \
-# RUN: -FmyFrameworks \
-# RUN: -F/Custom/Frameworks \
-# RUN: -F/opt/Frameworks \
-# RUN: -framework my \
-# RUN: -framework Bar \
-# RUN: -framework Foo \
-# RUN: -framework other \
-# RUN: 2>&1 | FileCheck %s
-
-# CHECK: Framework search paths:
-# CHECK-NEXT: myFrameworks
-# CHECK-NEXT: /SDK/Custom/Frameworks
-# CHECK-NEXT: /opt/Frameworks
-# CHECK-NEXT: /SDK/System/Library/Frameworks
-# CHECK: Found framework myFrameworks/my.framework/my
-# CHECK: Found framework /SDK/Custom/Frameworks/Bar.framework/Bar
-# CHECK: Found framework /SDK/System/Library/Frameworks/Foo.framework/Foo
-# CHECK: Found framework /opt/Frameworks/other.framework/other
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -static -function_starts && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -no_function_starts && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_FUNCTION_STARTS
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -static -function_starts -no_function_starts && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_FUNCTION_STARTS
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -static && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_FUNCTION_STARTS
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# CHECK: Load command {{[0-9]*}}
-# CHECK: cmd LC_FUNCTION_STARTS
-# CHECK: cmdsize 16
-# CHECK: dataoff
-# CHECK: datasize
-
-# NO_FUNCTION_STARTS-NOT: LC_FUNCTION_STARTS
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 %s \
-# RUN: -dylib %p/Inputs/arm64/libSystem.yaml -o %t
-# RUN: llvm-objdump --section-headers %t | FileCheck %s
-
-# Make sure that the GOT relocation from gcc_except_tab to the data
-# is not removed.
-
---- !native
-defined-atoms:
- - name: _main
- scope: global
- content: [ FD, 7B, BF, A9, FD, 03, 00, 91, FF, 43, 00, D1,
- BF, C3, 1F, B8, 00, 00, 00, 94, BF, 03, 00, 91,
- FD, 7B, C1, A8, C0, 03, 5F, D6 ]
- alignment: 4
- - name: __ZTSP1A
- scope: hidden
- type: constant
- content: [ 50, 31, 41, 00 ]
- merge: as-weak
- - name: GCC_except_table0
- type: unwind-lsda
- content: [ FF, 9B, E7, 80, 00, 03, 5B, 00, 00, 00, 00, 1C,
- 00, 00, 00, 00, 00, 00, 00, 00, 1C, 00, 00, 00,
- 18, 00, 00, 00, 84, 00, 00, 00, 03, 40, 00, 00,
- 00, 10, 00, 00, 00, 94, 00, 00, 00, 03, 60, 00,
- 00, 00, 20, 00, 00, 00, B4, 00, 00, 00, 05, 80,
- 00, 00, 00, 68, 00, 00, 00, 00, 00, 00, 00, 00,
- E8, 00, 00, 00, 08, 00, 00, 00, 28, 01, 00, 00,
- 00, F0, 00, 00, 00, 74, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 01, 7D, 01, 00, A8, FF, FF, FF ]
- alignment: 4
- references:
- - kind: delta32ToGOT
- offset: 104
- target: __ZTIP1A
- - name: __ZTIP1A
- scope: hidden
- type: data
- content: [ 10, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 80, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00 ]
- merge: as-weak
- alignment: 16
-shared-library-atoms:
- - name: dyld_stub_binder
- load-name: /usr/lib/libSystem.B.dylib
- type: unknown
-...
-
-# Make sure we have a GOT relocation.
-# This could only have come from __gcc_except_tab to __ZTIP1A
-# CHECK: __got
\ No newline at end of file
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/got-order.yaml \
-# RUN: %p/Inputs/got-order2.yaml -o %t %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-objdump --macho --bind %t | FileCheck %s
-#
-# Test that GOT slots are sorted by name
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x0D, 0x00,
- 0x00, 0x00, 0x00, 0x48, 0x8B, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0x8B, 0x00, 0x03, 0x01, 0x48, 0x8B,
- 0x0D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x5D,
- 0xC3 ]
- relocations:
- - offset: 0x00000019
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x0000000E
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000007
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
-global-symbols:
- - name: _func
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _aaa
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _fff
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _zzz
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-
-# CHECK: __DATA __got {{[0-9a-zA-Z _]+}} pointer 0 libfoobar _aaa
-# CHECK-NEXT: __DATA __got {{[0-9a-zA-Z _]+}} pointer 0 libfoobar _bar
-# CHECK-NEXT: __DATA __got {{[0-9a-zA-Z _]+}} pointer 0 libfoobar _fff
-# CHECK-NEXT: __DATA __got {{[0-9a-zA-Z _]+}} pointer 0 libfoobar _foo
-# CHECK-NEXT: __DATA __got {{[0-9a-zA-Z _]+}} pointer 0 libfoobar _zazzle
-# CHECK-NEXT: __DATA __got {{[0-9a-zA-Z _]+}} pointer 0 libfoobar _zzz
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 %s %p/Inputs/hello-world-arm64.yaml -o %t
-# RUN: llvm-nm -m -n %t | FileCheck %s
-# RUN: llvm-objdump --private-headers %t | FileCheck %s --check-prefix=CHECK-PRIVATE-HEADER
-#
-# Test that arm64 hello-world can be linked into a mach-o executable
-#
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
- 0x08, 0x00, 0x00, 0x90, 0x08, 0x01, 0x40, 0xF9,
- 0x00, 0x01, 0x40, 0xF9, 0x01, 0x00, 0x00, 0x90,
- 0x21, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x94,
- 0x00, 0x00, 0x80, 0x52, 0xFD, 0x7B, 0xC1, 0xA8,
- 0xC0, 0x03, 0x5F, 0xD6 ]
- relocations:
- - offset: 0x0000001C
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 5
- - offset: 0x00000018
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 1
- - offset: 0x00000014
- type: ARM64_RELOC_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x0000000C
- type: ARM64_RELOC_GOT_LOAD_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000008
- type: ARM64_RELOC_GOT_LOAD_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x000000000000002C
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
-local-symbols:
- - name: ltmp0
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: l_.str
- type: N_SECT
- sect: 2
- value: 0x000000000000002C
- - name: ltmp1
- type: N_SECT
- sect: 2
- value: 0x000000000000002C
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: ___stdoutp
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _fprintf
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: (undefined) external ___stdoutp (from libSystem)
-# CHECK: (undefined) external _fprintf (from libSystem)
-# CHECK: (undefined) external dyld_stub_binder (from libSystem)
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
-
-# CHECK-PRIVATE-HEADER: sectname __stubs
-# CHECK-PRIVATE-HEADER-NEXT: segname __TEXT
-# CHECK-PRIVATE-HEADER-NEXT: addr
-# CHECK-PRIVATE-HEADER-NEXT: size
-# CHECK-PRIVATE-HEADER-NEXT: offset
-# CHECK-PRIVATE-HEADER-NEXT: align 2^1 (2)
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch armv6 %s %p/Inputs/hello-world-armv6.yaml -o %t
-# RUN: llvm-nm -m %t | FileCheck %s
-#
-# Test that armv6 (arm) hello-world can be linked into a mach-o executable
-#
-
---- !mach-o
-arch: armv6
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x80, 0x40, 0x2D, 0xE9, 0x10, 0x00, 0x9F, 0xE5,
- 0x0D, 0x70, 0xA0, 0xE1, 0x00, 0x00, 0x8F, 0xE0,
- 0xFA, 0xFF, 0xFF, 0xEB, 0x00, 0x00, 0xA0, 0xE3,
- 0x80, 0x80, 0xBD, 0xE8, 0x0C, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x0000001C
- scattered: true
- type: ARM_RELOC_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000020
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000000C
- - offset: 0x00000010
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000020
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _printf
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
-# CHECK: (undefined) external _printf (from libSystem)
-# CHECK: (undefined) external dyld_stub_binder (from libSystem)
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch armv7 %s %p/Inputs/hello-world-armv7.yaml -o %t
-# RUN: llvm-nm -m -n %t | FileCheck %s
-#
-# Test that armv7 (thumb) hello-world can be linked into a mach-o executable
-#
-
---- !mach-o
-arch: armv7
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x80, 0xB5, 0x40, 0xF2, 0x06, 0x00, 0x6F, 0x46,
- 0xC0, 0xF2, 0x00, 0x00, 0x78, 0x44, 0xFF, 0xF7,
- 0xF8, 0xEF, 0x00, 0x20, 0x80, 0xBD ]
- relocations:
- - offset: 0x0000000E
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000008
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 3
- pc-rel: false
- value: 0x00000016
- - offset: 0x00000006
- scattered: true
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- value: 0x0000000C
- - offset: 0x00000002
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000016
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000000C
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000016
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000000
-undefined-symbols:
- - name: _printf
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: (undefined) external _printf (from libSystem)
-# CHECK: (undefined) external dyld_stub_binder (from libSystem)
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external [Thumb] _main
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 %s %p/Inputs/hello-world-x86.yaml -o %t
-# RUN: llvm-nm -m %t | FileCheck %s
-#
-# Test that i386 hello-world can be linked into a mach-o executable
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0x58, 0x8D, 0x80, 0x16, 0x00,
- 0x00, 0x00, 0x89, 0x04, 0x24, 0xE8, 0xE6, 0xFF,
- 0xFF, 0xFF, 0x31, 0xC0, 0x83, 0xC4, 0x08, 0x5D,
- 0xC3 ]
- relocations:
- - offset: 0x00000016
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x0000000E
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000021
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000000B
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000021
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _printf
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
-# CHECK: (undefined) external _printf (from libSystem)
-# CHECK: (undefined) external dyld_stub_binder (from libSystem)
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/hello-world-x86_64.yaml \
-# RUN: -o %t
-# RUN: llvm-nm -m -n %t | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/hello-world-x86_64.yaml \
-# RUN: -dead_strip -o %t2
-# RUN: llvm-nm -m -n %t2 | FileCheck %s
-#
-# Test that x86_64 hello-world can be linked into a mach-o executable
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x05, 0x00,
- 0x00, 0x00, 0x00, 0x48, 0x8B, 0x38, 0x48, 0x8D,
- 0x35, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0, 0xE8,
- 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0, 0x5D, 0xC3 ]
- relocations:
- - offset: 0x00000018
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 5
- - offset: 0x00000011
- type: X86_64_RELOC_SIGNED
- length: 2
- pc-rel: true
- extern: true
- symbol: 0
- - offset: 0x00000007
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000020
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
- - segment: __LD
- section: __compact_unwind
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000028
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - segment: __TEXT
- section: __eh_frame
- type: S_COALESCED
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000048
- content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
- 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
- 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
-local-symbols:
- - name: L1
- type: N_SECT
- sect: 2
- value: 0x0000000000000020
- - name: EH_frame0
- type: N_SECT
- sect: 4
- value: 0x0000000000000048
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _main.eh
- type: N_SECT
- scope: [ N_EXT ]
- sect: 4
- value: 0x0000000000000060
-undefined-symbols:
- - name: ___stdoutp
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _fprintf
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-# CHECK: (undefined) external ___stdoutp (from libSystem)
-# CHECK: (undefined) external _fprintf (from libSystem)
-# CHECK: (undefined) external dyld_stub_binder (from libSystem)
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) [referenced dynamically] external __mh_execute_header
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.9 %s -o %t -image_base 31415926000 %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-readobj --macho-segment %t | FileCheck %s
-# RUN: not ld64.lld.darwinold -arch x86_64 -image_base 0x31415926530 %s >/dev/null 2> %t
-# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-MISPAGED
-# RUN: not ld64.lld.darwinold -arch x86_64 -image_base 1000 %s >/dev/null 2> %t
-# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-OVERLAP
-# RUN: not ld64.lld.darwinold -arch x86_64 -image_base hithere %s >/dev/null 2> %t
-# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-NOTHEX
-
---- !native
-defined-atoms:
- - name: _main
- scope: global
- content: []
-
-# CHECK: Segment {
-# CHECK: Cmd: LC_SEGMENT_64
-# CHECK: Name: __TEXT
-# CHECK-NEXT: Size: 152
-# CHECK-NEXT: vmaddr: 0x31415926000
-# CHECK-NEXT: vmsize: 0x1000
-
-
-# CHECK-ERROR-MISPAGED: error: image_base must be a multiple of page size (0x1000)
-
-# CHECK-ERROR-OVERLAP: error: image_base overlaps with __PAGEZERO
-
-# CHECK-ERROR-NOTHEX: error: image_base expects a hex number
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -macosx_version_min 10.8 %s -r -o %t \
-# RUN: && ld64.lld.darwinold -r %t -o %t2 -print_atoms | FileCheck %s
-#
-# Test linker can detect architecture without -arch option.
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xC3 ]
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
-...
-
-
-# CHECK: defined-atoms:
-# CHECK: - name: _foo
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/interposing-section.yaml \
-# RUN: -dylib -o %t %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-objdump --private-headers %t | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 %s -r -o %t1
-# RUN: llvm-objdump --private-headers %t1 | FileCheck %s
-#
-# Test that interposing section is preserved by linker.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
- 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000008
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - segment: __DATA
- section: __interpose
- type: S_INTERPOSING
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000010
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000008
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
-local-symbols:
- - name: _my_open
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: __interpose_open
- type: N_SECT
- sect: 2
- desc: [ N_NO_DEAD_STRIP ]
- value: 0x0000000000000010
-undefined-symbols:
- - name: _open
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-
-# CHECK: sectname __interposing
-# CHECK: segname __DATA
-# CHECK: type S_INTERPOSING
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -o %t \
-# RUN: && llvm-nm -m %t | FileCheck %s
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -o %t2 -keep_private_externs \
-# RUN: && llvm-nm -m %t2 | FileCheck -check-prefix=CHECK_KPE %s
-#
-# Test -keep_private_externs in -r mode.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
- 0x89, 0xE5, 0x5D, 0xC3 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x000000000000000C
- content: [ 0x0A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00 ]
-
-global-symbols:
- - name: _a
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x000000000000000C
- - name: _b
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 2
- value: 0x0000000000000010
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000006
- - name: _foo
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000000
-
-
-...
-
-# CHECK: (__DATA,__data) external _a
-# CHECK: (__DATA,__data) non-external (was a private external) _b
-# CHECK: (__TEXT,__text) external _bar
-# CHECK: (__TEXT,__text) non-external (was a private external) _foo
-
-# CHECK_KPE: (__DATA,__data) external _a
-# CHECK_KPE: (__DATA,__data) private external _b
-# CHECK_KPE: (__TEXT,__text) external _bar
-# CHECK_KPE: (__TEXT,__text) private external _foo
+++ /dev/null
-# REQUIRES: x86
-
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s \
-# RUN: %p/Inputs/lazy-bind-x86_64.yaml %p/Inputs/lazy-bind-x86_64-2.yaml \
-# RUN: %p/Inputs/lazy-bind-x86_64-3.yaml -o %t \
-# RUN: %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-objdump --macho --lazy-bind %t | FileCheck %s
-# RUN: llvm-nm -m %t | FileCheck --check-prefix=CHECK-NM %s
-# RUN: llvm-objdump --disassemble %t | FileCheck --check-prefix=CHECK-HELPERS %s
-# RUN: llvm-objdump --private-headers %t | FileCheck --check-prefix=CHECK-DYLIBS %s
-#
-# Test that correct two-level namespace ordinals are used for lazy bindings.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0x31, 0xC0, 0xE8, 0x00, 0x00,
- 0x00, 0x00, 0x31, 0xC0, 0xE8, 0x00, 0x00, 0x00,
- 0x00, 0x31, 0xC0, 0x5D, 0xC3 ]
- relocations:
- - offset: 0x00000015
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x0000000E
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x00000007
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _bar
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _baz
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-
-# CHECK: libbar _bar
-# CHECK: libbaz _baz
-# CHECK: libfoo _foo
-
-
-# CHECK-NM: (undefined) external _bar (from libbar)
-# CHECK-NM: (undefined) external _baz (from libbaz)
-# CHECK-NM: (undefined) external _foo (from libfoo)
-
-
-# CHECK-HELPERS:Disassembly of section __TEXT,__stub_helper:
-# CHECK-HELPERS: 68 00 00 00 00 pushq $0
-# CHECK-HELPERS: 68 0b 00 00 00 pushq $11
-# CHECK-HELPERS: 68 16 00 00 00 pushq $22
-
-# Make sure the stub helper is correctly aligned
-# CHECK-DYLIBS: sectname __stub_helper
-# CHECK-DYLIBS-NEXT: segname __TEXT
-# CHECK-DYLIBS-NEXT: addr
-# CHECK-DYLIBS-NEXT: size
-# CHECK-DYLIBS-NEXT: offset
-# CHECK-DYLIBS-NEXT: align 2^2 (4)
-
-# Make sure the __nl_symbol_ptr section is used instea of __got as this is x86_64
-# CHECK-DYLIBS: sectname __nl_symbol_ptr
-# CHECK-DYLIBS-NEXT: segname __DATA
-
-# CHECK-DYLIBS: cmd LC_LOAD_DYLIB
-# CHECK-DYLIBS: name /usr/lib/libbar.dylib (offset 24)
-# CHECK-DYLIBS: current version 2.3.0
-# CHECK-DYLIBS: compatibility version 1.0.0
-# CHECK-DYLIBS: cmd LC_LOAD_DYLIB
-# CHECK-DYLIBS: name /usr/lib/libfoo.dylib (offset 24)
-# CHECK-DYLIBS: current version 3.4.0
-# CHECK-DYLIBS: compatibility version 2.0.0
-# CHECK-DYLIBS: cmd LC_LOAD_DYLIB
-# CHECK-DYLIBS: name /usr/lib/libbaz.dylib (offset 24)
-# CHECK-DYLIBS: current version 4.5.0
-# CHECK-DYLIBS: compatibility version 3.0.0
-
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -o %t %s && llvm-objdump --private-headers %t | FileCheck %s
-
-# CHECK: filesize 19
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
- alignment: 16
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00 ]
- - segment: __TEXT
- section: __alt
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
- alignment: 16
- address: 0x0000000000000010
- content: [ 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-page-size: 0x00000000
-...
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s -syslibroot %p/Inputs/lib-search-paths -lmyshared -lmystatic -lfile.o -r -print_atoms 2>&1 | FileCheck %s
-
---- !native
-undefined-atoms:
- - name: _from_myshared
- - name: _from_mystatic
- - name: _from_fileo
-
-# CHECK: defined-atoms:
-# CHECK: - name: _from_fileo
-# CHECK: content: [ 2A, 00, 00, 00 ]
-# CHECK: - name: _from_mystatic
-# CHECK: content: [ 02, 00, 00, 00 ]
-# CHECK: shared-library-atoms:
-# CHECK: - name: _from_myshared
-# CHECK: load-name: libmyshared.dylib
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %p/Inputs/libfoo.a %s -o %t \
-# RUN: %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-nm -m -n %t | FileCheck %s
-#
-# Test that if library is before object file on command line, it still is used.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
- 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0,
- 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0,
- 0x48, 0x83, 0xC4, 0x10, 0x5D, 0xC3 ]
- relocations:
- - offset: 0x00000012
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _foo
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %p/Inputs/libfoo.a %p/Inputs/libbar.a \
-# RUN: %s -o %t %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-nm -m -n %t | FileCheck %s
-#
-# Test that static libraries are automatically rescanned (bar needs foo).
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
- 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0,
- 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0,
- 0x48, 0x83, 0xC4, 0x10, 0x5D, 0xC3 ]
- relocations:
- - offset: 0x00000012
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _bar
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _bar
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _foo
+++ /dev/null
-# RUN: not ld64.lld.darwinold -test_file_usage -v \
-# RUN: -path_exists /usr/lib \
-# RUN: -path_exists /Applications/MySDK/usr/local/lib \
-# RUN: -path_exists /Applications/MySDK/usr/lib \
-# RUN: -path_exists /Applications/MySDK/usr/lib/libSystem.dylib \
-# RUN: -syslibroot /Applications/MySDK \
-# RUN: -syslibroot / \
-# RUN: -lSystem \
-# RUN: 2>&1 | FileCheck %s
-
-# When the last -syslibroot is simply "/", all of them get discarded. So in this
-# case, only /usr/lib should show up.
-
-# CHECK: Library search paths:
-# CHECK: /usr/lib
-# CHECK-NOT: /usr/local/lib
-# CHECK: Unable to find library for -lSystem
+++ /dev/null
-# RUN: ld64.lld.darwinold -test_file_usage -v \
-# RUN: -path_exists /usr/lib \
-# RUN: -path_exists /Applications/MyFirstSDK/usr/local/lib \
-# RUN: -path_exists /Applications/MySecondSDK/usr/local/lib \
-# RUN: -path_exists /Applications/MyFirstSDK/usr/local/lib/libSystem.a \
-# RUN: -path_exists /Applications/MySecondSDK/usr/local/lib/libSystem.a \
-# RUN: -syslibroot /Applications/MyFirstSDK \
-# RUN: -syslibroot /Applications/MySecondSDK \
-# RUN: -lSystem \
-# RUN: 2>&1 | FileCheck %s
-
-
-# CHECK: Library search paths:
-# CHECK: /usr/lib
-# CHECK: /Applications/MyFirstSDK/usr/local/lib
-# CHECK: /Applications/MySecondSDK/usr/local/lib
-# CHECK: Found library /Applications/MyFirstSDK/usr/local/lib/libSystem.a
+++ /dev/null
-# RUN: ld64.lld.darwinold -test_file_usage -v \
-# RUN: -path_exists /usr/lib \
-# RUN: -path_exists /Applications/MySDK/usr/local/lib \
-# RUN: -path_exists /Applications/MySDK/usr/local/lib/libSystem.a \
-# RUN: -path_exists /hasFoo \
-# RUN: -path_exists /hasFoo/foo.o \
-# RUN: -syslibroot /Applications/MySDK \
-# RUN: -L/hasFoo \
-# RUN: -lSystem -lfoo.o \
-# RUN: 2>&1 | FileCheck %s
-
-# When just one -syslibroot is specified, we apparently want to skip *system*
-# paths that aren't found. User ones should still get added. In this case
-# /usr/lib exists, but not the equivalent in the -syslibroot, so there should be
-# no mention of /usr/lib.
-
-# CHECK: Library search paths:
-# CHECK: /hasFoo
-# CHECK-NOT: /usr/lib
-# CHECK-NOT: /usr/local/lib
-# CHECK: /Applications/MySDK/usr/local/lib
-# CHECK-NOT: /usr/lib
-# CHECK-NOT: /usr/local/lib
-# CHECK: Found library /Applications/MySDK/usr/local/lib/libSystem.a
-# CHECK: Found library /hasFoo/foo.o
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -test_file_usage -v \
-# RUN: -path_exists /usr/lib \
-# RUN: -path_exists /usr/local/lib \
-# RUN: -path_exists /usr/lib/libSystem.dylib \
-# RUN: -path_exists hasFoo \
-# RUN: -path_exists hasFoo/libFoo.dylib \
-# RUN: -path_exists /hasBar \
-# RUN: -path_exists /hasBar/libBar.dylib \
-# RUN: -L hasFoo \
-# RUN: -L /hasBar \
-# RUN: -lSystem -lFoo -lBar \
-# RUN: 2>&1 | FileCheck %s
-
-# CHECK: Library search paths:
-# CHECK: hasFoo
-# CHECK: /hasBar
-# CHECK: /usr/lib
-# CHECK: /usr/local/lib
-# CHECK: Found library /usr/lib/libSystem.dylib
-# CHECK: Found library hasFoo/libFoo.dylib
-# CHECK: Found library /hasBar/libBar.dylib
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -test_file_usage -v \
-# RUN: -path_exists hasFoo \
-# RUN: -path_exists hasFoo/libFoo.dylib \
-# RUN: -path_exists /hasBar \
-# RUN: -path_exists /hasBar/libBar.dylib \
-# RUN: -path_exists /SDK/hasFoo \
-# RUN: -path_exists /SDK/hasFoo/libFoo.dylib \
-# RUN: -path_exists /SDK/hasBar \
-# RUN: -path_exists /SDK/hasBar/libBar.dylib \
-# RUN: -syslibroot /SDK \
-# RUN: -L hasFoo \
-# RUN: -L /hasBar \
-# RUN: -lFoo -lBar \
-# RUN: 2>&1 | FileCheck %s
-
-# CHECK: Library search paths:
-# CHECK: hasFoo
-# CHECK: /SDK/hasBar
-# CHECK: Found library hasFoo/libFoo.dylib
-# CHECK: Found library /SDK/hasBar/libBar.dylib
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -test_file_usage -v \
-# RUN: -path_exists /usr/lib \
-# RUN: -path_exists /usr/local/lib \
-# RUN: -path_exists /usr/lib/libSystem.dylib \
-# RUN: -path_exists hasFoo \
-# RUN: -path_exists hasFoo/libFoo.dylib \
-# RUN: -path_exists /hasBar \
-# RUN: -path_exists /hasBar/libBar.dylib \
-# RUN: -L hasFoo \
-# RUN: -L /hasBar \
-# RUN: -Z \
-# RUN: -lFoo -lBar \
-# RUN: 2>&1 | FileCheck %s
-
-# CHECK: Library search paths:
-# CHECK: hasFoo
-# CHECK: /hasBar
-# CHECK-NOT: /usr/lib
-# CHECK-NOT: /usr/local/lib
-# CHECK: Found library hasFoo/libFoo.dylib
-# CHECK: Found library /hasBar/libBar.dylib
+++ /dev/null
-
-# mach-o test cases encode input files in yaml and use .yaml extension
-config.suffixes = ['.yaml']
-config.excludes = ['Inputs']
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s -o %t -dylib \
-# RUN: -macosx_version_min 10.10 -sdk_version 10.10 \
-# RUN: -install_name /usr/lib/foo.dylib \
-# RUN: %p/Inputs/x86_64/libSystem.yaml && \
-# RUN: llvm-readobj %t
-
-# (Tests that lld doesn't crash or produce an invalid file.)
-
---- !native
-path: '<linker-internal>'
-defined-atoms:
- - name: _foo
- scope: global
- type: unknown
- content: [ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00 ]
- alignment: 16
- section-choice: custom-required
- section-name: '__TEXT/__foo'
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.4 %s %p/Inputs/hello-world-x86_64.yaml -o %t && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_LIB64
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.5 %s %p/Inputs/hello-world-x86_64.yaml -o %t && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=LIB64
-# RUN: ld64.lld.darwinold -arch x86_64 -dylib -macosx_version_min 10.5 %s %p/Inputs/hello-world-x86_64.yaml -o %t && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=DYLIB
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: start
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
-
-...
-
-# NO_LIB64: MH_MAGIC_64 X86_64 ALL 0x00 EXECUTE
-# LIB64: MH_MAGIC_64 X86_64 ALL LIB64 EXECUTE
-# DYLIB: MH_MAGIC_64 X86_64 ALL 0x00 DYLIB
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s -bundle -o %t %p/Inputs/x86_64/libSystem.yaml && llvm-nm -m -n %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 %s -bundle -dead_strip -o %t %p/Inputs/x86_64/libSystem.yaml && llvm-nm -m -n %t | FileCheck %s
-#
-# Test that __mh_bundle_header symbol is available for bundles
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xC3 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000008
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
-global-symbols:
- - name: _d
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x0000000000000008
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_NO_DEAD_STRIP ]
- value: 0x0000000000000000
-undefined-symbols:
- - name: __mh_bundle_header
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-
-...
-
-# CHECK: __mh_bundle_header
-# CHECK: _foo
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s -dylib -o %t %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-nm -m -n %t | FileCheck %s
-#
-# Test that __mh_dylib_header symbol is available for dylibs
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xC3 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000008
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
-global-symbols:
- - name: _d
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x0000000000000008
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: __mh_dylib_header
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-
-...
-
-# CHECK_NOT: __mh_dylib_header
-# CHECK: _foo
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %t -o %t2 | FileCheck %s
-
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_catlist
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- alignment: 8
- address: 0x00000000000003F8
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000008
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 1
-undefined-symbols:
- - name: __category1
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: __category2
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-page-size: 0x00000000
-...
-
-# Make sure we atomize the category list section by pointer sized atoms.
-
-# CHECK: path: '<linker-internal>'
-# CHECK: defined-atoms:
-# CHECK: - type: objc-category-list
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: merge: by-content
-# CHECK: alignment: 8
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: __category2
-# CHECK: - type: objc-category-list
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: merge: by-content
-# CHECK: alignment: 8
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: __category1
-# CHECK: undefined-atoms:
-# CHECK: - name: __category1
-# CHECK: - name: __category2
-# CHECK: ...
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -r %s 2>&1 | FileCheck %s
-
-# The file is built for the host, but the objc image info flags are for
-# the simulator.
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_imageinfo
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 ]
-...
-
-# CHECK: {{.*}} cannot be linked. It contains ObjC built for the simulator while we are linking a non-simulator target
\ No newline at end of file
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -r %s 2>&1 | FileCheck %s
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_imageinfo
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
-...
-
-# CHECK: error: __DATA/__objc_imageinfo in file {{.*}} should be 8 bytes in size
\ No newline at end of file
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -r %s 2>&1 | FileCheck %s
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_imageinfo
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 ]
-...
-
-# CHECK: error: __DATA/__objc_imageinfo in file {{.*}} should have version=0
\ No newline at end of file
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -r %s %p/Inputs/swift-version-1.yaml 2>&1 | FileCheck %s
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_imageinfo
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00 ]
-...
-
-# CHECK: different swift versions
\ No newline at end of file
+++ /dev/null
-# RUN: ld64.lld.darwinold -ios_simulator_version_min 5.0 -arch x86_64 -r %s -o %t -print_atoms | FileCheck %s
-
-# Make sure that we have an objc image info in the output. It should have
-# been generated by the objc pass.
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_imageinfo
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00 ]
-...
-
-# CHECK: --- !native
-# CHECK: path: '<linker-internal>'
-# CHECK: defined-atoms:
-# CHECK: - scope: hidden
-# CHECK: type: objc-image-info
-# CHECK: content: [ 00, 00, 00, 00, 20, 02, 00, 00 ]
-# CHECK: alignment: 4
-# CHECK: ...
\ No newline at end of file
+++ /dev/null
-# RUN: not ld64.lld.darwinold -ios_simulator_version_min 5.0 -arch x86_64 -r %s 2>&1 | FileCheck %s
-
-# The file is built for the simulator, but the objc image info flags are for
-# the host.
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_imageinfo
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
-...
-
-# CHECK: {{.*}} cannot be linked. It contains ObjC built for a non-simulator target while we are linking a simulator target
\ No newline at end of file
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -r %s 2>&1 | FileCheck %s
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_imageinfo
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 ]
-...
-
-# CHECK: error: __DATA/__objc_imageinfo in file {{.*}} uses GC. This is not supported
\ No newline at end of file
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -dylib %s -o %t \
-# RUN: -exported_symbol .objc_class_name_Foo %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-nm -m %t | FileCheck %s
-#
-# Test that exported objc classes can be specificed using old naming
-# (.e.g .objc_class_name_Foo instead of _OBJC_CLASS_$_Foo)
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __DATA
- section: __objc_data
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000030
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000028
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 1
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 1
-global-symbols:
- - name: '_OBJC_CLASS_$_Foo'
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: '_OBJC_METACLASS_$_Foo'
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000028
-...
-
-# CHECK: (__DATA,__objc_data) external _OBJC_CLASS_$_Foo
-# CHECK: (__DATA,__objc_data) external _OBJC_METACLASS_$_Foo
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/x86_64/libSystem.yaml \
-# RUN: -order_file %p/Inputs/order_file-basic.order \
-# RUN: -force_load %p/Inputs/libfoo.a -o %t
-# RUN: llvm-nm -m -n %t | FileCheck %s
-#
-# Test -order_file
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xC3, 0xC3, 0xC3, 0xC3 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000014
- content: [ 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _data1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x0000000000000014
- - name: _data2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x0000000000000018
- - name: _data3
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x000000000000001C
- - name: _func1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _func2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _func3
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000002
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000003
-...
-
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _func2
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _foo
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _func1
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _func3
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
-# CHECK: {{[0-9a-f]+}} (__DATA,__data) external _data3
-# CHECK: {{[0-9a-f]+}} (__DATA,__data) external _data1
-# CHECK: {{[0-9a-f]+}} (__DATA,__data) external _data2
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test multiple labels to same address parse into aliases.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xCC, 0xC3 ]
-local-symbols:
- - name: _pad
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _myStaticAlias1
- type: N_SECT
- sect: 1
- value: 0x0000000000000001
- - name: _myStaticAlias3
- type: N_SECT
- sect: 1
- value: 0x0000000000000001
- - name: _myStaticAlias2
- type: N_SECT
- sect: 1
- value: 0x0000000000000001
-global-symbols:
- - name: _myGlobalFunc1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myGlobalFunc2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myGlobalFunc3
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myHiddenAlias1
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myHiddenAlias2
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myHiddenAlias3
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000001
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: _pad
-# CHECK: scope: global
-# CHECK: content: [ CC ]
-# CHECK: - name: _myStaticAlias1
-# CHECK: - name: _myStaticAlias2
-# CHECK: - name: _myStaticAlias3
-# CHECK: - name: _myHiddenAlias1
-# CHECK: scope: hidden
-# CHECK: - name: _myHiddenAlias2
-# CHECK: scope: hidden
-# CHECK: - name: _myHiddenAlias3
-# CHECK: scope: hidden
-# CHECK: - name: _myGlobalFunc1
-# CHECK: scope: global
-# CHECK: - name: _myGlobalFunc2
-# CHECK: scope: global
-# CHECK: - name: _myGlobalFunc3
-# CHECK: scope: global
-# CHECK: content: [ C3 ]
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch armv7 -r -print_atoms %s -o %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch armv7 -r -print_atoms %t -o %t2 | FileCheck %s
-#
-# Test parsing of armv7 relocations.
-#
-#
-
---- !mach-o
-arch: armv7
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x00, 0xF0, 0x4E, 0xF8, 0x00, 0xF0, 0x4E, 0xF8,
- 0xFF, 0xF7, 0xFA, 0xFF, 0xFF, 0xF7, 0xFA, 0xFF,
- 0xFF, 0xF7, 0xF6, 0xBF, 0x40, 0xF2, 0x72, 0x01,
- 0xC0, 0xF2, 0x00, 0x01, 0x40, 0xF2, 0x7A, 0x02,
- 0xC0, 0xF2, 0x00, 0x02, 0x40, 0xF2, 0x29, 0x01,
- 0xC0, 0xF2, 0x00, 0x01, 0x79, 0x44, 0x40, 0xF2,
- 0xA0, 0x03, 0xC0, 0xF2, 0x00, 0x03, 0x40, 0xF2,
- 0xA8, 0x04, 0xC0, 0xF2, 0x00, 0x04, 0x40, 0xF2,
- 0x57, 0x03, 0xC0, 0xF2, 0x00, 0x03, 0x40, 0xF2,
- 0x00, 0x05, 0xC0, 0xF2, 0x00, 0x05, 0x40, 0xF2,
- 0x08, 0x06, 0xC0, 0xF2, 0x00, 0x06, 0xC0, 0x46,
- 0x10, 0x00, 0x00, 0xEB, 0x10, 0x00, 0x00, 0xEB,
- 0xE6, 0xFF, 0xFF, 0xEB, 0xE6, 0xFF, 0xFF, 0xEB,
- 0xE4, 0xFF, 0xFF, 0xEA, 0x20, 0x10, 0x00, 0xE3,
- 0x00, 0x10, 0x40, 0xE3, 0x28, 0x20, 0x00, 0xE3,
- 0x00, 0x20, 0x40, 0xE3, 0x0F, 0x10, 0x81, 0xE0,
- 0xA0, 0x30, 0x00, 0xE3, 0x00, 0x30, 0x40, 0xE3,
- 0xA8, 0x40, 0x00, 0xE3, 0x00, 0x40, 0x40, 0xE3,
- 0x00, 0x50, 0x00, 0xE3, 0x00, 0x50, 0x40, 0xE3,
- 0x08, 0x60, 0x00, 0xE3, 0x00, 0x60, 0x40, 0xE3 ]
- relocations:
- - offset: 0x0000009C
- type: ARM_RELOC_HALF
- length: 1
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000008
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000098
- type: ARM_RELOC_HALF
- length: 0
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000094
- type: ARM_RELOC_HALF
- length: 1
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000090
- type: ARM_RELOC_HALF
- length: 0
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x0000008C
- scattered: true
- type: ARM_RELOC_HALF
- length: 1
- pc-rel: false
- value: 0x000000A0
- - offset: 0x000000A8
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000088
- scattered: true
- type: ARM_RELOC_HALF
- length: 0
- pc-rel: false
- value: 0x000000A0
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000084
- type: ARM_RELOC_HALF
- length: 1
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x000000A0
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000080
- type: ARM_RELOC_HALF
- length: 0
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000078
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 1
- pc-rel: false
- value: 0x000000A0
- - offset: 0x00000028
- scattered: true
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- value: 0x00000080
- - offset: 0x00000074
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 0
- pc-rel: false
- value: 0x000000A0
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- value: 0x00000080
- - offset: 0x00000070
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 1
- pc-rel: false
- value: 0x000000A0
- - offset: 0x00000020
- scattered: true
- type: ARM_RELOC_PAIR
- length: 1
- pc-rel: false
- value: 0x00000080
- - offset: 0x0000006C
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 0
- pc-rel: false
- value: 0x000000A0
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 0
- pc-rel: false
- value: 0x00000080
- - offset: 0x00000068
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x00000064
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x00000060
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x0000005C
- scattered: true
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- value: 0x000000A0
- - offset: 0x00000058
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: false
- symbol: 2
- - offset: 0x00000052
- type: ARM_RELOC_HALF
- length: 3
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000008
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x0000004E
- type: ARM_RELOC_HALF
- length: 2
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x0000004A
- type: ARM_RELOC_HALF
- length: 3
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000046
- type: ARM_RELOC_HALF
- length: 2
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000042
- type: ARM_RELOC_HALF
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000057
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x0000003E
- type: ARM_RELOC_HALF
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x0000003A
- scattered: true
- type: ARM_RELOC_HALF
- length: 3
- pc-rel: false
- value: 0x000000A0
- - offset: 0x000000A8
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000036
- scattered: true
- type: ARM_RELOC_HALF
- length: 2
- pc-rel: false
- value: 0x000000A0
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000032
- type: ARM_RELOC_HALF
- length: 3
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x000000A0
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x0000002E
- type: ARM_RELOC_HALF
- length: 2
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x00000000
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- extern: false
- symbol: 16777215
- - offset: 0x00000028
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 3
- pc-rel: false
- value: 0x00000056
- - offset: 0x00000028
- scattered: true
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- value: 0x0000002E
- - offset: 0x00000024
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000056
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000002E
- - offset: 0x00000020
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 3
- pc-rel: false
- value: 0x000000A0
- - offset: 0x0000007A
- scattered: true
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- value: 0x0000002E
- - offset: 0x0000001C
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x000000A0
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000002E
- - offset: 0x00000018
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 3
- pc-rel: false
- value: 0x000000A0
- - offset: 0x00000072
- scattered: true
- type: ARM_RELOC_PAIR
- length: 3
- pc-rel: false
- value: 0x0000002E
- - offset: 0x00000014
- scattered: true
- type: ARM_RELOC_HALF_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x000000A0
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000002E
- - offset: 0x00000010
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x0000000C
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x00000008
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x00000004
- scattered: true
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- value: 0x000000A0
- - offset: 0x00000000
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: false
- symbol: 2
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x00000000000000A0
- content: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0xA4, 0xFF, 0xFF, 0xFF,
- 0xA4, 0xFF, 0xFF, 0xFF, 0x45, 0xFF, 0xFF, 0xFF,
- 0x45, 0xFF, 0xFF, 0xFF ]
- relocations:
- - offset: 0x00000020
- scattered: true
- type: ARM_RELOC_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000000
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x000000C0
- - offset: 0x0000001C
- scattered: true
- type: ARM_RELOC_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000000
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x000000BC
- - offset: 0x00000018
- scattered: true
- type: ARM_RELOC_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000058
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x000000B8
- - offset: 0x00000014
- scattered: true
- type: ARM_RELOC_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000058
- - offset: 0x00000000
- scattered: true
- type: ARM_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x000000B4
- - offset: 0x00000010
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x0000000C
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 4
- - offset: 0x00000008
- scattered: true
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- value: 0x00000000
- - offset: 0x00000004
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
-local-symbols:
- - name: _foo_thumb
- type: N_SECT
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000000
- - name: _x
- type: N_SECT
- sect: 2
- value: 0x00000000000000A0
- - name: _t1
- type: N_SECT
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000056
- - name: _foo_arm
- type: N_SECT
- sect: 1
- value: 0x0000000000000058
-undefined-symbols:
- - name: _undef
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: _x
-# CHECK: type: data
-# CHECK: references:
-# CHECK: - kind: pointer32
-# CHECK: offset: 4
-# CHECK: target: _foo_thumb
-# CHECK-NOT: addend:
-# CHECK: - kind: pointer32
-# CHECK: offset: 8
-# CHECK: target: _foo_thumb
-# CHECK: addend: 4
-# CHECK: - kind: pointer32
-# CHECK: offset: 12
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: pointer32
-# CHECK: offset: 16
-# CHECK: target: _undef
-# CHECK: addend: 4
-# CHECK: - kind: delta32
-# CHECK: offset: 20
-# CHECK: target: _foo_arm
-# CHECK-NOT: addend:
-# CHECK: - kind: delta32
-# CHECK: offset: 24
-# CHECK: target: _foo_arm
-# CHECK: addend: 4
-# CHECK: - kind: delta32
-# CHECK: offset: 28
-# CHECK: target: _foo_thumb
-# CHECK-NOT: addend:
-# CHECK: - kind: delta32
-# CHECK: offset: 32
-# CHECK: target: _foo_thumb
-# CHECK: addend: 4
-# CHECK: - name: _foo_thumb
-# CHECK: references:
-# CHECK: - kind: modeThumbCode
-# CHECK: offset: 0
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 0
-# CHECK: target: _x
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 4
-# CHECK: target: _x
-# CHECK: addend: 4
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 8
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_bl22
-# CHECK: offset: 12
-# CHECK: target: _undef
-# CHECK: addend: 4
-# CHECK: - kind: thumb_b22
-# CHECK: offset: 16
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movw_funcRel
-# CHECK: offset: 20
-# CHECK: target: _x
-# CHECK: addend: -46
-# CHECK: - kind: thumb_movt_funcRel
-# CHECK: offset: 24
-# CHECK: target: _x
-# CHECK: addend: -46
-# CHECK: - kind: thumb_movw_funcRel
-# CHECK: offset: 28
-# CHECK: target: _x
-# CHECK: addend: -38
-# CHECK: - kind: thumb_movt_funcRel
-# CHECK: offset: 32
-# CHECK: target: _x
-# CHECK: addend: -38
-# CHECK: - kind: thumb_movw_funcRel
-# CHECK: offset: 36
-# CHECK: target: _t1
-# CHECK: addend: -46
-# CHECK: - kind: thumb_movt_funcRel
-# CHECK: offset: 40
-# CHECK: target: _t1
-# CHECK: addend: -46
-# CHECK: - kind: thumb_movw
-# CHECK: offset: 46
-# CHECK: target: _x
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movt
-# CHECK: offset: 50
-# CHECK: target: _x
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movw
-# CHECK: offset: 54
-# CHECK: target: _x
-# CHECK: addend: 8
-# CHECK: - kind: thumb_movt
-# CHECK: offset: 58
-# CHECK: target: _x
-# CHECK: addend: 8
-# CHECK: - kind: thumb_movw
-# CHECK: offset: 62
-# CHECK: target: _t1
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movt
-# CHECK: offset: 66
-# CHECK: target: _t1
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movw
-# CHECK: offset: 70
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movt
-# CHECK: offset: 74
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: thumb_movw
-# CHECK: offset: 78
-# CHECK: target: _undef
-# CHECK: addend: 8
-# CHECK: - kind: thumb_movt
-# CHECK: offset: 82
-# CHECK: target: _undef
-# CHECK: addend: 8
-# CHECK: - name: _t1
-# CHECK: content: [ C0, 46 ]
-# CHECK: references:
-# CHECK: - kind: modeThumbCode
-# CHECK: offset: 0
-# CHECK: - name: _foo_arm
-# CHECK: references:
-# CHECK-NOT: - kind: modeThumbCode
-# CHECK: - kind: arm_bl24
-# CHECK: offset: 0
-# CHECK: target: _x
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_bl24
-# CHECK: offset: 4
-# CHECK: target: _x
-# CHECK: addend: 4
-# CHECK: - kind: arm_bl24
-# CHECK: offset: 8
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_bl24
-# CHECK: offset: 12
-# CHECK: target: _undef
-# CHECK: addend: 4
-# CHECK: - kind: arm_b24
-# CHECK: offset: 16
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_movw_funcRel
-# CHECK: offset: 20
-# CHECK: target: _x
-# CHECK: addend: -40
-# CHECK: - kind: arm_movt_funcRel
-# CHECK: offset: 24
-# CHECK: target: _x
-# CHECK: addend: -40
-# CHECK: - kind: arm_movw_funcRel
-# CHECK: offset: 28
-# CHECK: target: _x
-# CHECK: addend: -32
-# CHECK: - kind: arm_movt_funcRel
-# CHECK: offset: 32
-# CHECK: target: _x
-# CHECK: addend: -32
-# CHECK: - kind: arm_movw
-# CHECK: offset: 40
-# CHECK: target: _x
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_movt
-# CHECK: offset: 44
-# CHECK: target: _x
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_movw
-# CHECK: offset: 48
-# CHECK: target: _x
-# CHECK: addend: 8
-# CHECK: - kind: arm_movt
-# CHECK: offset: 52
-# CHECK: target: _x
-# CHECK: addend: 8
-# CHECK: - kind: arm_movw
-# CHECK: offset: 56
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_movt
-# CHECK: offset: 60
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: arm_movw
-# CHECK: offset: 64
-# CHECK: target: _undef
-# CHECK: addend: 8
-# CHECK: - kind: arm_movt
-# CHECK: offset: 68
-# CHECK: target: _undef
-# CHECK: addend: 8
-# CHECK: undefined-atoms:
-# CHECK: - name: _undef
-
-
-
-
-# .align 2
-# .code 16
-# .thumb_func _foo_thumb
-#_foo_thumb:
-# bl _x
-# bl _x+4
-# bl _undef
-# bl _undef+4
-# b _undef
-# movw r1, :lower16:(_x-L1)
-# movt r1, :upper16:(_x-L1)
-# movw r2, :lower16:(_x+8-L1)
-# movt r2, :upper16:(_x+8-L1)
-# movw r1, :lower16:(_t1-L1)
-# movt r1, :upper16:(_t1-L1)
-# add r1, pc
-#L1:
-# movw r3, :lower16:_x
-# movt r3, :upper16:_x
-# movw r4, :lower16:_x+8
-# movt r4, :upper16:_x+8
-# movw r3, :lower16:_t1
-# movt r3, :upper16:_t1
-# movw r5, :lower16:_undef
-# movt r5, :upper16:_undef
-# movw r6, :lower16:_undef+8
-# movt r6, :upper16:_undef+8
-#
-# .thumb_func _t1
-#_t1:
-# nop
-#
-#
-# .code 32
-# .align 2
-#_foo_arm:
-# bl _x
-# bl _x+4
-# bl _undef
-# bl _undef+4
-# b _undef
-# movw r1, :lower16:(_x-L2)
-# movt r1, :upper16:(_x-L2)
-# movw r2, :lower16:(_x+8-L2)
-# movt r2, :upper16:(_x+8-L2)
-# add r1, pc
-#L2:
-# movw r3, :lower16:_x
-# movt r3, :upper16:_x
-# movw r4, :lower16:_x+8
-# movt r4, :upper16:_x+8
-# movw r5, :lower16:_undef
-# movt r5, :upper16:_undef
-# movw r6, :lower16:_undef+8
-# movt r6, :upper16:_undef+8
-#
-#
-# .data
-#_x: .long 0
-# .long _foo_thumb
-# .long _foo_thumb+4
-# .long _undef
-# .long _undef+4
-# .long _foo_arm - .
-# .long _foo_arm+4- .
-# .long _foo_thumb - .
-# .long _foo_thumb+4 - .
-#
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of mach-o functions.
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000000
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x74, 0x68,
- 0x65, 0x72, 0x65, 0x00 ]
- - segment: __DATA
- section: __cfstring
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000010
- content: [ 0x00, 0x00, 0x00, 0x00, 0xC8, 0x07, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xC8, 0x07, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000018
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000010
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000008
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 0
-undefined-symbols:
- - name: ___CFConstantStringClassReference
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: defined-atoms:
-# CHECK: - ref-name: [[STR1:L[L0-9]+]]
-# CHECK: scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 68, 65, 6C, 6C, 6F, 00 ]
-# CHECK: merge: by-content
-# CHECK: - ref-name: [[STR2:L[L0-9]+]]
-# CHECK: scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 74, 68, 65, 72, 65, 00 ]
-# CHECK: merge: by-content
-# CHECK: - scope: hidden
-# CHECK: type: cfstring
-# CHECK: merge: by-content
-# CHECK: references:
-# CHECK: - kind: pointer32
-# CHECK: offset: 0
-# CHECK: target: ___CFConstantStringClassReference
-# CHECK: - kind: pointer32
-# CHECK: offset: 8
-# CHECK: target: [[STR1]]
-# CHECK: - scope: hidden
-# CHECK: type: cfstring
-# CHECK: merge: by-content
-# CHECK: references:
-# CHECK: - kind: pointer32
-# CHECK: offset: 0
-# CHECK: target: ___CFConstantStringClassReference
-# CHECK: - kind: pointer32
-# CHECK: offset: 8
-# CHECK: target: [[STR2]]
-# CHECK:undefined-atoms:
-# CHECK: - name: ___CFConstantStringClassReference
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of CFString constants.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000000
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x74, 0x68,
- 0x65, 0x72, 0x65, 0x00 ]
- - segment: __DATA
- section: __cfstring
- type: S_REGULAR
- attributes: [ ]
- alignment: 4
- address: 0x0000000000000010
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xC8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xC8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000030
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 1
- - offset: 0x00000020
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000010
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
-local-symbols:
- - name: Lstr1
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: Lstr2
- type: N_SECT
- sect: 1
- value: 0x0000000000000006
-undefined-symbols:
- - name: ___CFConstantStringClassReference
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK:defined-atoms:
-# CHECK: - ref-name: L000
-# CHECK: scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 68, 65, 6C, 6C, 6F, 00 ]
-# CHECK: merge: by-content
-# CHECK: - ref-name: L001
-# CHECK: scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 74, 68, 65, 72, 65, 00 ]
-# CHECK: merge: by-content
-# CHECK: - scope: hidden
-# CHECK: type: cfstring
-# CHECK: merge: by-content
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: ___CFConstantStringClassReference
-# CHECK: - kind: pointer64
-# CHECK: offset: 16
-# CHECK: target: L000
-# CHECK: - scope: hidden
-# CHECK: type: cfstring
-# CHECK: merge: by-content
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: ___CFConstantStringClassReference
-# CHECK: - kind: pointer64
-# CHECK: offset: 16
-# CHECK: target: L001
-# CHECK:undefined-atoms:
-# CHECK: - name: ___CFConstantStringClassReference
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of __LD/__compact_unwind (compact unwind) section.
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0xB8, 0x0A, 0x00, 0x00, 0x00,
- 0x5D, 0xC3, 0x55, 0x89, 0xE5, 0xB8, 0x0A, 0x00,
- 0x00, 0x00, 0x5D, 0xC3 ]
- - segment: __LD
- section: __compact_unwind
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x000000000000001C
- content: [ 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
- 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000014
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
-global-symbols:
- - name: __Z3barv
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000A
- - name: __Z3foov
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# CHECK: defined-atoms:
-# CHECK: - type: compact-unwind
-# CHECK: content: [ 00, 00, 00, 00, 0A, 00, 00, 00, 00, 00, 00, 01,
-# CHECK: 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: - type: compact-unwind
-# CHECK: content: [ 10, 00, 00, 00, 0A, 00, 00, 00, 00, 00, 00, 01,
-# CHECK: 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: - name: __Z3foov
-# CHECK: scope: global
-# CHECK: content: [ 55, 89, E5, B8, 0A, 00, 00, 00, 5D, C3 ]
-# CHECK: - name: __Z3barv
-# CHECK: scope: global
-# CHECK: content: [ 55, 89, E5, B8, 0A, 00, 00, 00, 5D, C3 ]
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of __LD/__compact_unwind (compact unwind) section.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0xB8, 0x0A, 0x00, 0x00,
- 0x00, 0x5D, 0xC3, 0x55, 0x48, 0x89, 0xE5, 0xB8,
- 0x0A, 0x00, 0x00, 0x00, 0x5D, 0xC3 ]
- - segment: __LD
- section: __compact_unwind
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000020
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000020
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
-global-symbols:
- - name: __Z3barv
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: __Z3foov
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000B
-...
-
-# CHECK: defined-atoms:
-# CHECK: - type: compact-unwind
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 0B, 00, 00, 00,
-# CHECK: 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: - type: compact-unwind
-# CHECK: content: [ 10, 00, 00, 00, 00, 00, 00, 00, 0B, 00, 00, 00,
-# CHECK: 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: - name: __Z3barv
-# CHECK: scope: global
-# CHECK: content: [ 55, 48, 89, E5, B8, 0A, 00, 00, 00, 5D, C3 ]
-# CHECK: - name: __Z3foov
-# CHECK: scope: global
-# CHECK: content: [ 55, 48, 89, E5, B8, 0A, 00, 00, 00, 5D, C3 ]
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch armv7 -r -print_atoms %s -o %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch armv7 -r -print_atoms %t -o %t2 | FileCheck %s
-# RUN: ld64.lld.darwinold -arch armv7 -dylib %s -o %t3.dylib %p/Inputs/armv7/libSystem.yaml \
-# RUN: && llvm-objdump --macho --private-headers %t3.dylib | FileCheck --check-prefix=CHECK2 %s
-#
-# Test parsing LC_DATA_IN_CODE
-#
-#
-
---- !mach-o
-arch: armv7
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x00, 0xBF, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x00, 0xBF,
- 0x00, 0xF0, 0x20, 0xE3, 0x0A, 0x00, 0x00, 0x00,
- 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
- 0x0D, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3 ]
-local-symbols:
- - name: _foo_thumb
- type: N_SECT
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000000
- - name: _foo_arm
- type: N_SECT
- sect: 1
- value: 0x0000000000000018
-dataInCode:
- - offset: 0x00000004
- length: 0x0004
- kind: DICE_KIND_DATA
- - offset: 0x00000008
- length: 0x0004
- kind: DICE_KIND_JUMP_TABLE32
- - offset: 0x0000000C
- length: 0x0004
- kind: DICE_KIND_JUMP_TABLE16
- - offset: 0x00000010
- length: 0x0004
- kind: DICE_KIND_JUMP_TABLE8
- - offset: 0x0000001C
- length: 0x0004
- kind: DICE_KIND_DATA
- - offset: 0x00000020
- length: 0x0004
- kind: DICE_KIND_JUMP_TABLE32
- - offset: 0x00000024
- length: 0x0004
- kind: DICE_KIND_JUMP_TABLE16
- - offset: 0x00000028
- length: 0x0004
- kind: DICE_KIND_JUMP_TABLE8
-...
-
-
-
-# CHECK: defined-atoms:
-# CHECK: - name: _foo_thumb
-# CHECK: references:
-# CHECK: - kind: modeThumbCode
-# CHECK: offset: 0
-# CHECK: - kind: modeData
-# CHECK: offset: 4
-# CHECK: addend: 1
-# CHECK: - kind: modeData
-# CHECK: offset: 8
-# CHECK: addend: 4
-# CHECK: - kind: modeData
-# CHECK: offset: 12
-# CHECK: addend: 3
-# CHECK: - kind: modeData
-# CHECK: offset: 16
-# CHECK: addend: 2
-# CHECK: - kind: modeThumbCode
-# CHECK: offset: 20
-# CHECK: - name: _foo_arm
-# CHECK: references:
-# CHECK: - kind: modeData
-# CHECK: offset: 4
-# CHECK: addend: 1
-# CHECK: - kind: modeData
-# CHECK: offset: 8
-# CHECK: addend: 4
-# CHECK: - kind: modeData
-# CHECK: offset: 12
-# CHECK: addend: 3
-# CHECK: - kind: modeData
-# CHECK: offset: 16
-# CHECK: addend: 2
-# CHECK: - kind: modeArmCode
-# CHECK: offset: 20
-
-
-# CHECK2: cmd LC_DATA_IN_CODE
-# CHECK2: cmdsize 16
-# CHECK2: datasize 64
-
-
-# .code 16
-# .thumb_func _foo_thumb
-#_foo_thumb:
-# nop
-# nop
-#
-# .data_region
-# .long 0
-# .end_data_region
-#
-# .data_region jt32
-# .long 1
-# .end_data_region
-#
-# .data_region jt16
-# .long 2
-# .end_data_region
-#
-# .data_region jt8
-# .long 3
-# .end_data_region
-#
-# nop
-# nop
-#
-#
-#
-# .code 32
-# .align 2
-#_foo_arm:
-# nop
-#
-# .data_region
-# .long 10
-# .end_data_region
-#
-# .data_region jt32
-# .long 11
-# .end_data_region
-#
-# .data_region jt16
-# .long 12
-# .end_data_region
-#
-# .data_region jt8
-# .long 13
-# .end_data_region
-#
-# nop
-#
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -r -print_atoms %s -o %t | FileCheck %s \
-# RUN: && ld64.lld.darwinold -arch i386 -r -print_atoms %t -o %t2 | FileCheck %s
-#
-# Test parsing LC_DATA_IN_CODE
-#
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x90, 0x90, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
- 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x03, 0x00,
- 0x00, 0x00 ]
-local-symbols:
- - name: _func1
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: _func2
- type: N_SECT
- sect: 1
- value: 0x000000000000000B
-dataInCode:
- - offset: 0x00000002
- length: 0x0008
- kind: DICE_KIND_JUMP_TABLE32
- - offset: 0x0000000E
- length: 0x0004
- kind: DICE_KIND_JUMP_TABLE32
-...
-
-
-
-# CHECK: defined-atoms:
-# CHECK: - name: _func1
-# CHECK: references:
-# CHECK: - kind: modeData
-# CHECK: offset: 2
-# CHECK: addend: 4
-# CHECK: - kind: modeCode
-# CHECK: offset: 10
-# CHECK: - name: _func2
-# CHECK: references:
-# CHECK: - kind: modeData
-# CHECK: offset: 3
-# CHECK: addend: 4
-# CHECK-NOT: - kind: modeData
-
-
-
-
-#
-#_func1:
-# nop
-# nop
-# .data_region jt32
-# .long 1
-# .long 2
-# .end_data_region
-# nop
-#
-#
-# _func2:
-# nop
-# nop
-# nop
-# .data_region jt32
-# .long 3
-# .end_data_region
-#
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 -r -print_atoms %s -o %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
-#
-# Test parsing and writing of arm64 data relocations.
-#
-# The first step tests if the supplied mach-o file is parsed into the correct
-# set of references. The second step verifies relocations can be round-tripped
-# by writing to a new .o file, then parsing that file which should result in
-# the same references.
-#
-#_test:
-
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xC0, 0x03, 0x5F, 0xD6 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x0000000000000004
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xC0, 0xFF, 0xFF, 0xFF, 0xBE, 0xFF, 0xFF, 0xFF,
- 0xB0, 0xFF, 0xFF, 0xFF ]
- relocations:
- - offset: 0x00000050
- type: ARM64_RELOC_POINTER_TO_GOT
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x0000004C
- type: ARM64_RELOC_SUBTRACTOR
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x0000004C
- type: ARM64_RELOC_UNSIGNED
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000048
- type: ARM64_RELOC_SUBTRACTOR
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000048
- type: ARM64_RELOC_UNSIGNED
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000040
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000038
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x00000030
- type: ARM64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000030
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000028
- type: ARM64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000028
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000020
- type: ARM64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000020
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000018
- type: ARM64_RELOC_POINTER_TO_GOT
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000010
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000008
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
-local-symbols:
- - name: _v1
- type: N_SECT
- sect: 2
- value: 0x000000000000000C
-global-symbols:
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-page-size: 0x00000000
-...
-
-# CHECK: defined-atoms:
-# CHECK: - ref-name: L000
-# CHECK: type: data
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: - name: _v1
-# CHECK: type: data
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 08, 00, 00, 00,
-# CHECK: 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 00, 00, 00, 00, 00, 00, 00, 00, E0, FF, FF, FF,
-# CHECK: FF, FF, FF, FF, DC, FF, FF, FF, FF, FF, FF, FF,
-# CHECK: {{..}}, {{..}}, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
-# CHECK: 00, 00, 00, 00, C0, FF, FF, FF, BE, FF, FF, FF,
-# CHECK: {{B0|B8}}, {{..}}, FF, FF ]
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: pointer64
-# CHECK: offset: 8
-# CHECK: target: _foo
-# CHECK: addend: 8
-# CHECK: - kind: pointer64ToGOT
-# CHECK: offset: 16
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: delta64
-# CHECK: offset: 24
-# CHECK: target: _foo
-# CHECK: addend: 24
-# CHECK: - kind: delta64
-# CHECK: offset: 32
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: delta64
-# CHECK: offset: 40
-# CHECK: target: _foo
-# CHECK: addend: 4
-# CHECK: - kind: pointer64
-# CHECK: offset: 48
-# CHECK: target: L000
-# CHECK-NOT: addend:
-# CHECK: - kind: pointer64
-# CHECK: offset: 56
-# CHECK: target: _foo
-# CHECK: addend: 4
-# CHECK: - kind: delta32
-# CHECK: offset: 64
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: delta32
-# CHECK: offset: 68
-# CHECK: target: _foo
-# CHECK: addend: 2
-# CHECK: - kind: delta32ToGOT
-# CHECK: offset: 72
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - name: _bar
-# CHECK: scope: global
-# CHECK: content: [ C0, 03, 5F, D6 ]
-# CHECK: alignment: 4
-# CHECK: undefined-atoms:
-# CHECK: - name: _foo
-
-# .subsections_via_symbols
-# .text
-# .globl_foo
-# .align2
-# _foo:
-# ret
-# .data
-#Lanon:
-# .quad 0
-#_v1:
-# .quad _foo
-# .quad _foo + 8
-# .quad _foo@GOT
-# .quad _foo + 24 - .
-# .quad _foo - .
-# .quad _foo + 4 - .
-# .quad Lanon
-# .quad Lanon + 4
-# .long _foo - .
-# .long _foo +2 - .
-# .long _foo@GOT - .
-
+++ /dev/null
-
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -o %t -print_atoms | FileCheck %s \
-# RUN: && ld64.lld.darwinold -arch x86_64 %t -r -print_atoms -o %t2 | FileCheck %s
-#
-# Test parsing and writing of x86_64 data relocations.
-#
-# The first step tests if the supplied mach-o file is parsed into the correct
-# set of references. The second step verifies relocations can be round-tripped
-# by writing to a new .o file, then parsing that file which should result in
-# the same references.
-#
-#_foo:
-# ret
-#
-#_bar:
-# ret
-#
-# .section __DATA,__custom
-#L1:
-# .quad 0
-#
-# .data
-#_d:
-# .quad _foo
-# .quad _foo+4
-# .quad _foo - .
-# .quad L1
-# .quad L1 + 2
-# .quad _foo - .
-# .quad _foo + 4 - .
-# .quad L1 - .
-# .long _foo - .
-# .long _foo + 4 - .
-# .long L1 - .
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xC3, 0xC3 ]
- - segment: __DATA
- section: __custom
- type: S_REGULAR
- attributes: [ ]
- address: 0x0000000000000002
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x000000000000000A
- content: [
-# .quad _foo
-# No addend is needed here as we are referencing _foo directly and that is
-# encoded entirely in the X86_64_RELOC_UNSIGNED
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-# .quad _foo+4
-# Addend of 4 is needed here as we are referencing _foo from the
-# X86_64_RELOC_UNSIGNED, then the addend gives us 4 more.
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-# .quad _foo - .
-# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
-# The subtractor references _d which is the first nonlocal label in this
-# section. The unsigned references _foo.
-# Note the addend here is -16 because that is the offset from here back
-# to _d.
- 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-# .quad . - _foo
-# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
-# The subtractor references _d which is the first nonlocal label in this
-# section. The unsigned references _foo.
-# Note the addend here is -16 because that is the offset from here back
-# to _d.
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-# .quad L1
-# This is a X86_64_RELOC_UNSIGNED without extern set.
-# In this case, we encode the section number for L1 in the relocation, and
-# the addend here is the absolute address of the location in that section
-# we want to reference.
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-# .quad L1 + 2
-# This is a X86_64_RELOC_UNSIGNED without extern set.
-# In this case, we encode the section number for L1 in the relocation, and
-# the addend here is the absolute address of the location in that section
-# we want to reference. We have a 4 because the section is at address 2
-# and we want an offset of 2 from there.
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-# .quad _foo - .
-# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
-# The subtractor references _d which is the first nonlocal label in this
-# section. The unsigned references _foo.
-# Note the addend here is -40 because that is the offset from here back
-# to _d.
- 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-# .quad _foo + 4 - .
-# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
-# The subtractor references _d which is the first nonlocal label in this
-# section. The unsigned references _foo.
-# Note the addend here is -52. It would have been -56 because that
-# would take us from the address of this relocation back to _d. But as
-# we also add 4 for the offset, we get -52.
- 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-# .quad L1 - .
-# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
-# The subtractor references _d which is the first nonlocal label in this
-# section. The unsigned does not have extern set, so the relocation
-# number is the section number for L1.
-# Note the addend here is -62. Of that, -64 would be the offset from
-# this location from _d. The remaining 2 is the absolute address
-# of L1.
- 0xC2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-# .long _foo - .
-# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
-# The subtractor references _d which is the first nonlocal label in this
-# section. The unsigned references _foo.
-# Note the addend here is -72 because that is the offset from here back
-# to _d.
- 0xB8, 0xFF, 0xFF, 0xFF,
-# .long . - _foo
-# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
-# The subtractor references _d which is the first nonlocal label in this
-# section. The unsigned references _foo.
-# Note the addend here is -76 because that is the offset from here back
-# to _d.
- 0xB4, 0xFF, 0xFF, 0xFF,
-# .long _foo + 4 - .
-# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
-# The subtractor references _d which is the first nonlocal label in this
-# section. The unsigned references _foo.
-# Note the addend here is -76. It would have been -80 because that
-# would take us from the address of this relocation back to _d. But as
-# we also add 4 for the offset, we get -76.
- 0xB4, 0xFF, 0xFF, 0xFF,
-# .long L1 - .
-# This is the pair X86_64_RELOC_SUBTRACTOR and X86_64_RELOC_UNSIGNED.
-# The subtractor references _d which is the first nonlocal label in this
-# section. The unsigned does not have extern set, so the relocation
-# number is the section number for L1.
-# Note the addend here is -82. Of that, -84 would be the offset from
-# this location from _d. The remaining 2 is the absolute address
-# of L1.
- 0xAE, 0xFF, 0xFF, 0xFF ]
- relocations:
- - offset: 0x00000054
- type: X86_64_RELOC_SUBTRACTOR
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000054
- type: X86_64_RELOC_UNSIGNED
- length: 2
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x00000050
- type: X86_64_RELOC_SUBTRACTOR
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000050
- type: X86_64_RELOC_UNSIGNED
- length: 2
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x0000004C
- type: X86_64_RELOC_SUBTRACTOR
- length: 2
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x0000004C
- type: X86_64_RELOC_UNSIGNED
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000048
- type: X86_64_RELOC_SUBTRACTOR
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000048
- type: X86_64_RELOC_UNSIGNED
- length: 2
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000040
- type: X86_64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000040
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x00000038
- type: X86_64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000038
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000030
- type: X86_64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000030
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000028
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x00000020
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x00000018
- type: X86_64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000018
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000010
- type: X86_64_RELOC_SUBTRACTOR
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000010
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000008
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
-local-symbols:
- - name: _foo
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: _bar
- type: N_SECT
- sect: 1
- value: 0x0000000000000001
- - name: _d
- type: N_SECT
- sect: 3
- value: 0x000000000000000A
-page-size: 0x00000000
-...
-
-
-# CHECK:defined-atoms:
-# CHECK: - name: _d
-# CHECK: type: data
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 04, 00, 00, 00,
-# CHECK: 00, 00, 00, 00, F0, FF, FF, FF, FF, FF, FF, FF,
-# CHECK: 18, 00, 00, 00, 00, 00, 00, 00, {{..}}, {{..}}, 00, 00,
-# CHECK: 00, 00, 00, 00, {{..}}, {{..}}, 00, 00, 00, 00, 00, 00,
-# CHECK: D0, FF, FF, FF, FF, FF, FF, FF, CC, FF, FF, FF,
-# CHECK: FF, FF, FF, FF, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}}, {{..}},
-# CHECK: B8, FF, FF, FF, B4, FF, FF, FF, B4, FF, FF, FF,
-# CHECK: {{..}}, {{..}}, {{..}}, {{..}} ]
-# CHECK: dead-strip: never
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: _foo
-# CHECK: - kind: pointer64
-# CHECK: offset: 8
-# CHECK: target: _foo
-# CHECK: addend: 4
-# CHECK: - kind: delta64
-# CHECK: offset: 16
-# CHECK: target: _foo
-# CHECK: - kind: negDelta64
-# CHECK: offset: 24
-# CHECK: target: _foo
-# CHECK: - kind: pointer64Anon
-# CHECK: offset: 32
-# CHECK: target: L003
-# CHECK: - kind: pointer64Anon
-# CHECK: offset: 40
-# CHECK: target: L003
-# CHECK: addend: 2
-# CHECK: - kind: delta64
-# CHECK: offset: 48
-# CHECK: target: _foo
-# CHECK: - kind: delta64
-# CHECK: offset: 56
-# CHECK: target: _foo
-# CHECK: addend: 4
-# CHECK: - kind: delta64Anon
-# CHECK: offset: 64
-# CHECK: target: L003
-# CHECK: - kind: delta32
-# CHECK: offset: 72
-# CHECK: target: _foo
-# CHECK: - kind: negDelta32
-# CHECK: offset: 76
-# CHECK: target: _foo
-# CHECK: - kind: delta32
-# CHECK: offset: 80
-# CHECK: target: _foo
-# CHECK: addend: 4
-# CHECK: - kind: delta32Anon
-# CHECK: offset: 84
-# CHECK: target: L003
-# CHECK: - name: _foo
-# CHECK: content: [ C3 ]
-# CHECK: dead-strip: never
-# CHECK: - name: _bar
-# CHECK: content: [ C3 ]
-# CHECK: dead-strip: never
-# CHECK: - ref-name: L003
-# CHECK: type: unknown
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: section-choice: custom-required
-# CHECK: section-name: '__DATA/__custom'
-# CHECK: dead-strip: never
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of mach-o data symbols.
-#
-# long a = 0x0807060504030201;
-# int b = 0x14131211;
-# int c = 0x24232221;
-# static int s1;
-# static int s2 = 0x34333231;
-#
-#
-
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000000
- content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x11, 0x12, 0x13, 0x14, 0x21, 0x22, 0x23, 0x24,
- 0x31, 0x32, 0x33, 0x34, 0x41, 0x42, 0x43, 0x44 ]
- - segment: __CUST
- section: __custom
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000018
- content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ]
- - segment: __DATA
- section: __bss
- type: S_ZEROFILL
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000020
- size: 4
-local-symbols:
- - name: _s1
- type: N_SECT
- sect: 3
- value: 0x0000000000000020
- - name: _s2
- type: N_SECT
- sect: 1
- value: 0x0000000000000010
-global-symbols:
- - name: _a
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _b
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000008
- - name: _c
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000C
- - name: _cWeak
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_WEAK_DEF ]
- value: 0x0000000000000014
- - name: _kustom
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x0000000000000018
-...
-
-# CHECK: defined-atoms:
-
-# CHECK: - name: _a
-# CHECK: scope: global
-# CHECK: type: data
-# CHECK: content: [ 01, 02, 03, 04, 05, 06, 07, 08 ]
-
-# CHECK: - name: _b
-# CHECK: scope: global
-# CHECK: type: data
-# CHECK: content: [ 11, 12, 13, 14 ]
-
-# CHECK: - name: _c
-# CHECK: scope: global
-# CHECK: type: data
-# CHECK: content: [ 21, 22, 23, 24 ]
-
-# CHECK: - name: _s2
-# CHECK: type: data
-# CHECK: content: [ 31, 32, 33, 34 ]
-
-# CHECK: - name: _cWeak
-# CHECK: scope: global
-# CHECK: type: data
-# CHECK: content: [ 41, 42, 43, 44 ]
-# CHECK: merge: as-weak
-
-# CHECK: - name: _s1
-# CHECK: type: zero-fill
-# CHECK: size: 4
-
-# CHECK: - name: _kustom
-# CHECK: scope: global
-# CHECK: type: unknown
-# CHECK: content: [ 01, 02, 03, 04, 05, 06, 07, 08 ]
-# CHECK: section-choice: custom-required
-# CHECK: section-name: '__CUST/__custom'
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of x86_64 __eh_frame (dwarf unwind) relocations.
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 16
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00,
- 0x00, 0x5D, 0xC3, 0x48, 0x89, 0xC7, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0x5D, 0xE9, 0x00, 0x00, 0x00,
- 0x00, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00,
- 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x66, 0x2E,
- 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x55, 0x48, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00,
- 0x00, 0x5D, 0xC3, 0x48, 0x89, 0xC7, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0x5D, 0xE9, 0x00, 0x00, 0x00,
- 0x00 ]
- - segment: __TEXT
- section: __gcc_except_tab
- type: S_REGULAR
- attributes: [ ]
- alignment: 4
- address: 0x000000000000004C
- content: [ 0xFF, 0x9B, 0xA2, 0x80, 0x80, 0x00, 0x03, 0x1A,
- 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x0B, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0x9B, 0xA2, 0x80, 0x80, 0x00, 0x03, 0x1A,
- 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
- 0x0B, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- - segment: __TEXT
- section: __eh_frame
- type: S_COALESCED
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000100
- content: [ 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
- 0x10, 0x07, 0x9B, 0x04, 0x00, 0x00, 0x00, 0x10,
- 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
- 0x2C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
- 0xD8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
- 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
- 0xB0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2C, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
- 0x98, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0xCB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000013
- type: X86_64_RELOC_GOT
- length: 2
- pc-rel: true
- extern: true
- symbol: 8
-local-symbols:
- - name: GCC_except_table0
- type: N_SECT
- sect: 2
- value: 0x000000000000004C
- - name: GCC_except_table2
- type: N_SECT
- sect: 2
- value: 0x0000000000000074
-global-symbols:
- - name: _catchMyException1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _catchMyException2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000030
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000020
-undefined-symbols:
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_begin_catch
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_end_catch
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___gxx_personality_v0
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-page-size: 0x00000000
-...
-
-# Check that LSDA fields are fixed up correctly, even when there are multiple
-# CIEs involved.
-#
-# (1) Check that we can relocate an LSDA at all. Requires correct interpretation
-# of augmentation data strings in CIEs and augmentation data fields of FDEs.
-#
-# CHECK: - type: unwind-cfi
-# CHECK-NOT: - type:
-# CHECK: references:
-# CHECK-NEXT: - kind: negDelta32
-# CHECK-NEXT: offset: 4
-# CHECK-NEXT: target: L002
-# CHECK-NEXT: - kind: unwindFDEToFunction
-# CHECK-NEXT: offset: 8
-# CHECK-NEXT: target: _catchMyException1
-# CHECK-NEXT: - kind: unwindFDEToFunction
-# CHECK-NEXT: offset: 25
-# CHECK-NEXT: target: GCC_except_table0
-#
-# (2) Check that we have an intervening FDE with a different CIE.
-# If the test fails here then test (3) probably isn't testing what it
-# should, and this test-case should be updated.
-#
-# CHECK: - type: unwind-cfi
-# CHECK-NOT: - type:
-# CHECK: references:
-# CHECK-NEXT: - kind: negDelta32
-# CHECK-NEXT: offset: 4
-# CHECK-NEXT: target: L001
-# CHECK-NEXT: - kind: unwindFDEToFunction
-# CHECK-NEXT: offset: 8
-# CHECK-NEXT: target: _bar
-#
-# (3) Check that we can relocate the LSDA on a second FDE that references the
-# original CIE from (1). Requires us to match this FDE up with the correct
-# CIE.
-#
-# CHECK-NEXT: - type: unwind-cfi
-# CHECK-NOT: - type:
-# CHECK: references:
-# CHECK-NEXT: - kind: negDelta32
-# CHECK-NEXT: offset: 4
-# CHECK-NEXT: target: L002
-# CHECK-NEXT: - kind: unwindFDEToFunction
-# CHECK-NEXT: offset: 8
-# CHECK-NEXT: target: _catchMyException2
-# CHECK-NEXT: - kind: unwindFDEToFunction
-# CHECK-NEXT: offset: 25
-# CHECK-NEXT: target: GCC_except_table2
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of new __eh_frame (dwarf unwind) section that has no .eh labels
-# and no relocations.
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0x56, 0x83, 0xEC, 0x14, 0xE8,
- 0x00, 0x00, 0x00, 0x00, 0x5E, 0xC7, 0x04, 0x24,
- 0x04, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xFF, 0xFF,
- 0xFF, 0xC7, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x8B,
- 0x8E, 0x38, 0x00, 0x00, 0x00, 0x89, 0x4C, 0x24,
- 0x04, 0x89, 0x04, 0x24, 0xC7, 0x44, 0x24, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0xE8, 0xC7, 0xFF, 0xFF,
- 0xFF, 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8,
- 0xBC, 0xFF, 0xFF, 0xFF ]
- relocations:
- - offset: 0x00000040
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x00000035
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x00000021
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000044
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000000C
- - offset: 0x00000015
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - segment: __IMPORT
- section: __pointers
- type: S_NON_LAZY_SYMBOL_POINTERS
- attributes: [ ]
- address: 0x0000000000000044
- content: [ 0x00, 0x00, 0x00, 0x00 ]
- indirect-syms: [ 5 ]
- - segment: __TEXT
- section: __eh_frame
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000048
- content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x52, 0x00, 0x01, 0x7C, 0x08, 0x01,
- 0x10, 0x0C, 0x05, 0x04, 0x88, 0x01, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
- 0x98, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x08, 0x84, 0x02, 0x42, 0x0D,
- 0x04, 0x44, 0x86, 0x03, 0x18, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF,
- 0x0B, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0E, 0x08,
- 0x84, 0x02, 0x42, 0x0D, 0x04, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: __Z3barv
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000039
- - name: __Z3foov
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: __ZTIi
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_allocate_exception
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_throw
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: defined-atoms:
-# CHECK: - ref-name: [[CIE:L[L0-9]+]]
-# CHECK: type: unwind-cfi
-# CHECK: content:
-# CHECK: - type: unwind-cfi
-# CHECK: content:
-# CHECK: references:
-# CHECK: - kind: negDelta32
-# CHECK: offset: 4
-# CHECK: target: [[CIE]]
-# CHECK: - kind: delta32
-# CHECK: offset: 8
-# CHECK: target: __Z3foov
-# CHECK: - type: unwind-cfi
-# CHECK: content:
-# CHECK: references:
-# CHECK: - kind: negDelta32
-# CHECK: offset: 4
-# CHECK: target: [[CIE]]
-# CHECK: - kind: delta32
-# CHECK: offset: 8
-# CHECK: target: __Z3barv
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of old __eh_frame (dwarf unwind) section that has .eh labels
-# and relocations.
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0x56, 0x83, 0xEC, 0x14, 0xE8,
- 0x00, 0x00, 0x00, 0x00, 0x5E, 0xC7, 0x04, 0x24,
- 0x04, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xFF, 0xFF,
- 0xFF, 0xC7, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x8B,
- 0x8E, 0x38, 0x00, 0x00, 0x00, 0x89, 0x4C, 0x24,
- 0x04, 0x89, 0x04, 0x24, 0xC7, 0x44, 0x24, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0xE8, 0xC7, 0xFF, 0xFF,
- 0xFF, 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8,
- 0xBC, 0xFF, 0xFF, 0xFF ]
- relocations:
- - offset: 0x00000040
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x00000035
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: true
- symbol: 7
- - offset: 0x00000021
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000044
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000000C
- - offset: 0x00000015
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: true
- symbol: 6
- - segment: __IMPORT
- section: __pointers
- type: S_NON_LAZY_SYMBOL_POINTERS
- attributes: [ ]
- address: 0x0000000000000044
- content: [ 0x00, 0x00, 0x00, 0x00 ]
- indirect-syms: [ 5 ]
- - segment: __TEXT
- section: __eh_frame
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000048
- content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x52, 0x00, 0x01, 0x7C, 0x08, 0x01,
- 0x10, 0x0C, 0x05, 0x04, 0x88, 0x01, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
- 0x98, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x08, 0x84, 0x02, 0x42, 0x0D,
- 0x04, 0x44, 0x86, 0x03, 0x18, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF,
- 0x0B, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0E, 0x08,
- 0x84, 0x02, 0x42, 0x0D, 0x04, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x0000001C
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000064
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000048
- - offset: 0x00000020
- scattered: true
- type: GENERIC_RELOC_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000000
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000068
- - offset: 0x00000038
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000080
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000048
- - offset: 0x0000003C
- scattered: true
- type: GENERIC_RELOC_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000039
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000084
-local-symbols:
- - name: EH_frame0
- type: N_SECT
- sect: 3
- value: 0x0000000000000048
-global-symbols:
- - name: __Z3barv
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000039
- - name: __Z3barv.eh
- type: N_SECT
- scope: [ N_EXT ]
- sect: 3
- value: 0x000000000000007C
- - name: __Z3foov
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: __Z3foov.eh
- type: N_SECT
- scope: [ N_EXT ]
- sect: 3
- value: 0x0000000000000060
-undefined-symbols:
- - name: __ZTIi
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_allocate_exception
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_throw
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: defined-atoms:
-# CHECK: - ref-name: [[CIE:L[L0-9]+]]
-# CHECK: type: unwind-cfi
-# CHECK: content:
-# CHECK: - type: unwind-cfi
-# CHECK: content:
-# CHECK: references:
-# CHECK: - kind: negDelta32
-# CHECK: offset: 4
-# CHECK: target: [[CIE]]
-# CHECK: - kind: delta32
-# CHECK: offset: 8
-# CHECK: target: __Z3foov
-# CHECK: - type: unwind-cfi
-# CHECK: content:
-# CHECK: references:
-# CHECK: - kind: negDelta32
-# CHECK: offset: 4
-# CHECK: target: [[CIE]]
-# CHECK: - kind: delta32
-# CHECK: offset: 8
-# CHECK: target: __Z3barv
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of __eh_frame (dwarf unwind) section.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0xB8, 0x09, 0x00, 0x00,
- 0x00, 0x5D, 0xC3, 0x55, 0x48, 0x89, 0xE5, 0xB8,
- 0x0A, 0x00, 0x00, 0x00, 0x5D, 0xC3 ]
- - segment: __TEXT
- section: __eh_frame
- type: S_COALESCED
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000058
- content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
- 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
- 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00,
- 0x6B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
- 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: __Z3barv
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: __Z3foov
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000B
-...
-
-# CHECK: defined-atoms:
-# CHECK: - ref-name: [[CIE:L[0-9]+]]
-# CHECK: type: unwind-cfi
-# CHECK: content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00,
-# CHECK: 01, 78, 10, 01, 10, 0C, 07, 08, 90, 01, 00, 00 ]
-# CHECK: - type: unwind-cfi
-# CHECK: content: [ 24, 00, 00, 00, 1C, 00, 00, 00, 88, FF, FF, FF,
-# CHECK: FF, FF, FF, FF, 0B, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
-# CHECK: 00, 00, 00, 00 ]
-# CHECK: references:
-# CHECK: - kind: negDelta32
-# CHECK: offset: 4
-# CHECK: target: [[CIE]]
-# CHECK: - kind: unwindFDEToFunction
-# CHECK: offset: 8
-# CHECK: target: __Z3barv
-# CHECK: - type: unwind-cfi
-# CHECK: content: [ 24, 00, 00, 00, 44, 00, 00, 00, 6B, FF, FF, FF,
-# CHECK: FF, FF, FF, FF, 0B, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
-# CHECK: 00, 00, 00, 00 ]
-# CHECK: references:
-# CHECK: - kind: negDelta32
-# CHECK: offset: 4
-# CHECK: target: [[CIE]]
-# CHECK: - kind: unwindFDEToFunction
-# CHECK: offset: 8
-# CHECK: target: __Z3foov
-# CHECK: - name: __Z3barv
-# CHECK: scope: global
-# CHECK: content: [ 55, 48, 89, E5, B8, 09, 00, 00, 00, 5D, C3 ]
-# CHECK: - name: __Z3foov
-# CHECK: scope: global
-# CHECK: content: [ 55, 48, 89, E5, B8, 0A, 00, 00, 00, 5D, C3 ]
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -o %t
-# RUN: ld64.lld.darwinold -arch x86_64 -r %t -print_atoms -o %t2 | FileCheck %s
-#
-# Test parsing of mach-o functions.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xCC, 0xC3, 0x90, 0xC3, 0x90, 0x90, 0xC3, 0x90,
- 0x90, 0x90, 0xC3, 0x90, 0x90, 0x90, 0x90, 0xC3,
- 0xCC, 0x31, 0xC0, 0xC3 ]
-local-symbols:
- - name: _myStatic
- type: N_SECT
- sect: 1
- value: 0x000000000000000B
-global-symbols:
- - name: _myGlobal
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myGlobalWeak
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_WEAK_DEF ]
- value: 0x0000000000000002
- - name: _myHidden
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000004
- - name: _myHiddenWeak
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- desc: [ N_WEAK_DEF ]
- value: 0x0000000000000007
- - name: _myStripNot
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_NO_DEAD_STRIP ]
- value: 0x0000000000000010
- - name: _myResolver
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_SYMBOL_RESOLVER ]
- value: 0x0000000000000011
-...
-
-# CHECK-NOT: name:
-# CHECK: content: [ CC ]
-
-# CHECK: name: _myGlobal
-# CHECK: scope: global
-# CHECK: content: [ C3 ]
-
-# CHECK: name: _myGlobalWeak
-# CHECK: scope: global
-# CHECK: content: [ 90, C3 ]
-# CHECK: merge: as-weak
-
-# CHECK: name: _myHidden
-# CHECK: scope: hidden
-# CHECK: content: [ 90, 90, C3 ]
-
-# CHECK: name: _myHiddenWeak
-# CHECK: scope: hidden
-# CHECK: content: [ 90, 90, 90, C3 ]
-# CHECK: merge: as-weak
-
-# CHECK: name: _myStatic
-# CHECK-NOT: scope: global
-# CHECK-NOT: scope: hidden
-# CHECK: content: [ 90, 90, 90, 90, C3 ]
-
-# CHECK: name: _myStripNot
-# CHECK: scope: global
-# CHECK: content: [ CC ]
-# CHECK: dead-strip: never
-
-# CHECK: name: _myResolver
-# CHECK: scope: global
-# CHECK: type: resolver
-# CHECK: content: [ 31, C0, C3 ]
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of literal sections.
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x89, 0xE5,
- 0x5D, 0xC3, 0x55, 0x89, 0xE5, 0x5D, 0xC3 ]
- - segment: __DATA
- section: __mod_init_func
- type: S_MOD_INIT_FUNC_POINTERS
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000044
- content: [ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000004
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - segment: __DATA
- section: __mod_term_func
- type: S_MOD_TERM_FUNC_POINTERS
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000104
- content: [ 0x0A, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _init
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _init2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000005
- - name: _term
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000A
-...
-
-
-# CHECK:defined-atoms:
-# CHECK: - type: initializer-pointer
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: dead-strip: never
-# CHECK: - type: initializer-pointer
-# CHECK: content: [ 05, 00, 00, 00 ]
-# CHECK: dead-strip: never
-# CHECK: - type: terminator-pointer
-# CHECK: content: [ 0A, 00, 00, 00 ]
-# CHECK: dead-strip: never
-# CHECK: - name: _init
-# CHECK: scope: global
-# CHECK: content: [ 55, 89, E5, 5D, C3 ]
-# CHECK: - name: _init2
-# CHECK: scope: global
-# CHECK: content: [ 55, 89, E5, 5D, C3 ]
-# CHECK: - name: _term
-# CHECK: scope: global
-# CHECK: content: [ 55, 89, E5, 5D, C3 ]
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of literal sections.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
- 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48, 0x89, 0xE5,
- 0x5D, 0xC3 ]
- - segment: __DATA
- section: __mod_init_func
- type: S_MOD_INIT_FUNC_POINTERS
- attributes: [ ]
- alignment: 1
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000008
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 1
- - segment: __DATA
- section: __mod_term_func
- type: S_MOD_TERM_FUNC_POINTERS
- attributes: [ ]
- alignment: 8
- address: 0x0000000000000108
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 2
-global-symbols:
- - name: _init
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _init2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000006
- - name: _term
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000C
-...
-
-
-# CHECK:defined-atoms:
-# CHECK: - type: initializer-pointer
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: dead-strip: never
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: _init
-# CHECK: - type: initializer-pointer
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: dead-strip: never
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: _init2
-# CHECK: - type: terminator-pointer
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: dead-strip: never
-# CHECK: references:
-# CHECK: - kind: pointer64
-# CHECK: offset: 0
-# CHECK: target: _term
-# CHECK: - name: _init
-# CHECK: scope: global
-# CHECK: content: [ 55, 48, 89, E5, 5D, C3 ]
-# CHECK: - name: _init2
-# CHECK: scope: global
-# CHECK: content: [ 55, 48, 89, E5, 5D, C3 ]
-# CHECK: - name: _term
-# CHECK: scope: global
-# CHECK: content: [ 55, 48, 89, E5, 5D, C3 ]
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t 2> %t.err
-# RUN: FileCheck %s < %t.err
-#
-# Test for error if literal section is not correct size multiple.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __literal8
- type: S_8BYTE_LITERALS
- attributes: [ ]
- alignment: 0
- address: 0x0000000000000120
- content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D ]
-...
-
-# CHECK: error:
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of literal sections.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- alignment: 1
- address: 0x0000000000000100
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x74, 0x68,
- 0x65, 0x72, 0x65, 0x00, 0x77, 0x6F, 0x72, 0x6C,
- 0x00 ]
- - segment: __TEXT
- section: __literal4
- type: S_4BYTE_LITERALS
- attributes: [ ]
- alignment: 1
- address: 0x0000000000000114
- content: [ 0x01, 0x02, 0x03, 0x04, 0x11, 0x12, 0x13, 0x14,
- 0x28, 0x29, 0x2A, 0x2B ]
- - segment: __TEXT
- section: __literal8
- type: S_8BYTE_LITERALS
- attributes: [ ]
- alignment: 1
- address: 0x0000000000000120
- content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F ]
- - segment: __TEXT
- section: __literal16
- type: S_16BYTE_LITERALS
- attributes: [ ]
- alignment: 1
- address: 0x0000000000000130
- content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00 ]
- - segment: __TEXT
- section: __ustring
- type: S_REGULAR
- attributes: [ ]
- alignment: 1
- address: 0x0000000000000100
- content: [ 0x68, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00,
- 0x6F, 0x00, 0x00, 0x00, 0x74, 0x00, 0x68, 0x00,
- 0x65, 0x00, 0x72, 0x00, 0x00, 0x00 ]
-...
-
-
-# CHECK:defined-atoms:
-# CHECK: - scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 68, 65, 6C, 6C, 6F, 00 ]
-# CHECK: - scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 74, 68, 65, 72, 65, 00 ]
-# CHECK: - scope: hidden
-# CHECK: type: c-string
-# CHECK: content: [ 77, 6F, 72, 6C, 00 ]
-# CHECK: - scope: hidden
-# CHECK: type: utf16-string
-# CHECK: content: [ 68, 00, 65, 00, 6C, 00, 6C, 00, 6F, 00, 00, 00 ]
-# CHECK: - scope: hidden
-# CHECK: type: utf16-string
-# CHECK: content: [ 74, 00, 68, 00, 65, 00, 72, 00, 00, 00 ]
-# CHECK: - scope: hidden
-# CHECK: type: const-4-byte
-# CHECK: content: [ 01, 02, 03, 04 ]
-# CHECK: - scope: hidden
-# CHECK: type: const-4-byte
-# CHECK: content: [ 11, 12, 13, 14 ]
-# CHECK: - scope: hidden
-# CHECK: type: const-4-byte
-# CHECK: content: [ 28, 29, 2A, 2B ]
-# CHECK: - scope: hidden
-# CHECK: type: const-8-byte
-# CHECK: content: [ 01, 02, 03, 04, 05, 06, 07, 08 ]
-# CHECK: - scope: hidden
-# CHECK: type: const-8-byte
-# CHECK: content: [ 28, 29, 2A, 2B, 2C, 2D, 2E, 2F ]
-# CHECK: - scope: hidden
-# CHECK: type: const-16-byte
-# CHECK: content: [ 01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C,
-# CHECK: 0D, 0E, 0F, 00 ]
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of non-lazy-pointer sections.
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00, 0x00,
- 0x59, 0x8D, 0x81, 0x14, 0x00, 0x00, 0x00, 0x8D,
- 0x81, 0x18, 0x00, 0x00, 0x00, 0x5D, 0xC3, 0x55,
- 0x89, 0xE5, 0x5D, 0xC3 ]
- relocations:
- - offset: 0x00000011
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000020
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000008
- - offset: 0x0000000B
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x0000001C
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000008
- - segment: __IMPORT
- section: __pointers
- type: S_NON_LAZY_SYMBOL_POINTERS
- attributes: [ ]
- address: 0x000000000000001C
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- indirect-syms: [ 2, 2147483648 ]
-local-symbols:
- - name: _foo
- type: N_SECT
- sect: 1
- value: 0x0000000000000017
-global-symbols:
- - name: _get
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _bar
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-
-# CHECK:defined-atoms:
-# CHECK: - ref-name: [[GOT1:L[L0-9]+]]
-# CHECK: scope: hidden
-# CHECK: type: got
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: merge: by-content
-# CHECK: - ref-name: [[GOT2:L[L0-9]+]]
-# CHECK: scope: hidden
-# CHECK: type: got
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: merge: by-content
-# CHECK: - name: _get
-# CHECK: scope: global
-# CHECK: content: [ 55, 89, E5, E8, 00, 00, 00, 00, 59, 8D, 81, 14,
-# CHECK: 00, 00, 00, 8D, 81, 18, 00, 00, 00, 5D, C3 ]
-# CHECK: references:
-# CHECK: - kind: funcRel32
-# CHECK: offset: 11
-# CHECK: target: [[GOT1]]
-# CHECK: - kind: funcRel32
-# CHECK: offset: 17
-# CHECK: target: [[GOT2]]
-# CHECK: - name: _foo
-# CHECK: content: [ 55, 89, E5, 5D, C3 ]
-
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 -r -print_atoms %s -o %t | FileCheck %s \
-# RUN: && ld64.lld.darwinold -arch i386 -r -print_atoms %t -o %t2 | FileCheck %s
-#
-# Test parsing and writing of x86 relocations.
-#
-# The first step tests if the supplied mach-o file is parsed into the correct
-# set of references. The second step verifies relocations can be round-tripped
-# by writing to a new .o file, then parsing that file which should result in
-# the same references.
-#
-# .text
-#_test:
-# call _undef
-# call _undef+2
-# call _foo
-# call _foo+2
-# callw _undef
-# callw _foo
-# callw _foo+2
-#L1:
-# movl _undef, %eax
-# movl _x, %eax
-# movl _x+4, %eax
-# movl _x-L1(%eax), %eax
-# movl _x+4-L1(%eax), %eax
-#
-#_foo:
-# ret
-#
-# .data
-#_x:
-# .long _undef
-# .long _undef+7
-# .long _foo
-# .long _foo+3
-# .long _test - .
-# .long _test+3 - .
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xE8, 0xFB, 0xFF, 0xFF, 0xFF, 0xE8, 0xF8, 0xFF,
- 0xFF, 0xFF, 0xE8, 0x2C, 0x00, 0x00, 0x00, 0xE8,
- 0x29, 0x00, 0x00, 0x00, 0x66, 0xE8, 0xE8, 0xFF,
- 0x66, 0xE8, 0x1F, 0x00, 0x66, 0xE8, 0x1D, 0x00,
- 0xA1, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x3C, 0x00,
- 0x00, 0x00, 0xA1, 0x40, 0x00, 0x00, 0x00, 0x8B,
- 0x80, 0x1C, 0x00, 0x00, 0x00, 0x8B, 0x80, 0x20,
- 0x00, 0x00, 0x00, 0xC3 ]
- relocations:
- - offset: 0x00000037
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x0000003C
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000020
- - offset: 0x00000031
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x0000003C
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000020
- - offset: 0x0000002B
- scattered: true
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- value: 0x0000003C
- - offset: 0x00000026
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x00000021
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 3
- - offset: 0x0000001E
- scattered: true
- type: GENERIC_RELOC_VANILLA
- length: 1
- pc-rel: true
- value: 0x0000003B
- - offset: 0x0000001A
- type: GENERIC_RELOC_VANILLA
- length: 1
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x00000016
- type: GENERIC_RELOC_VANILLA
- length: 1
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000010
- scattered: true
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- value: 0x0000003B
- - offset: 0x0000000B
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x00000006
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000001
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x000000000000003C
- content: [ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3B, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00,
- 0xB4, 0xFF, 0xFF, 0xFF, 0xB3, 0xFF, 0xFF, 0xFF ]
- relocations:
- - offset: 0x00000014
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000000
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x00000050
- - offset: 0x00000010
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000000
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000004C
- - offset: 0x0000000C
- scattered: true
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- value: 0x0000003B
- - offset: 0x00000008
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000004
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 3
- - offset: 0x00000000
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 3
-local-symbols:
- - name: _test
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: _foo
- type: N_SECT
- sect: 1
- value: 0x000000000000003B
- - name: _x
- type: N_SECT
- sect: 2
- value: 0x000000000000003C
-undefined-symbols:
- - name: _undef
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: _x
-# CHECK: type: data
-# CHECK: references:
-# CHECK: - kind: pointer32
-# CHECK: offset: 0
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: pointer32
-# CHECK: offset: 4
-# CHECK: target: _undef
-# CHECK: addend: 7
-# CHECK: - kind: pointer32
-# CHECK: offset: 8
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: pointer32
-# CHECK: offset: 12
-# CHECK: target: _foo
-# CHECK: addend: 3
-# CHECK: - kind: delta32
-# CHECK: offset: 16
-# CHECK: target: _test
-# CHECK: - kind: delta32
-# CHECK: offset: 20
-# CHECK: target: _test
-# CHECK: addend: 3
-# CHECK: - name: _test
-# CHECK: references:
-# CHECK: - kind: branch32
-# CHECK: offset: 1
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: branch32
-# CHECK: offset: 6
-# CHECK: target: _undef
-# CHECK: addend: 2
-# CHECK: - kind: branch32
-# CHECK: offset: 11
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: branch32
-# CHECK: offset: 16
-# CHECK: target: _foo
-# CHECK: addend: 2
-# CHECK: - kind: branch16
-# CHECK: offset: 22
-# CHECK: target: _undef
-# CHECK-NOT: addend:
-# CHECK: - kind: branch16
-# CHECK: offset: 26
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: branch16
-# CHECK: offset: 30
-# CHECK: target: _foo
-# CHECK: addend: 2
-# CHECK: - kind: abs32
-# CHECK: offset: 33
-# CHECK: target: _undef
-# CHECK: - kind: abs32
-# CHECK: offset: 38
-# CHECK: target: _x
-# CHECK: - kind: abs32
-# CHECK: offset: 43
-# CHECK: target: _x
-# CHECK: addend: 4
-# CHECK: - kind: funcRel32
-# CHECK: offset: 49
-# CHECK: target: _x
-# CHECK: addend: -32
-# CHECK: - kind: funcRel32
-# CHECK: offset: 55
-# CHECK: target: _x
-# CHECK: addend: -28
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r %s -print_atoms -o %t2 | FileCheck %s
-#
-# Test parsing of mach-o functions with no symbols at all.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xCC ]
-...
-
-# CHECK-NOT: name:
-# CHECK: content: [ CC ]
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
-#
-# Test parsing of tentative definitions, including size, scope, and alignment.
-#
-#
-# int tent4;
-# long tent8;
-# __attribute__((visibility("hidden"))) int tentHidden;
-# __attribute__((aligned(16))) int tent4_16;
-# __attribute__((aligned(32))) long tent64_32[8];
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __tex
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
- address: 0x0000000000000000
-undefined-symbols:
- - name: _tent4
- type: N_UNDF
- scope: [ N_EXT ]
- desc: 0x0200
- value: 0x0000000000000004
- - name: _tent4_16
- type: N_UNDF
- scope: [ N_EXT ]
- desc: 0x0400
- value: 0x0000000000000004
- - name: _tent64_32
- type: N_UNDF
- scope: [ N_EXT ]
- desc: 0x0500
- value: 0x0000000000000040
- - name: _tent8
- type: N_UNDF
- scope: [ N_EXT ]
- desc: 0x0300
- value: 0x0000000000000008
- - name: _tentHidden
- type: N_UNDF
- scope: [ N_EXT, N_PEXT ]
- desc: 0x0200
- value: 0x0000000000000004
-...
-
-
-# CHECK: defined-atoms:
-# CHECK: name: _tent4
-# CHECK: scope: global
-# CHECK: type: zero-fill
-# CHECK: size: 4
-# CHECK: merge: as-tentative
-# CHECK: alignment: 4
-
-# CHECK: name: _tent4_16
-# CHECK: scope: global
-# CHECK: type: zero-fill
-# CHECK: size: 4
-# CHECK: merge: as-tentative
-# CHECK: alignment: 16
-
-# CHECK: name: _tent64_32
-# CHECK: scope: global
-# CHECK: type: zero-fill
-# CHECK: size: 64
-# CHECK: merge: as-tentative
-# CHECK: alignment: 32
-
-# CHECK: name: _tent8
-# CHECK: scope: global
-# CHECK: type: zero-fill
-# CHECK: size: 8
-# CHECK: merge: as-tentative
-# CHECK: alignment: 8
-
-# CHECK: name: _tentHidden
-# CHECK: scope: hidden
-# CHECK: type: zero-fill
-# CHECK: size: 4
-# CHECK: merge: as-tentative
-# CHECK: alignment: 4
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 -r -print_atoms %s -o %t | FileCheck %s \
-# RUN: && ld64.lld.darwinold -arch arm64 -r -print_atoms %t -o %t2 | FileCheck %s
-#
-# Test parsing and writing of arm64 text relocations.
-#
-# The first step tests if the supplied mach-o file is parsed into the correct
-# set of references. The second step verifies relocations can be round-tripped
-# by writing to a new .o file, then parsing that file which should result in
-# the same references.
-#
-#_test:
-
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x94,
- 0x01, 0x00, 0x00, 0x90, 0x20, 0x00, 0x40, 0x39,
- 0x20, 0x00, 0x40, 0x79, 0x20, 0x00, 0x40, 0xB9,
- 0x20, 0x00, 0x40, 0xF9, 0x20, 0x00, 0xC0, 0x3D,
- 0x01, 0x00, 0x00, 0x90, 0x20, 0x00, 0x40, 0xB9,
- 0x01, 0x00, 0x00, 0x90, 0x20, 0x00, 0x40, 0xF9,
- 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x40, 0xF9 ]
- relocations:
- - offset: 0x00000034
- type: ARM64_RELOC_TLVP_LOAD_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 5
- - offset: 0x00000030
- type: ARM64_RELOC_TLVP_LOAD_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 5
- - offset: 0x0000002C
- type: ARM64_RELOC_GOT_LOAD_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 6
- - offset: 0x00000028
- type: ARM64_RELOC_GOT_LOAD_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 6
- - offset: 0x00000024
- type: ARM64_RELOC_ADDEND
- length: 2
- pc-rel: false
- extern: false
- symbol: 16
- - offset: 0x00000024
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000020
- type: ARM64_RELOC_ADDEND
- length: 2
- pc-rel: false
- extern: false
- symbol: 16
- - offset: 0x00000020
- type: ARM64_RELOC_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x0000001C
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000018
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000014
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000010
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x0000000C
- type: ARM64_RELOC_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 2
- - offset: 0x00000008
- type: ARM64_RELOC_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x00000004
- type: ARM64_RELOC_ADDEND
- length: 2
- pc-rel: false
- extern: false
- symbol: 8
- - offset: 0x00000004
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x00000000
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000038
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
-local-symbols:
- - name: ltmp0
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: _func
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: _v1
- type: N_SECT
- sect: 2
- value: 0x0000000000000038
- - name: ltmp1
- type: N_SECT
- sect: 2
- value: 0x0000000000000038
-undefined-symbols:
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _tlv
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _v2
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: defined-atoms:
-# CHECK: - name: _v1
-# CHECK: type: data
-# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
-# CHECK: 00, 00, 00, 00 ]
-# CHECK: - name: _func
-# CHECK: content: [ 00, 00, 00, 94, 00, 00, 00, 94, 01, 00, 00, 90,
-# CHECK: 20, 00, 40, 39, 20, 00, 40, 79, 20, 00, 40, B9,
-# CHECK: 20, 00, 40, F9, 20, 00, C0, 3D, 01, 00, 00, 90,
-# CHECK: 20, 00, 40, B9, 01, 00, 00, 90, 20, 00, 40, F9,
-# CHECK: 00, 00, 00, 90, 00, 00, 40, F9 ]
-# CHECK: references:
-# CHECK: - kind: branch26
-# CHECK: offset: 0
-# CHECK: target: _foo
-# CHECK: - kind: branch26
-# CHECK: offset: 4
-# CHECK: target: _foo
-# CHECK: addend: 8
-# CHECK: - kind: page21
-# CHECK: offset: 8
-# CHECK: target: _v1
-# CHECK: - kind: offset12
-# CHECK: offset: 12
-# CHECK: target: _v1
-# CHECK: - kind: offset12scale2
-# CHECK: offset: 16
-# CHECK: target: _v1
-# CHECK: - kind: offset12scale4
-# CHECK: offset: 20
-# CHECK: target: _v1
-# CHECK: - kind: offset12scale8
-# CHECK: offset: 24
-# CHECK: target: _v1
-# CHECK: - kind: offset12scale16
-# CHECK: offset: 28
-# CHECK: target: _v1
-# CHECK: - kind: page21
-# CHECK: offset: 32
-# CHECK: target: _v1
-# CHECK: addend: 16
-# CHECK: - kind: offset12scale4
-# CHECK: offset: 36
-# CHECK: target: _v1
-# CHECK: addend: 16
-# CHECK: - kind: gotPage21
-# CHECK: offset: 40
-# CHECK: target: _v2
-# CHECK: - kind: gotOffset12
-# CHECK: offset: 44
-# CHECK: target: _v2
-# CHECK: - kind: tlvPage21
-# CHECK: offset: 48
-# CHECK: target: _tlv
-# CHECK: - kind: tlvOffset12
-# CHECK: offset: 52
-# CHECK: target: _tlv
-# CHECK: undefined-atoms:
-# CHECK: - name: _foo
-# CHECK: - name: _tlv
-# CHECK: - name: _v2
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s \
-# RUN: && ld64.lld.darwinold -arch x86_64 -r -print_atoms %t -o %t2 | FileCheck %s
-#
-# Test parsing and writing of x86_64 text relocations.
-#
-# The first step tests if the supplied mach-o file is parsed into the correct
-# set of references. The second step verifies relocations can be round-tripped
-# by writing to a new .o file, then parsing that file which should result in
-# the same references.
-#
-#_test:
-# call _foo
-# call _foo+4
-# movq _foo@GOTPCREL(%rip), %rax
-# pushq _foo@GOTPCREL(%rip)
-# movl _foo(%rip), %eax
-# movl _foo+4(%rip), %eax
-# movb $0x12, _foo(%rip)
-# movw $0x1234, _foo(%rip)
-# movl $0x12345678, _foo(%rip)
-# movl L2(%rip), %eax
-# movb $0x12, L2(%rip)
-# movw $0x1234, L2(%rip)
-# movl $0x12345678, L2(%rip)
-#
-# .data
-#L2: .long 0
-
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xE8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x04, 0x00,
- 0x00, 0x00, 0x48, 0x8B, 0x05, 0x04, 0x00, 0x00,
- 0x00, 0xFF, 0x35, 0x04, 0x00, 0x00, 0x00, 0x8B,
- 0x05, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x05, 0x04,
- 0x00, 0x00, 0x00, 0xC6, 0x05, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x12, 0x66, 0xC7, 0x05, 0xFE, 0xFF, 0xFF,
- 0xFF, 0x34, 0x12, 0xC7, 0x05, 0xFC, 0xFF, 0xFF,
- 0xFF, 0x78, 0x56, 0x34, 0x12, 0x8B, 0x05, 0x1A,
- 0x00, 0x00, 0x00, 0xc6, 0x05, 0x13, 0x00, 0x00,
- 0x00, 0x12, 0x66, 0xc7, 0x05, 0x0a, 0x00, 0x00,
- 0x00, 0x34, 0x12, 0xc7, 0x05, 0x00, 0x00, 0x00,
- 0x00, 0x78, 0x56, 0x34, 0x12 ]
- relocations:
- - offset: 0x00000055
- type: X86_64_RELOC_SIGNED_4
- length: 2
- pc-rel: true
- extern: false
- symbol: 2
- - offset: 0x0000004d
- type: X86_64_RELOC_SIGNED_2
- length: 2
- pc-rel: true
- extern: false
- symbol: 2
- - offset: 0x00000045
- type: X86_64_RELOC_SIGNED_1
- length: 2
- pc-rel: true
- extern: false
- symbol: 2
- - offset: 0x0000003F
- type: X86_64_RELOC_SIGNED
- length: 2
- pc-rel: true
- extern: false
- symbol: 2
- - offset: 0x00000035
- type: X86_64_RELOC_SIGNED_4
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x0000002D
- type: X86_64_RELOC_SIGNED_2
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000025
- type: X86_64_RELOC_SIGNED_1
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x0000001F
- type: X86_64_RELOC_SIGNED
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000019
- type: X86_64_RELOC_SIGNED
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000013
- type: X86_64_RELOC_GOT
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x0000000D
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000006
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000001
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x000000000000005D
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-local-symbols:
- - name: _test
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: defined-atoms:
-# CHECK: - ref-name: [[LABEL:L[0-9]+]]
-# CHECK: type: data
-# CHECK: content: [ 00, 00, 00, 00 ]
-# CHECK: - name: _test
-# CHECK: references:
-# CHECK: - kind: branch32
-# CHECK: offset: 1
-# CHECK: target: _foo
-# CHECK: - kind: branch32
-# CHECK: offset: 6
-# CHECK: target: _foo
-# CHECK: addend: 4
-# CHECK: - kind: ripRel32GotLoad
-# CHECK: offset: 13
-# CHECK: target: _foo
-# CHECK: addend: 4
-# CHECK: - kind: ripRel32Got
-# CHECK: offset: 19
-# CHECK: target: _foo
-# CHECK: addend: 4
-# CHECK: - kind: ripRel32
-# CHECK: offset: 25
-# CHECK: target: _foo
-# CHECK: - kind: ripRel32
-# CHECK: offset: 31
-# CHECK: target: _foo
-# CHECK: addend: 4
-# CHECK: - kind: ripRel32Minus1
-# CHECK: offset: 37
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: ripRel32Minus2
-# CHECK: offset: 45
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: ripRel32Minus4
-# CHECK: offset: 53
-# CHECK: target: _foo
-# CHECK-NOT: addend:
-# CHECK: - kind: ripRel32Anon
-# CHECK: offset: 63
-# CHECK: target: [[LABEL]]
-# CHECK-NOT: addend:
-# CHECK: - kind: ripRel32Minus1Anon
-# CHECK: offset: 69
-# CHECK: target: [[LABEL]]
-# CHECK-NOT: addend:
-# CHECK: - kind: ripRel32Minus2Anon
-# CHECK: offset: 77
-# CHECK: target: [[LABEL]]
-# CHECK-NOT: addend:
-# CHECK: - kind: ripRel32Minus4Anon
-# CHECK: offset: 85
-# CHECK: target: [[LABEL]]
-# CHECK-NOT: addend:
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s \
-# RUN: && ld64.lld.darwinold -arch x86_64 -r -print_atoms %t -o %t2 | FileCheck %s
-#
-# Test parsing of x86_64 tlv relocations.
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 16
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x3D, 0x00,
- 0x00, 0x00, 0x00, 0xFF, 0x17, 0x8B, 0x00, 0x5D,
- 0xC3 ]
- relocations:
- - offset: 0x00000007
- type: X86_64_RELOC_TLV
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - segment: __DATA
- section: __thread_data
- type: S_THREAD_LOCAL_REGULAR
- attributes: [ ]
- alignment: 4
- address: 0x0000000000000014
- content: [ 0x07, 0x00, 0x00, 0x00 ]
- - segment: __DATA
- section: __thread_vars
- type: S_THREAD_LOCAL_VARIABLES
- attributes: [ ]
- address: 0x0000000000000018
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000010
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 3
-local-symbols:
- - name: '_x$tlv$init'
- type: N_SECT
- sect: 2
- value: 0x0000000000000014
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _x
- type: N_SECT
- scope: [ N_EXT ]
- sect: 3
- value: 0x0000000000000018
-undefined-symbols:
- - name: __tlv_bootstrap
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-page-size: 0x00000000
-...
-
-# CHECK: - name: _x
-# CHECK-NEXT: scope: global
-# CHECK-NEXT: type: tlv-thunk
-# CHECK-NOT: - name:
-# CHECK: references:
-# CHECK-NEXT: - kind: pointer64
-# CHECK-NEXT: offset: 0
-# CHECK-NEXT: target: __tlv_bootstrap
-# CHECK-NEXT: - kind: tlvInitSectionOffset
-# CHECK-NEXT: offset: 16
-# CHECK-NEXT: target: '_x$tlv$init'
-# CHECK: - name: _main
-# CHECK-NOT: - name:
-# CHECK-NEXT: scope: global
-# CHECK: references:
-# CHECK-NEXT: - kind: ripRel32Tlv
-# CHECK-NEXT: offset: 7
-# CHECK-NEXT: target: _x
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s \
-# RUN: %p/Inputs/re-exported-dylib-ordinal.yaml \
-# RUN: %p/Inputs/re-exported-dylib-ordinal2.yaml \
-# RUN: %p/Inputs/re-exported-dylib-ordinal3.yaml -dylib -o %t \
-# RUN: && llvm-nm -m %t | FileCheck %s
-#
-# Test that when one dylib A re-exports dylib B that using a symbol from B
-# gets recorded as coming from A.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
- 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000008
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
-global-symbols:
- - name: _test
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _bar
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: (undefined) external _bar (from libfoo)
-# CHECK: (undefined) external dyld_stub_binder (from libSystem)
+++ /dev/null
-# Check we handle -rpath correctly:
-# RUN: ld64.lld.darwinold -arch x86_64 -rpath @loader_path/../Frameworks \
-# RUN: %p/Inputs/x86_64/libSystem.yaml %s -o %t
-# RUN: llvm-objdump --private-headers %t | FileCheck %s --check-prefix=CHECK-BINARY-WRITE
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xCC, 0xC3, 0x90, 0xC3, 0x90, 0x90, 0xC3, 0x90,
- 0x90, 0x90, 0xC3, 0x90, 0x90, 0x90, 0x90, 0xC3,
- 0x31, 0xC0, 0xC3 ]
-local-symbols:
- - name: _myStatic
- type: N_SECT
- sect: 1
- value: 0x000000000000000B
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
-...
-
-
-# CHECK-BINARY-WRITE: cmd LC_RPATH
-# CHECK-BINARY-WRITE-NEXT: cmdsize 40
-# CHECK-BINARY-WRITE-NEXT: path @loader_path/../Frameworks (offset 12)
+++ /dev/null
-# RUN: ld64.lld.darwinold -macosx_version_min 10.7 -arch x86_64 -print_atoms %s -o %t | FileCheck %s
-# RUN: not ld64.lld.darwinold -macosx_version_min 10.6 -arch x86_64 -o %t %s 2> %t2
-# RUN: FileCheck < %t2 %s --check-prefix=CHECK-ERROR
-# RUN: llvm-objdump --macho --private-headers %t | FileCheck %s --check-prefix=CHECK-LOADCMDS
-#
-# Test parsing of x86_64 tlv relocations.
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 16
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x3D, 0x00,
- 0x00, 0x00, 0x00, 0xFF, 0x17, 0x8B, 0x00, 0x5D,
- 0xC3 ]
- relocations:
- - offset: 0x00000007
- type: X86_64_RELOC_TLV
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - segment: __DATA
- section: __thread_bss
- type: S_THREAD_LOCAL_ZEROFILL
- attributes: [ ]
- alignment: 4
- address: 0x0000000000000014
- size: 4
- - segment: __DATA
- section: __thread_vars
- type: S_THREAD_LOCAL_VARIABLES
- attributes: [ ]
- address: 0x0000000000000018
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000010
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 0
- - offset: 0x00000000
- type: X86_64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 3
- - segment: __DATA
- section: __dummy
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x00000000000000C0
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
-local-symbols:
- - name: '_x$tlv$init'
- type: N_SECT
- sect: 2
- value: 0x0000000000000014
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _x
- type: N_SECT
- scope: [ N_EXT ]
- sect: 3
- value: 0x0000000000000018
- - name: '__tlv_bootstrap'
- type: N_SECT
- scope: [ N_EXT ]
- sect: 4
- value: 0x00000000000000C0
- - name: 'dyld_stub_binder'
- type: N_SECT
- scope: [ N_EXT ]
- sect: 4
- value: 0x00000000000000C8
- - name: 'start'
- type: N_SECT
- scope: [ N_EXT ]
- sect: 4
- value: 0x00000000000000D0
-page-size: 0x00000000
-...
-
-# CHECK: - name: _x
-# CHECK-NEXT: scope: global
-# CHECK-NEXT: type: tlv-thunk
-# CHECK-NOT: - name:
-# CHECK: references:
-# CHECK-NEXT: - kind: pointer64
-# CHECK-NEXT: offset: 0
-# CHECK-NEXT: target: __tlv_bootstrap
-# CHECK-NEXT: - kind: tlvInitSectionOffset
-# CHECK-NEXT: offset: 16
-# CHECK-NEXT: target: '_x$tlv$init'
-# CHECK: - name: '_x$tlv$init'
-# CHECK-NEXT: type: tlv-zero-fill
-# CHECK: - name: _main
-# CHECK-NOT: - name:
-# CHECK: references:
-# CHECK-NEXT: - kind: ripRel32
-# CHECK-NEXT: offset: 7
-# CHECK-NEXT: target: L[[ID:[0-9]+]]
-# CHECK: - ref-name: L[[ID]]
-# CHECK-NEXT: scope: hidden
-# CHECK-NEXT: type: tlv-initializer-ptr
-# CHECK-NEXT: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK-NEXT: alignment: 8
-# CHECK-NEXT: permissions: rw-
-# CHECK-NEXT: references:
-# CHECK-NEXT: - kind: pointer64
-# CHECK-NEXT: offset: 0
-# CHECK-NEXT: target: _x
-
-# CHECK-ERROR: targeted OS version does not support use of thread local variables in _main for architecture x86_64
-
-# CHECK-LOADCMDS: sectname __thread_bss
-# CHECK-LOADCMDS: segname __DATA
-# CHECK-LOADCMDS: addr 0x{{[0-9A-F]*}}
-# CHECK-LOADCMDS: size 0x0000000000000004
-# CHECK-LOADCMDS: offset 0
-# CHECK-LOADCMDS: align 2^2 (4)
-# CHECK-LOADCMDS: reloff 0
-# CHECK-LOADCMDS: nreloc 0
-# CHECK-LOADCMDS: type S_THREAD_LOCAL_ZEROFILL
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -sdk_version 10.blah %s -o %t 2>&1 | FileCheck %s --check-prefix=ERROR
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# ERROR: malformed sdkVersion value
\ No newline at end of file
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -dylib \
-# RUN: -sectalign __DATA __custom 0x800 -sectalign __TEXT __text 0x400 \
-# RUN: %p/Inputs/x86_64/libSystem.yaml -o %t \
-# RUN: && llvm-readobj --sections %t | FileCheck %s
-#
-# Test -sectalign option on __text and a custom section.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x8B, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,
- 0x5D, 0xC3 ]
- relocations:
- - offset: 0x0000000C
- type: X86_64_RELOC_SIGNED
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000006
- type: X86_64_RELOC_SIGNED
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000014
- content: [ 0x0A, 0x00, 0x00, 0x00 ]
- - segment: __DATA
- section: __custom
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000018
- content: [ 0x0A, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _a
- type: N_SECT
- scope: [ N_EXT ]
- sect: 2
- value: 0x0000000000000014
- - name: _b
- type: N_SECT
- scope: [ N_EXT ]
- sect: 3
- value: 0x0000000000000018
- - name: _get
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
-...
-
-
-# CHECK: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
-# CHECK: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
-# CHECK: Address: 0xC00
-
-# CHECK: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00)
-# CHECK: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00)
-# CHECK: Address: 0x1000
-
-# CHECK: Name: __custom (5F 5F 63 75 73 74 6F 6D 00 00 00 00 00 00 00 00)
-# CHECK: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00)
-# CHECK: Address: 0x1800
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -dylib \
-# RUN: %p/Inputs/x86_64/libSystem.yaml -o %t \
-# RUN: && llvm-objdump --private-headers %t | FileCheck %s
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x8B, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,
- 0x5D, 0xC3 ]
-global-symbols:
- - name: _get
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
-...
-
-
-# CHECK: PURE_INSTRUCTIONS SOME_INSTRUCTIONS
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -r -arch x86_64 -o %t -sectcreate __DATA __data \
-# RUN: %p/Inputs/hw.raw_bytes -print_atoms | FileCheck %s
-
-# CHECK: --- !native
-# CHECK: path: '<linker-internal>'
-# CHECK: defined-atoms:
-# CHECK: - scope: global
-# CHECK: type: sectcreate
-# CHECK: content: [ 68, 65, 6C, 6C, 6F, 0A ]
-# CHECK: section-choice: custom-required
-# CHECK: section-name: '__DATA/__data'
-# CHECK: dead-strip: never
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 %s %p/Inputs/hello-world-arm64.yaml -o %t && llvm-objdump --private-headers %t | FileCheck %s
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: start
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
-
-...
-
-# CHECK: Load command 0
-# CHECK: cmd LC_SEGMENT_64
-# CHECK: cmdsize 72
-# CHECK: segname __PAGEZERO
-# CHECK: vmaddr
-# CHECK: vmsize
-# CHECK: fileoff
-# CHECK: filesize
-# CHECK: maxprot ---
-# CHECK: initprot ---
-# CHECK: nsects 0
-# CHECK: flags (none)
-# CHECK: Load command 1
-# CHECK: cmd LC_SEGMENT_64
-# CHECK: cmdsize 152
-# CHECK: segname __TEXT
-# CHECK: vmaddr
-# CHECK: vmsize
-# CHECK: fileoff
-# CHECK: filesize
-# CHECK: maxprot r-x
-# CHECK: initprot r-x
-# CHECK: nsects 1
-# CHECK: flags (none)
-# CHECK: Section
-# CHECK: sectname __text
-# CHECK: segname __TEXT
-# CHECK: addr
-# CHECK: size
-# CHECK: offset
-# CHECK: align 2^0 (1)
-# CHECK: reloff 0
-# CHECK: nreloc 0
-# CHECK: type S_REGULAR
-# CHECK: attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
-# CHECK: reserved1 0
-# CHECK: reserved2 0
-# CHECK: Load command 2
-# CHECK: cmd LC_SEGMENT_64
-# CHECK: cmdsize 72
-# CHECK: segname __LINKEDIT
-# CHECK: vmaddr
-# CHECK: vmsize
-# CHECK: fileoff
-# CHECK: filesize
-# CHECK: maxprot r--
-# CHECK: initprot r--
-# CHECK: nsects 0
-# CHECK: flags (none)
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/hello-world-x86_64.yaml -o %t && llvm-objdump --private-headers %t | FileCheck %s
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: start
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
-
-...
-
-# CHECK: Load command 0
-# CHECK: cmd LC_SEGMENT_64
-# CHECK: cmdsize 72
-# CHECK: segname __PAGEZERO
-# CHECK: vmaddr
-# CHECK: vmsize
-# CHECK: fileoff
-# CHECK: filesize
-# CHECK: maxprot ---
-# CHECK: initprot ---
-# CHECK: nsects 0
-# CHECK: flags (none)
-# CHECK: Load command 1
-# CHECK: cmd LC_SEGMENT_64
-# CHECK: cmdsize 152
-# CHECK: segname __TEXT
-# CHECK: vmaddr
-# CHECK: vmsize
-# CHECK: fileoff
-# CHECK: filesize
-# CHECK: maxprot rwx
-# CHECK: initprot r-x
-# CHECK: nsects 1
-# CHECK: flags (none)
-# CHECK: Section
-# CHECK: sectname __text
-# CHECK: segname __TEXT
-# CHECK: addr
-# CHECK: size
-# CHECK: offset
-# CHECK: align 2^0 (1)
-# CHECK: reloff 0
-# CHECK: nreloc 0
-# CHECK: type S_REGULAR
-# CHECK: attributes PURE_INSTRUCTIONS SOME_INSTRUCTIONS
-# CHECK: reserved1 0
-# CHECK: reserved2 0
-# CHECK: Load command 2
-# CHECK: cmd LC_SEGMENT_64
-# CHECK: cmdsize 72
-# CHECK: segname __LINKEDIT
-# CHECK: vmaddr
-# CHECK: vmsize
-# CHECK: fileoff
-# CHECK: filesize
-# CHECK: maxprot rwx
-# CHECK: initprot r--
-# CHECK: nsects 0
-# CHECK: flags (none)
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -source_version 10.blah %s -o %t 2>&1 | FileCheck %s --check-prefix=ERROR
-# RUN: ld64.lld.darwinold -arch x86_64 -source_version 10.1.2.3.4 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml && llvm-objdump --private-headers %t | FileCheck %s
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# ERROR: malformed source_version value
-
-# CHECK: Load command {{[0-9]*}}
-# CHECK: cmd LC_SOURCE_VERSION
-# CHECK: cmdsize 16
-# CHECK: version 10.1.2.3.4
\ No newline at end of file
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.9 %s -o %t %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-objdump --private-headers %t | FileCheck --check-prefix=CHECK-DEFAULT %s
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.9 %s -o %t -stack_size 31415926000 %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-objdump --private-headers %t | FileCheck --check-prefix=CHECK-EXPLICIT %s
-# RUN: not ld64.lld.darwinold -arch x86_64 -stack_size 0x31415926530 %s >/dev/null 2> %t
-# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-MISPAGED
-# RUN: not ld64.lld.darwinold -arch x86_64 -stack_size hithere %s >/dev/null 2> %t
-# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-NOTHEX
-
---- !native
-defined-atoms:
- - name: _main
- scope: global
- content: []
-
-# CHECK-DEFAULT: cmd LC_MAIN
-# CHECK-DEFAULT: stacksize 0
-
-# CHECK-EXPLICIT: cmd LC_MAIN
-# CHECK-EXPLICIT: stacksize 3384796143616
-
-# CHECK-ERROR-MISPAGED: error: stack_size must be a multiple of page size (0x1000)
-
-# CHECK-ERROR-NOTHEX: error: stack_size expects a hex number
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch i386 %s %p/Inputs/hello-world-x86.yaml -o %t
-# RUN: obj2yaml %t | FileCheck %s
-#
-# Test that the string table contains a ' ' as its first symbol
-#
-
---- !mach-o
-arch: x86
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0x58, 0x8D, 0x80, 0x16, 0x00,
- 0x00, 0x00, 0x89, 0x04, 0x24, 0xE8, 0xE6, 0xFF,
- 0xFF, 0xFF, 0x31, 0xC0, 0x83, 0xC4, 0x08, 0x5D,
- 0xC3 ]
- relocations:
- - offset: 0x00000016
- type: GENERIC_RELOC_VANILLA
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x0000000E
- scattered: true
- type: GENERIC_RELOC_LOCAL_SECTDIFF
- length: 2
- pc-rel: false
- value: 0x00000021
- - offset: 0x00000000
- scattered: true
- type: GENERIC_RELOC_PAIR
- length: 2
- pc-rel: false
- value: 0x0000000B
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000021
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _printf
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-# CHECK: StringTable:
-# CHECK-NEXT: - ' '
-# CHECK-NEXT: - __mh_execute_header
-# CHECK-NEXT: - _main
-# CHECK-NEXT: - _printf
-# CHECK-NEXT: - dyld_stub_binder
-# CHECK-NEXT: - ''
+++ /dev/null
-# REQUIRES: x86
-
-# RUN: mkdir -p %t
-#
-# RUN: llvm-mc -filetype obj -triple x86_64-apple-darwin %s -o %t/test.o
-# RUN: ld64.lld.darwinold -o %t/test -Z -L%S/Inputs/MacOSX.sdk/usr/lib -lSystem %t/test.o
-#
-# RUN: llvm-objdump --bind --no-show-raw-insn -d -r %t/test | FileCheck %s
-
-# CHECK: Disassembly of section __TEXT,__text:
-# CHECK: movq {{.*}} # [[ADDR:[0-9a-f]+]]
-
-# CHECK: Bind table:
-# CHECK: __DATA __got 0x[[ADDR]] pointer 0 libSystem ___nan
-
-.section __TEXT,__text
-.global _main
-
-_main:
- movq ___nan@GOTPCREL(%rip), %rax
- ret
+++ /dev/null
-# RUN: ld64.lld.darwinold -ios_simulator_version_min 5.0 -arch x86_64 -r %s -o %t
-# RUN: llvm-readobj --file-headers %t | FileCheck %s
-
-# Make sure that we have an objc image info in the output. It should have
-# been generated by the objc pass.
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-compat-version: 0.0
-current-version: 0.0
-has-UUID: false
-OS: unknown
-sections:
- - segment: __DATA
- section: __objc_imageinfo
- type: S_REGULAR
- attributes: [ S_ATTR_NO_DEAD_STRIP ]
- address: 0x0000000000000100
- content: [ 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00 ]
-...
-
-# The ObjC pass creates a new image info in a new MachoFile internal to the pass.
-# Make sure that we still have MH_SUBSECTIONS_VIA_SYMBOLS in the output file, even
-# though that file in the ObjCPass didn't get it set from being parsed.
-
-# CHECK: MH_SUBSECTIONS_VIA_SYMBOLS
\ No newline at end of file
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.9 -twolevel_namespace -undefined dynamic_lookup %s -o %t %p/Inputs/x86_64/libSystem.yaml
-#
-# Sanity check '-twolevel_namespace -undefined dynamic_lookup'.
-# This should pass without error, even though '_bar' is undefined.
-
---- !native
-defined-atoms:
- - name: _main
- scope: global
- content: [ E9, 00, 00, 00, 00 ]
- alignment: 16
- references:
- - kind: branch32
- offset: 1
- target: _bar
-undefined-atoms:
- - name: _bar
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.9 -twolevel_namespace -undefined warning %s -o %t %p/Inputs/x86_64/libSystem.yaml 2>&1 | \
-# RUN: FileCheck --check-prefix=CHECK-WARNING %s
-# RUN: not ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.9 -twolevel_namespace -undefined suppress %s -o %t %p/Inputs/x86_64/libSystem.yaml 2>&1 | \
-# RUN: FileCheck --check-prefix=CHECK-SUPPRESS %s
-
---- !native
-defined-atoms:
- - name: _main
- scope: global
- content: [ E9, 00, 00, 00, 00 ]
- alignment: 16
- references:
- - kind: branch32
- offset: 1
- target: _bar
-undefined-atoms:
- - name: _bar
-
-# Make sure that the driver issues an error diagnostic about this combination
-# being invalid.
-#
-# CHECK-WARNING: can't use -undefined warning or suppress with -twolevel_namespace
-# CHECK-SUPPRESS: can't use -undefined warning or suppress with -twolevel_namespace
\ No newline at end of file
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch arm64 -o %t %s \
-# RUN: %p/Inputs/unwind-info-simple-arm64.yaml -e _main %p/Inputs/arm64/libSystem.yaml
-# RUN: llvm-objdump --unwind-info %t | FileCheck %s
-
---- !mach-o
-arch: arm64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
- 0xE0, 0x03, 0x1E, 0x32, 0x00, 0x00, 0x00, 0x94,
- 0x48, 0x01, 0x80, 0x52, 0x08, 0x00, 0x00, 0xB9,
- 0x02, 0x00, 0x80, 0xD2, 0x01, 0x00, 0x00, 0x90,
- 0x21, 0x00, 0x40, 0xF9, 0x00, 0x00, 0x00, 0x94,
- 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
- 0xE0, 0x03, 0x1E, 0x32, 0x00, 0x00, 0x00, 0x94,
- 0x48, 0x01, 0x80, 0x52, 0x08, 0x00, 0x00, 0xB9,
- 0x02, 0x00, 0x80, 0xD2, 0x01, 0x00, 0x00, 0x90,
- 0x21, 0x00, 0x40, 0xF9, 0x00, 0x00, 0x00, 0x94,
- 0x3F, 0x04, 0x00, 0x71, 0x81, 0x00, 0x00, 0x54,
- 0x00, 0x00, 0x00, 0x94, 0xFD, 0x7B, 0xC1, 0xA8,
- 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x94,
- 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
- 0x00, 0x00, 0x00, 0x94 ]
- relocations:
- - offset: 0x00000070
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 5
- - offset: 0x00000064
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 7
- - offset: 0x00000060
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 12
- - offset: 0x00000058
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 11
- - offset: 0x0000004C
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 13
- - offset: 0x00000048
- type: ARM64_RELOC_GOT_LOAD_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 8
- - offset: 0x00000044
- type: ARM64_RELOC_GOT_LOAD_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 8
- - offset: 0x00000034
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 10
- - offset: 0x00000024
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 13
- - offset: 0x00000020
- type: ARM64_RELOC_GOT_LOAD_PAGEOFF12
- length: 2
- pc-rel: false
- extern: true
- symbol: 8
- - offset: 0x0000001C
- type: ARM64_RELOC_GOT_LOAD_PAGE21
- length: 2
- pc-rel: true
- extern: true
- symbol: 8
- - offset: 0x0000000C
- type: ARM64_RELOC_BRANCH26
- length: 2
- pc-rel: true
- extern: true
- symbol: 10
- - segment: __TEXT
- section: __gcc_except_tab
- type: S_REGULAR
- attributes: [ ]
- alignment: 2
- address: 0x0000000000000074
- content: [ 0xFF, 0x9B, 0xAF, 0x80, 0x00, 0x03, 0x27, 0x00,
- 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x01, 0x28, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
- 0xD0, 0xFF, 0xFF, 0xFF ]
- relocations:
- - offset: 0x00000030
- type: ARM64_RELOC_POINTER_TO_GOT
- length: 2
- pc-rel: true
- extern: true
- symbol: 9
- - segment: __LD
- section: __compact_unwind
- type: S_REGULAR
- attributes: [ ]
- alignment: 8
- address: 0x00000000000000A8
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000040
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000038
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 2
- - offset: 0x00000030
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: true
- symbol: 14
- - offset: 0x00000020
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM64_RELOC_UNSIGNED
- length: 3
- pc-rel: false
- extern: false
- symbol: 1
-local-symbols:
- - name: ltmp0
- type: N_SECT
- sect: 1
- value: 0x0000000000000000
- - name: ltmp14
- type: N_SECT
- sect: 2
- value: 0x0000000000000074
- - name: GCC_except_table1
- type: N_SECT
- sect: 2
- value: 0x0000000000000074
- - name: ltmp21
- type: N_SECT
- sect: 3
- value: 0x00000000000000A8
-global-symbols:
- - name: __Z3barv
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000028
- - name: __Z3foov
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000068
-undefined-symbols:
- - name: __Unwind_Resume
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: __ZTIi
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: __ZTIl
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_allocate_exception
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_begin_catch
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_end_catch
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___cxa_throw
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: ___gxx_personality_v0
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-
-# CHECK: Contents of __unwind_info section:
-# CHECK: Version: 0x1
-# CHECK: Common encodings array section offset: 0x1c
-# CHECK: Number of common encodings in array: 0x0
-# CHECK: Personality function array section offset: 0x1c
-# CHECK: Number of personality functions in array: 0x1
-# CHECK: Index array section offset: 0x20
-# CHECK: Number of indices in array: 0x2
-# CHECK: Common encodings: (count = 0)
-# CHECK: Personality functions: (count = 1)
-# CHECK: personality[1]: 0x00004020
-# CHECK: Top level indices: (count = 2)
-# CHECK: [0]: function offset=0x00003e68, 2nd level page offset=0x00000040, LSDA offset=0x00000038
-# CHECK: [1]: function offset=0x00003edc, 2nd level page offset=0x00000000, LSDA offset=0x00000040
-# CHECK: LSDA descriptors:
-# CHECK: [0]: function offset=0x00003e90, LSDA offset=0x00003f6c
-# CHECK: Second level indices:
-# CHECK: Second level index[0]: offset in section=0x00000040, base function offset=0x00003e68
-# CHECK: [0]: function offset=0x00003e68, encoding=0x04000000
-# CHECK: [1]: function offset=0x00003e90, encoding=0x54000000
-# CHECK: [2]: function offset=0x00003ed0, encoding=0x04000000
-# CHECK-NOT: Contents of __compact_unwind section
-
-
-
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s -o %t -e _main %p/Inputs/x86_64/libSystem.yaml
-# RUN: llvm-objdump --unwind-info %t | FileCheck %s
-
-# CHECK: Contents of __unwind_info section:
-# CHECK: Version: 0x1
-# CHECK: Common encodings array section offset: 0x1c
-# CHECK: Number of common encodings in array: 0x0
-# CHECK: Personality function array section offset: 0x1c
-# CHECK: Number of personality functions in array: 0x1
-# CHECK: Index array section offset: 0x20
-# CHECK: Number of indices in array: 0x2
-# CHECK: Common encodings: (count = 0)
-# CHECK: Personality functions: (count = 1)
-# CHECK: personality[1]: 0x00001000
-# CHECK: Top level indices: (count = 2)
-# CHECK: [0]: function offset=0x00000efb, 2nd level page offset=0x00000040, LSDA offset=0x00000038
-# CHECK: [1]: function offset=0x00000f00, 2nd level page offset=0x00000000, LSDA offset=0x00000040
-# CHECK: LSDA descriptors:
-# CHECK: [0]: function offset=0x00000efb, LSDA offset=0x00000f00
-# CHECK: Second level indices:
-# CHECK: Second level index[0]: offset in section=0x00000040, base function offset=0x00000efb
-# CHECK: [0]: function offset=0x00000efb, encoding=0x51000000
-# CHECK: [1]: function offset=0x00000efc, encoding=0x01000000
-# CHECK: [2]: function offset=0x00000efd, encoding=0x04000018
-# CHECK: [3]: function offset=0x00000efe, encoding=0x04000040
-# CHECK: [4]: function offset=0x00000eff, encoding=0x00000000
-# CHECK-NOT: Contents of __compact_unwind section
-
---- !native
-path: '<linker-internal>'
-defined-atoms:
- - name: GCC_except_table1
- type: unwind-lsda
- content: [ FF, 9B, A2, 80, 80, 00, 03, 1A, 08, 00, 00, 00,
- 05, 00, 00, 00, 1A, 00, 00, 00, 01, 0D, 00, 00,
- 00, 64, 00, 00, 00, 00, 00, 00, 00, 00, 01, 00,
- 04, 00, 00, 00 ]
- - type: compact-unwind
- content: [ 40, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00,
- 00, 00, 00, 41, 00, 00, 00, 00, 00, 00, 00, 00,
- E0, 00, 00, 00, 00, 00, 00, 00 ]
- references:
- - kind: pointer64Anon
- offset: 0
- target: __Z3barv
- - kind: pointer64
- offset: 16
- target: ___gxx_personality_v0
- - kind: pointer64Anon
- offset: 24
- target: GCC_except_table1
- - type: compact-unwind
- content: [ C0, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00,
- 00, 00, 00, 01, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00 ]
- references:
- - kind: pointer64Anon
- offset: 0
- target: _main
- - type: compact-unwind
- content: [ C1, 00, 00, 00, 00, 00, 00, 00, 01, 00, 00, 00,
- 00, 00, 00, 04, 00, 00, 00, 00, 00, 00, 00, 00,
- 00, 00, 00, 00, 00, 00, 00, 00 ]
- references:
- - kind: pointer64Anon
- offset: 0
- target: _needsDwarfButNoCompactUnwind
-
-# Generic x86_64 CIE:
- - name: LCIE
- type: unwind-cfi
- content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00,
- 01, 78, 10, 01, 10, 0C, 07, 08, 90, 01, 00, 00 ]
-
- - type: unwind-cfi
- content: [ 24, 00, 00, 00, 1C, 00, 00, 00, C8, FE, FF, FF,
- FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
- 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
- 00, 00, 00, 00 ]
- references:
- - kind: unwindFDEToFunction
- offset: 8
- target: _needsDwarfButNoCompactUnwind
- - kind: negDelta32
- offset: 4
- target: LCIE
-
- - type: unwind-cfi
- content: [ 24, 00, 00, 00, 44, 00, 00, 00, C8, FE, FF, FF,
- FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
- 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
- 00, 00, 00, 00 ]
- references:
- - kind: unwindFDEToFunction
- offset: 8
- target: _needsDwarfSaysCompactUnwind
- - kind: negDelta32
- offset: 4
- target: LCIE
-
- - type: unwind-cfi
- content: [ 24, 00, 00, 00, 6C, 00, 00, 00, C8, FE, FF, FF,
- FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
- 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
- 00, 00, 00, 00 ]
- references:
- - kind: unwindFDEToFunction
- offset: 8
- target: _main
- - kind: negDelta32
- offset: 4
- target: LCIE
-
- - name: __Z3barv
- scope: global
- content: [ C3 ]
- - name: _main
- scope: global
- content: [ C3 ]
- - name: _needsDwarfButNoCompactUnwind
- scope: global
- content: [ C3 ]
- - name: _needsDwarfSaysCompactUnwind
- scope: global
- content: [ C3 ]
- - name: _noUnwindData
- scope: global
- content: [ C3 ]
-
-shared-library-atoms:
- - name: ___gxx_personality_v0
- load-name: '/usr/lib/libc++abi.dylib'
- type: unknown
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -dylib %p/Inputs/bar.yaml \
-# RUN: -install_name /usr/lib/libbar.dylib %p/Inputs/x86_64/libSystem.yaml -o %t1.dylib
-# RUN: ld64.lld.darwinold -arch x86_64 -dylib %s -upward_library %t1.dylib \
-# RUN: -install_name /usr/lib/libfoo.dylib %p/Inputs/x86_64/libSystem.yaml -o %t
-# RUN: llvm-objdump --private-headers %t | FileCheck %s
-#
-#
-# Test upward linking: 1) build libbar.dylib, 2) build libfoo.dylib and upward
-# like with libbar.dylib, 3) dump load commands of libfoo and verify upward link.
-#
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
- 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000008
- type: X86_64_RELOC_BRANCH
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _bar
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
-...
-
-
-# CHECK: cmd LC_LOAD_UPWARD_DYLIB
-# CHECK-NEXT: cmdsize 48
-# CHECK-NEXT: name /usr/lib/libbar.dylib (offset 24)
+++ /dev/null
-#
-#
-# RUN: ld64.lld.darwinold -arch x86_64 -r -test_file_usage -v \
-# RUN: -path_exists /Custom/Frameworks \
-# RUN: -path_exists /Custom/Frameworks/Bar.framework/Bar \
-# RUN: -path_exists /usr/lib \
-# RUN: -path_exists /usr/lib/libfoo.dylib \
-# RUN: -path_exists /opt/stuff/libstuff.dylib \
-# RUN: -F/Custom/Frameworks \
-# RUN: -upward_framework Bar \
-# RUN: -upward-lfoo \
-# RUN: -upward_library /opt/stuff/libstuff.dylib \
-# RUN: 2>&1 | FileCheck %s
-
-# CHECK: Found upward framework /Custom/Frameworks/Bar.framework/Bar
-# CHECK: Found upward library /usr/lib/libfoo.dylib
-
-
+++ /dev/null
-# RUN: not ld64.lld.darwinold | FileCheck %s
-#
-# Test that running darwin linker with no option prints out usage message.
-#
-
-
-# CHECK: USAGE:
-# CHECK: -arch
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s \
-# RUN: %p/Inputs/use-simple-dylib.yaml %p/Inputs/x86_64/libSystem.yaml -dylib -o %t.dylib
-# RUN: llvm-objdump --private-headers %t.dylib | FileCheck %s
-
-# This test ensures that we have a LC_LOAD_DYLIB for libspecial.dylib even though we don't
-# use any atoms from it. This matches the ld64 behaviour.
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00,
- 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00,
- 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xE9, 0x00,
- 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
-
-# CHECK: cmd LC_LOAD_DYLIB
-# CHECK: name libspecial.dylib (offset 24)
-# CHECK: current version 1.0.0
-# CHECK: compatibility version 1.0.0
-# CHECK: cmd LC_LOAD_DYLIB
-# CHECK: name /usr/lib/libSystem.B.dylib (offset 24)
-# CHECK: current version 1.0.0
-# CHECK: compatibility version 1.0.0
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -print_atoms -r %s \
-# RUN: %p/Inputs/use-simple-dylib.yaml -o %t | FileCheck %s
-
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00,
- 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00,
- 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xE9, 0x00,
- 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _myGlobal
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _myGlobalWeak
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _myHidden
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _myHiddenWeak
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _myResolver
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _myStatic
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _myVariablePreviouslyKnownAsPrivateExtern
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-...
-
-
-# CHECK: undefined-atoms:
-# CHECK: - name: _myStatic
-# CHECK: - name: _myVariablePreviouslyKnownAsPrivateExtern
-# CHECK: shared-library-atoms:
-# CHECK: - name: _myGlobal
-# CHECK: load-name: libspecial.dylib
-# CHECK: - name: _myGlobalWeak
-# CHECK: load-name: libspecial.dylib
-# CHECK: - name: _myHidden
-# CHECK: load-name: libspecial.dylib
-# CHECK: - name: _myHiddenWeak
-# CHECK: load-name: libspecial.dylib
-# CHECK: - name: _myResolver
-# CHECK: load-name: libspecial.dylib
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s -o %t -r -macosx_version_min 10.8 && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 %s -o %t -r && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 %s -o %t -r %p/Inputs/no-version-min-load-command-object.yaml && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_VERSION_MIN
-
-# If we are emitting an object file, then we only emit a min version load command if the source object file(s) all have
-# version(s) and either known platforms or contain min version load commands themselves.
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-min-os-version-kind: LC_VERSION_MIN_MACOSX
-min-os-version: 10.8
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# CHECK: Load command {{[0-9]*}}
-# CHECK: cmd LC_VERSION_MIN_MACOSX
-# CHECK: cmdsize 16
-# CHECK: version 10.8
-# CHECK: sdk n/a
-
-# NO_VERSION_MIN-NOT: LC_VERSION_MIN_MACOSX
\ No newline at end of file
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml 2>&1 | FileCheck %s --check-prefix=WARNING
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -static -version_load_command && llvm-objdump --private-headers %t | FileCheck %s
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -no_version_load_command && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_VERSION_MIN
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -static -version_load_command -no_version_load_command && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_VERSION_MIN
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml -static && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=NO_VERSION_MIN
-
-# RUN: ld64.lld.darwinold -arch x86_64 -macosx_version_min 10.8 -sdk_version 10.9 %s -o %t -dylib %p/Inputs/x86_64/libSystem.yaml && llvm-objdump --private-headers %t | FileCheck %s --check-prefix=SDK_VERSION
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-# CHECK: Load command {{[0-9]*}}
-# CHECK: cmd LC_VERSION_MIN_MACOSX
-# CHECK: cmdsize 16
-# CHECK: version 10.8
-# CHECK: sdk 10.8
-
-# SDK_VERSION: Load command {{[0-9]*}}
-# SDK_VERSION: cmd LC_VERSION_MIN_MACOSX
-# SDK_VERSION: cmdsize 16
-# SDK_VERSION: version 10.8
-# SDK_VERSION: sdk 10.9
-
-# WARNING: warning: -sdk_version is required when emitting min version load command. Setting sdk version to match provided min version
-
-# NO_VERSION_MIN-NOT: LC_VERSION_MIN_MACOSX
+++ /dev/null
-# RUN: ld64.lld.darwinold -arch x86_64 %s %p/Inputs/write-final-sections.yaml \
-# RUN: -o %t -e _foo
-# RUN: llvm-readobj --sections --section-data %t | FileCheck %s
-
---- !native
-defined-atoms:
-# For __TEXT, __text (with typeCode)
- - name: _foo
- scope: global
- content: [ 55 ]
-# CHECK: Name: __text
-# CHECK: Segment: __TEXT
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 55
-# CHECK-NEXT: )
-
-# For __TEXT, __const (with typeConstant),
- - type: constant
- content: [ 01, 00, 00, 00 ]
-# From __TEXT, __literal4, (with typeLiteral4)
- - scope: hidden
- type: const-4-byte
- content: [ 02, 00, 00, 00 ]
-# From __TEXT, __literal8, (with typeLiteral8)
- - scope: hidden
- type: const-8-byte
- content: [ 03, 00, 00, 00, 00, 00, 00, 00 ]
-# From __TEXT, __literal16, (with typeLiteral16)
- - scope: hidden
- type: const-16-byte
- content: [ 04, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: Name: __const
-# CHECK: Segment: __TEXT
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 01000000 02000000 03000000 00000000
-# CHECK-NEXT: 0010: 04000000 00000000 00000000 00000000
-# CHECK-NEXT: )
-
-# For __TEXT, __cstring (with typeCString)
- - scope: hidden
- type: c-string
- content: [ 57, 69, 62, 62, 6C, 65, 00 ]
- merge: by-content
-# CHECK: Name: __cstring
-# CHECK: Segment: __TEXT
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 57696262 6C6500
-# CHECK-NEXT: )
-
-# For __TEXT, __ustring (with typeUTF16String)
- - scope: hidden
- type: utf16-string
- content: [ 05, 00 ]
- merge: by-content
-# CHECK: Name: __ustring
-# CHECK: Segment: __TEXT
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 0500
-# CHECK-NEXT: )
-
-# For __TEXT, __gcc_except_tab, (with typeLSDA)
- - name: GCC_except_table0
- type: unwind-lsda
- content: [ 06, 00 ]
-# CHECK: Name: __gcc_except_tab
-# CHECK: Segment: __TEXT
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 0600
-# CHECK-NEXT: )
-
-# For __TEXT, __eh_frame, (with typeCFI)
- - name: LCIE
- type: unwind-cfi
- content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00,
- 01, 78, 10, 01, 10, 0C, 07, 08, 90, 01, 00, 00 ]
-
- - type: unwind-cfi
- content: [ 24, 00, 00, 00, 1C, 00, 00, 00, C8, FE, FF, FF,
- FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
- 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
- 00, 00, 00, 00 ]
- references:
- - kind: unwindFDEToFunction
- offset: 8
- target: _foo
- - kind: negDelta32
- offset: 4
- target: LCIE
-
-# CHECK: Name: __eh_frame
-# CHECK: Segment: __TEXT
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 14000000 00000000 017A5200 01781001
-# CHECK-NEXT: 0010: 100C0708 90010000 24000000 1C000000
-# CHECK-NEXT: 0020: 70FFFFFF FFFFFFFF 01000000 00000000
-# CHECK-NEXT: 0030: 00410E10 8602430D 06000000 00000000
-# CHECK-NEXT: )
-
-# For __DATA, __data, (with typeData)
- - name: var
- type: data
- content: [ 08 ]
-# CHECK: Name: __data
-# CHECK: Segment: __DATA
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 08
-# CHECK-NEXT: )
-
-# For __DATA, __bss (with typeZeroFill)
-# FIXME: Attributes & tags of __bss are mostly broken. Should be at end of
-# __DATA, should have size, should have S_ZEROFILL flag.
- - type: zero-fill
- size: 8
-# CHECK: Name: __bss
-# CHECK: Segment: __DATA
-
-# For __DATA, __const, (with typeConstData)
- - type: const-data
- content: [ 09, 00, 00, 00 ]
-# CHECK: Name: __const
-# CHECK: Segment: __DATA
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 09000000
-# CHECK-NEXT: )
-
-# For __DATA, __cfstring, (with typeCFString)
- - type: cfstring
- content: [ 0A, 00 ]
-# CHECK: Name: __cfstring
-# CHECK: Segment: __DATA
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 0A00
-# CHECK-NEXT: )
-
-# For __DATA, __got (with typeGOT)
- - type: got
- content: [ 0B, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: Name: __got
-# CHECK: Segment: __DATA
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 0B000000 00000000
-# CHECK-NEXT: )
-
-
-# For __DATA, __mod_init_func (with typeInitializerPtr)
- - type: initializer-pointer
- content: [ 0C, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: Name: __mod_init_func
-# CHECK: Segment: __DATA
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 0C000000 00000000
-# CHECK-NEXT: )
-
-# For __DATA, __mod_term_func (with typeTerminatorPointer)
- - type: terminator-pointer
- content: [ 0D, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK: Name: __mod_term_func
-# CHECK: Segment: __DATA
-# CHECK: SectionData (
-# CHECK-NEXT: 0000: 0D000000 00000000
-# CHECK-NEXT: )
-
- - type: compact-unwind
- content: [ 0E, 00, 00, 00, 00, 00, 00, 00 ]
-# CHECK-NOT: Name: __compact_unwind
+++ /dev/null
-# RUN: not ld64.lld.darwinold -arch x86_64 -r %s \
-# RUN: %p/Inputs/wrong-arch-error.yaml 2> %t.err
-# RUN: FileCheck %s < %t.err
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0xCC ]
-
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-...
-
-
-# CHECK: wrong architecture
PRIVATE
lldCommon
lldCOFF
- lldDriver
lldELF
lldMachO
lldMinGW
if(NOT LLD_SYMLINKS_TO_CREATE)
set(LLD_SYMLINKS_TO_CREATE
- lld-link ld.lld ld64.lld ld64.lld.darwinnew ld64.lld.darwinold wasm-ld)
+ lld-link ld.lld ld64.lld wasm-ld)
endif()
foreach(link ${LLD_SYMLINKS_TO_CREATE})
enum Flavor {
Invalid,
- Gnu, // -flavor gnu
- WinLink, // -flavor link
- Darwin, // -flavor darwin
- DarwinOld, // -flavor darwinold
- Wasm, // -flavor wasm
+ Gnu, // -flavor gnu
+ WinLink, // -flavor link
+ Darwin, // -flavor darwin
+ Wasm, // -flavor wasm
};
[[noreturn]] static void die(const Twine &s) {
.CasesLower("ld", "ld.lld", "gnu", Gnu)
.CasesLower("wasm", "ld-wasm", Wasm)
.CaseLower("link", WinLink)
- .CasesLower("ld64", "ld64.lld", "darwin", "darwinnew",
- "ld64.lld.darwinnew", Darwin)
- .CasesLower("darwinold", "ld64.lld.darwinold", DarwinOld)
+ .CasesLower("ld64", "ld64.lld", "darwin", Darwin)
.Default(Invalid);
}
return !coff::link(args, exitEarly, stdoutOS, stderrOS);
case Darwin:
return !macho::link(args, exitEarly, stdoutOS, stderrOS);
- case DarwinOld:
- return !mach_o::link(args, exitEarly, stdoutOS, stderrOS);
case Wasm:
return !lld::wasm::link(args, exitEarly, stdoutOS, stderrOS);
default:
+++ /dev/null
-add_custom_target(LLDUnitTests)
-set_target_properties(LLDUnitTests PROPERTIES FOLDER "lld tests")
-
-set(CMAKE_BUILD_WITH_INSTALL_RPATH OFF)
-
-# add_lld_unittest(test_dirname file1.cpp file2.cpp)
-#
-# Will compile the list of files together and link against lld
-# Produces a binary named 'basename(test_dirname)'.
-function(add_lld_unittest test_dirname)
- add_unittest(LLDUnitTests ${test_dirname} ${ARGN})
- target_link_libraries(${test_dirname} ${LLVM_COMMON_LIBS})
-endfunction()
-
-add_subdirectory(DriverTests)
-add_subdirectory(MachOTests)
+++ /dev/null
-add_lld_unittest(DriverTests
- DarwinLdDriverTest.cpp
- )
-
-target_link_libraries(DriverTests
- PRIVATE
- lldDriver
- lldMachOOld
- )
+++ /dev/null
-//===- lld/unittest/DarwinLdDriverTest.cpp --------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// Darwin's ld driver tests.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Common/Driver.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-
-using namespace llvm;
-using namespace lld;
-
-namespace lld {
-namespace mach_o {
-bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx);
-}
-}
-
-namespace {
-class DarwinLdParserTest : public testing::Test {
-protected:
- int inputFileCount() { return _ctx.getNodes().size(); }
-
- StringRef inputFile(int index) {
- Node &node = *_ctx.getNodes()[index];
- if (node.kind() == Node::Kind::File)
- return cast<FileNode>(&node)->getFile()->path();
- llvm_unreachable("not handling other types of input files");
- }
-
- bool parse(std::vector<const char *> args) {
- args.insert(args.begin(), "ld");
- return mach_o::parse(args, _ctx);
- }
-
- MachOLinkingContext _ctx;
-};
-}
-
-TEST_F(DarwinLdParserTest, Basic) {
- EXPECT_TRUE(parse({"foo.o", "bar.o", "-arch", "i386"}));
- EXPECT_FALSE(_ctx.allowRemainingUndefines());
- EXPECT_FALSE(_ctx.deadStrip());
- EXPECT_EQ(2, inputFileCount());
- EXPECT_EQ("foo.o", inputFile(0));
- EXPECT_EQ("bar.o", inputFile(1));
-}
-
-TEST_F(DarwinLdParserTest, Output) {
- EXPECT_TRUE(parse({"-o", "my.out", "foo.o", "-arch", "i386"}));
- EXPECT_EQ("my.out", _ctx.outputPath());
-}
-
-TEST_F(DarwinLdParserTest, Dylib) {
- EXPECT_TRUE(parse({"-dylib", "foo.o", "-arch", "i386"}));
- EXPECT_EQ(llvm::MachO::MH_DYLIB, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Relocatable) {
- EXPECT_TRUE(parse({"-r", "foo.o", "-arch", "i386"}));
- EXPECT_EQ(llvm::MachO::MH_OBJECT, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Bundle) {
- EXPECT_TRUE(parse({"-bundle", "foo.o", "-arch", "i386"}));
- EXPECT_EQ(llvm::MachO::MH_BUNDLE, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Preload) {
- EXPECT_TRUE(parse({"-preload", "foo.o", "-arch", "i386"}));
- EXPECT_EQ(llvm::MachO::MH_PRELOAD, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Static) {
- EXPECT_TRUE(parse({"-static", "foo.o", "-arch", "i386"}));
- EXPECT_EQ(llvm::MachO::MH_EXECUTE, _ctx.outputMachOType());
-}
-
-TEST_F(DarwinLdParserTest, Entry) {
- EXPECT_TRUE(parse({"-e", "entryFunc", "foo.o", "-arch", "i386"}));
- EXPECT_EQ("entryFunc", _ctx.entrySymbolName());
-}
-
-TEST_F(DarwinLdParserTest, DeadStrip) {
- EXPECT_TRUE(parse({"-arch", "x86_64", "-dead_strip", "foo.o"}));
- EXPECT_TRUE(_ctx.deadStrip());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsExe) {
- EXPECT_TRUE(parse({"-arch", "x86_64", "-dead_strip", "foo.o"}));
- EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsDylib) {
- EXPECT_TRUE(parse({"-arch", "x86_64", "-dylib", "-dead_strip", "foo.o"}));
- EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsRelocatable) {
- EXPECT_TRUE(parse({"-arch", "x86_64", "-r", "-dead_strip", "foo.o"}));
- EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicExe) {
- EXPECT_TRUE(
- parse({"-arch", "x86_64", "-dead_strip", "-export_dynamic", "foo.o"}));
- EXPECT_TRUE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicDylib) {
- EXPECT_TRUE(parse({"-arch", "x86_64", "-dylib", "-dead_strip",
- "-export_dynamic", "foo.o"}));
- EXPECT_TRUE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, DeadStripRootsExportDynamicRelocatable) {
- EXPECT_TRUE(parse(
- {"-arch", "x86_64", "-r", "-dead_strip", "-export_dynamic", "foo.o"}));
- EXPECT_FALSE(_ctx.globalsAreDeadStripRoots());
-}
-
-TEST_F(DarwinLdParserTest, Arch) {
- EXPECT_TRUE(parse({"-arch", "x86_64", "foo.o"}));
- EXPECT_EQ(MachOLinkingContext::arch_x86_64, _ctx.arch());
- EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_X86_64, _ctx.getCPUType());
- EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_X86_64_ALL, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, Arch_x86) {
- EXPECT_TRUE(parse({"-arch", "i386", "foo.o"}));
- EXPECT_EQ(MachOLinkingContext::arch_x86, _ctx.arch());
- EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_I386, _ctx.getCPUType());
- EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_X86_ALL, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, Arch_armv6) {
- EXPECT_TRUE(parse({"-arch", "armv6", "foo.o"}));
- EXPECT_EQ(MachOLinkingContext::arch_armv6, _ctx.arch());
- EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_ARM, _ctx.getCPUType());
- EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_ARM_V6, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, Arch_armv7) {
- EXPECT_TRUE(parse({"-arch", "armv7", "foo.o"}));
- EXPECT_EQ(MachOLinkingContext::arch_armv7, _ctx.arch());
- EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_ARM, _ctx.getCPUType());
- EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_ARM_V7, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, Arch_armv7s) {
- EXPECT_TRUE(parse({"-arch", "armv7s", "foo.o"}));
- EXPECT_EQ(MachOLinkingContext::arch_armv7s, _ctx.arch());
- EXPECT_EQ((uint32_t)llvm::MachO::CPU_TYPE_ARM, _ctx.getCPUType());
- EXPECT_EQ(llvm::MachO::CPU_SUBTYPE_ARM_V7S, _ctx.getCPUSubType());
-}
-
-TEST_F(DarwinLdParserTest, MinMacOSX10_7) {
- EXPECT_TRUE(
- parse({"-macosx_version_min", "10.7", "foo.o", "-arch", "x86_64"}));
- EXPECT_EQ(MachOLinkingContext::OS::macOSX, _ctx.os());
- EXPECT_TRUE(_ctx.minOS("10.7", ""));
- EXPECT_FALSE(_ctx.minOS("10.8", ""));
-}
-
-TEST_F(DarwinLdParserTest, MinMacOSX10_8) {
- EXPECT_TRUE(
- parse({"-macosx_version_min", "10.8.3", "foo.o", "-arch", "x86_64"}));
- EXPECT_EQ(MachOLinkingContext::OS::macOSX, _ctx.os());
- EXPECT_TRUE(_ctx.minOS("10.7", ""));
- EXPECT_TRUE(_ctx.minOS("10.8", ""));
-}
-
-TEST_F(DarwinLdParserTest, iOS5) {
- EXPECT_TRUE(parse({"-ios_version_min", "5.0", "foo.o", "-arch", "armv7"}));
- EXPECT_EQ(MachOLinkingContext::OS::iOS, _ctx.os());
- EXPECT_TRUE(_ctx.minOS("", "5.0"));
- EXPECT_FALSE(_ctx.minOS("", "6.0"));
-}
-
-TEST_F(DarwinLdParserTest, iOS6) {
- EXPECT_TRUE(parse({"-ios_version_min", "6.0", "foo.o", "-arch", "armv7"}));
- EXPECT_EQ(MachOLinkingContext::OS::iOS, _ctx.os());
- EXPECT_TRUE(_ctx.minOS("", "5.0"));
- EXPECT_TRUE(_ctx.minOS("", "6.0"));
-}
-
-TEST_F(DarwinLdParserTest, iOS_Simulator5) {
- EXPECT_TRUE(
- parse({"-ios_simulator_version_min", "5.0", "a.o", "-arch", "i386"}));
- EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _ctx.os());
- EXPECT_TRUE(_ctx.minOS("", "5.0"));
- EXPECT_FALSE(_ctx.minOS("", "6.0"));
-}
-
-TEST_F(DarwinLdParserTest, iOS_Simulator6) {
- EXPECT_TRUE(
- parse({"-ios_simulator_version_min", "6.0", "a.o", "-arch", "i386"}));
- EXPECT_EQ(MachOLinkingContext::OS::iOS_simulator, _ctx.os());
- EXPECT_TRUE(_ctx.minOS("", "5.0"));
- EXPECT_TRUE(_ctx.minOS("", "6.0"));
-}
-
-TEST_F(DarwinLdParserTest, compatibilityVersion) {
- EXPECT_TRUE(parse(
- {"-dylib", "-compatibility_version", "1.2.3", "a.o", "-arch", "i386"}));
- EXPECT_EQ(_ctx.compatibilityVersion(), 0x10203U);
-}
-
-TEST_F(DarwinLdParserTest, compatibilityVersionInvalidType) {
- EXPECT_FALSE(parse(
- {"-bundle", "-compatibility_version", "1.2.3", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, compatibilityVersionInvalidValue) {
- EXPECT_FALSE(parse(
- {"-bundle", "-compatibility_version", "1,2,3", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, currentVersion) {
- EXPECT_TRUE(
- parse({"-dylib", "-current_version", "1.2.3", "a.o", "-arch", "i386"}));
- EXPECT_EQ(_ctx.currentVersion(), 0x10203U);
-}
-
-TEST_F(DarwinLdParserTest, currentVersionInvalidType) {
- EXPECT_FALSE(
- parse({"-bundle", "-current_version", "1.2.3", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, currentVersionInvalidValue) {
- EXPECT_FALSE(
- parse({"-bundle", "-current_version", "1,2,3", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, bundleLoader) {
- EXPECT_TRUE(
- parse({"-bundle", "-bundle_loader", "/bin/ls", "a.o", "-arch", "i386"}));
- EXPECT_EQ(_ctx.bundleLoader(), "/bin/ls");
-}
-
-TEST_F(DarwinLdParserTest, bundleLoaderInvalidType) {
- EXPECT_FALSE(parse({"-bundle_loader", "/bin/ls", "a.o", "-arch", "i386"}));
-}
-
-TEST_F(DarwinLdParserTest, deadStrippableDylib) {
- EXPECT_TRUE(
- parse({"-dylib", "-mark_dead_strippable_dylib", "a.o", "-arch", "i386"}));
- EXPECT_EQ(true, _ctx.deadStrippableDylib());
-}
-
-TEST_F(DarwinLdParserTest, deadStrippableDylibInvalidType) {
- EXPECT_FALSE(parse({"-mark_dead_strippable_dylib", "a.o", "-arch", "i386"}));
-}
+++ /dev/null
-
-add_lld_unittest(lldMachOOldTests
- MachONormalizedFileBinaryReaderTests.cpp
- MachONormalizedFileBinaryWriterTests.cpp
- MachONormalizedFileToAtomsTests.cpp
- MachONormalizedFileYAMLTests.cpp
- )
-
-target_link_libraries(lldMachOOldTests
- PRIVATE
- lldDriver
- lldMachOOld
- lldYAML
- )
+++ /dev/null
-//===- lld/unittest/MachOTests/MachONormalizedFileBinaryReaderTests.cpp ---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "gtest/gtest.h"
-#include <cstdint>
-#include <memory>
-
-using llvm::SmallString;
-using llvm::StringRef;
-using llvm::MemoryBuffer;
-using llvm::Twine;
-
-using namespace lld::mach_o::normalized;
-using namespace llvm::MachO;
-
-static std::unique_ptr<NormalizedFile>
-fromBinary(const uint8_t bytes[], unsigned length, StringRef archStr) {
- StringRef sr((const char*)bytes, length);
- std::unique_ptr<MemoryBuffer> mb(MemoryBuffer::getMemBuffer(sr, "", false));
- llvm::Expected<std::unique_ptr<NormalizedFile>> r =
- lld::mach_o::normalized::readBinary(
- mb, lld::MachOLinkingContext::archFromName(archStr));
- EXPECT_FALSE(!r);
- return std::move(*r);
-}
-
-// The Mach-O object reader uses functions such as read32 or read64
-// which don't allow unaligned access. Our in-memory object file
-// needs to be aligned to a larger boundary than uint8_t's.
-#if _MSC_VER
-#define FILEBYTES __declspec(align(64)) const uint8_t fileBytes[]
-#else
-#define FILEBYTES const uint8_t fileBytes[] __attribute__((aligned(64)))
-#endif
-
-TEST(BinaryReaderTest, empty_obj_x86_64) {
- FILEBYTES = {
- 0xcf, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x01,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x19, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5f, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- std::unique_ptr<NormalizedFile> f =
- fromBinary(fileBytes, sizeof(fileBytes), "x86_64");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
- EXPECT_EQ((int)(f->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, empty_obj_x86) {
- FILEBYTES = {
- 0xce, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74, 0x65,
- 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45,
- 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- std::unique_ptr<NormalizedFile> f =
- fromBinary(fileBytes, sizeof(fileBytes), "i386");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
- EXPECT_EQ((int)(f->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, empty_obj_ppc) {
- FILEBYTES = {
- 0xfe, 0xed, 0xfa, 0xce, 0x00, 0x00, 0x00, 0x12,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c,
- 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74, 0x65,
- 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45,
- 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- std::unique_ptr<NormalizedFile> f =
- fromBinary(fileBytes, sizeof(fileBytes), "ppc");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc);
- EXPECT_EQ((int)(f->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, empty_obj_armv7) {
- FILEBYTES = {
- 0xce, 0xfa, 0xed, 0xfe, 0x0c, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00,
- 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74, 0x65,
- 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45,
- 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- std::unique_ptr<NormalizedFile> f =
- fromBinary(fileBytes, sizeof(fileBytes), "armv7");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
- EXPECT_EQ((int)(f->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, empty_obj_x86_64_arm7) {
- FILEBYTES = {
-#include "empty_obj_x86_armv7.txt"
- };
- std::unique_ptr<NormalizedFile> f =
- fromBinary(fileBytes, sizeof(fileBytes), "x86_64");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
- EXPECT_EQ((int)(f->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-
- std::unique_ptr<NormalizedFile> f2 =
- fromBinary(fileBytes, sizeof(fileBytes), "armv7");
- EXPECT_EQ(f2->arch, lld::MachOLinkingContext::arch_armv7);
- EXPECT_EQ((int)(f2->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f2->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f2->localSymbols.empty());
- EXPECT_TRUE(f2->globalSymbols.empty());
- EXPECT_TRUE(f2->undefinedSymbols.empty());
-}
-
-TEST(BinaryReaderTest, hello_obj_x86_64) {
- FILEBYTES = {
- 0xCF, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 0x01,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00,
- 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x19, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x70, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0xA4, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x63, 0x73, 0x74, 0x72, 0x69, 0x6E,
- 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x9D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0xB4, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
- 0xE4, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x0B, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
- 0x48, 0x8D, 0x3D, 0x00, 0x00, 0x00, 0x00, 0xC7,
- 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x00,
- 0xE8, 0x00, 0x00, 0x00, 0x00, 0xB9, 0x00, 0x00,
- 0x00, 0x00, 0x89, 0x45, 0xF8, 0x89, 0xC8, 0x48,
- 0x83, 0xC4, 0x10, 0x5D, 0xC3, 0x68, 0x65, 0x6C,
- 0x6C, 0x6F, 0x0A, 0x00, 0x19, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x2D, 0x0B, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x1D, 0x0F, 0x00, 0x00, 0x00,
- 0x0E, 0x02, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x6D, 0x61,
- 0x69, 0x6E, 0x00, 0x5F, 0x70, 0x72, 0x69, 0x6E,
- 0x74, 0x66, 0x00, 0x4C, 0x5F, 0x2E, 0x73, 0x74,
- 0x72, 0x00, 0x00, 0x00 };
- std::unique_ptr<NormalizedFile> f =
- fromBinary(fileBytes, sizeof(fileBytes), "x86_64");
-
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
- EXPECT_EQ((int)(f->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_EQ(f->sections.size(), 2UL);
- const Section& text = f->sections[0];
- EXPECT_TRUE(text.segmentName.equals("__TEXT"));
- EXPECT_TRUE(text.sectionName.equals("__text"));
- EXPECT_EQ(text.type, S_REGULAR);
- EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)text.alignment, 16U);
- EXPECT_EQ(text.address, Hex64(0x0));
- EXPECT_EQ(text.content.size(), 45UL);
- EXPECT_EQ((int)(text.content[0]), 0x55);
- EXPECT_EQ((int)(text.content[1]), 0x48);
- EXPECT_TRUE(text.indirectSymbols.empty());
- EXPECT_EQ(text.relocations.size(), 2UL);
- const Relocation& call = text.relocations[0];
- EXPECT_EQ(call.offset, Hex32(0x19));
- EXPECT_EQ(call.type, X86_64_RELOC_BRANCH);
- EXPECT_EQ(call.length, 2);
- EXPECT_EQ(call.isExtern, true);
- EXPECT_EQ(call.symbol, 2U);
- const Relocation& str = text.relocations[1];
- EXPECT_EQ(str.offset, Hex32(0xB));
- EXPECT_EQ(str.type, X86_64_RELOC_SIGNED);
- EXPECT_EQ(str.length, 2);
- EXPECT_EQ(str.isExtern, true);
- EXPECT_EQ(str.symbol, 0U);
-
- const Section& cstring = f->sections[1];
- EXPECT_TRUE(cstring.segmentName.equals("__TEXT"));
- EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
- EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
- EXPECT_EQ(cstring.attributes, SectionAttr(0));
- EXPECT_EQ((uint16_t)cstring.alignment, 1U);
- EXPECT_EQ(cstring.address, Hex64(0x02D));
- EXPECT_EQ(cstring.content.size(), 7UL);
- EXPECT_EQ((int)(cstring.content[0]), 0x68);
- EXPECT_EQ((int)(cstring.content[1]), 0x65);
- EXPECT_EQ((int)(cstring.content[2]), 0x6c);
- EXPECT_TRUE(cstring.indirectSymbols.empty());
- EXPECT_TRUE(cstring.relocations.empty());
-
- EXPECT_EQ(f->localSymbols.size(), 1UL);
- const Symbol& strLabel = f->localSymbols[0];
- EXPECT_EQ(strLabel.type, N_SECT);
- EXPECT_EQ(strLabel.sect, 2);
- EXPECT_EQ(strLabel.value, Hex64(0x2D));
- EXPECT_EQ(f->globalSymbols.size(), 1UL);
- const Symbol& mainLabel = f->globalSymbols[0];
- EXPECT_TRUE(mainLabel.name.equals("_main"));
- EXPECT_EQ(mainLabel.type, N_SECT);
- EXPECT_EQ(mainLabel.sect, 1);
- EXPECT_EQ(mainLabel.scope, SymbolScope(N_EXT));
- EXPECT_EQ(mainLabel.value, Hex64(0x0));
- EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
- const Symbol& printfLabel = f->undefinedSymbols[0];
- EXPECT_TRUE(printfLabel.name.equals("_printf"));
- EXPECT_EQ(printfLabel.type, N_UNDF);
- EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
-}
-
-TEST(BinaryReaderTest, hello_obj_x86) {
- FILEBYTES = {
- 0xCE, 0xFA, 0xED, 0xFE, 0x07, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
- 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
- 0x37, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x74, 0x65,
- 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x54, 0x45,
- 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x7C, 0x01, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x63, 0x73, 0x74, 0x72, 0x69, 0x6E,
- 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x94, 0x01, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0xAC, 0x01, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x55, 0x89, 0xE5, 0x83,
- 0xEC, 0x18, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x58,
- 0x8D, 0x80, 0x25, 0x00, 0x00, 0x00, 0xC7, 0x45,
- 0xFC, 0x00, 0x00, 0x00, 0x00, 0x89, 0x04, 0x24,
- 0xE8, 0xDF, 0xFF, 0xFF, 0xFF, 0xB9, 0x00, 0x00,
- 0x00, 0x00, 0x89, 0x45, 0xF8, 0x89, 0xC8, 0x83,
- 0xC4, 0x18, 0x5D, 0xC3, 0x68, 0x65, 0x6C, 0x6C,
- 0x6F, 0x0A, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x0D, 0x0E, 0x00, 0x00, 0xA4,
- 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1,
- 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x6D, 0x61,
- 0x69, 0x6E, 0x00, 0x5F, 0x70, 0x72, 0x69, 0x6E,
- 0x74, 0x66, 0x00, 0x00
- };
- std::unique_ptr<NormalizedFile> f =
- fromBinary(fileBytes, sizeof(fileBytes), "i386");
-
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
- EXPECT_EQ((int)(f->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_EQ(f->sections.size(), 2UL);
- const Section& text = f->sections[0];
- EXPECT_TRUE(text.segmentName.equals("__TEXT"));
- EXPECT_TRUE(text.sectionName.equals("__text"));
- EXPECT_EQ(text.type, S_REGULAR);
- EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)text.alignment, 16U);
- EXPECT_EQ(text.address, Hex64(0x0));
- EXPECT_EQ(text.content.size(), 48UL);
- EXPECT_EQ((int)(text.content[0]), 0x55);
- EXPECT_EQ((int)(text.content[1]), 0x89);
- EXPECT_TRUE(text.indirectSymbols.empty());
- EXPECT_EQ(text.relocations.size(), 3UL);
- const Relocation& call = text.relocations[0];
- EXPECT_EQ(call.offset, Hex32(0x1D));
- EXPECT_EQ(call.scattered, false);
- EXPECT_EQ(call.type, GENERIC_RELOC_VANILLA);
- EXPECT_EQ(call.pcRel, true);
- EXPECT_EQ(call.length, 2);
- EXPECT_EQ(call.isExtern, true);
- EXPECT_EQ(call.symbol, 1U);
- const Relocation& sectDiff = text.relocations[1];
- EXPECT_EQ(sectDiff.offset, Hex32(0xE));
- EXPECT_EQ(sectDiff.scattered, true);
- EXPECT_EQ(sectDiff.type, GENERIC_RELOC_LOCAL_SECTDIFF);
- EXPECT_EQ(sectDiff.pcRel, false);
- EXPECT_EQ(sectDiff.length, 2);
- EXPECT_EQ(sectDiff.value, 0x30U);
- const Relocation& pair = text.relocations[2];
- EXPECT_EQ(pair.offset, Hex32(0x0));
- EXPECT_EQ(pair.scattered, true);
- EXPECT_EQ(pair.type, GENERIC_RELOC_PAIR);
- EXPECT_EQ(pair.pcRel, false);
- EXPECT_EQ(pair.length, 2);
- EXPECT_EQ(pair.value, 0x0BU);
-
- const Section& cstring = f->sections[1];
- EXPECT_TRUE(cstring.segmentName.equals("__TEXT"));
- EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
- EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
- EXPECT_EQ(cstring.attributes, SectionAttr(0));
- EXPECT_EQ((uint16_t)cstring.alignment, 1U);
- EXPECT_EQ(cstring.address, Hex64(0x030));
- EXPECT_EQ(cstring.content.size(), 7UL);
- EXPECT_EQ((int)(cstring.content[0]), 0x68);
- EXPECT_EQ((int)(cstring.content[1]), 0x65);
- EXPECT_EQ((int)(cstring.content[2]), 0x6c);
- EXPECT_TRUE(cstring.indirectSymbols.empty());
- EXPECT_TRUE(cstring.relocations.empty());
-
- EXPECT_EQ(f->localSymbols.size(), 0UL);
- EXPECT_EQ(f->globalSymbols.size(), 1UL);
- const Symbol& mainLabel = f->globalSymbols[0];
- EXPECT_TRUE(mainLabel.name.equals("_main"));
- EXPECT_EQ(mainLabel.type, N_SECT);
- EXPECT_EQ(mainLabel.sect, 1);
- EXPECT_EQ(mainLabel.scope, SymbolScope(N_EXT));
- EXPECT_EQ(mainLabel.value, Hex64(0x0));
- EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
- const Symbol& printfLabel = f->undefinedSymbols[0];
- EXPECT_TRUE(printfLabel.name.equals("_printf"));
- EXPECT_EQ(printfLabel.type, N_UNDF);
- EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
-}
-
-TEST(BinaryReaderTest, hello_obj_armv7) {
- FILEBYTES = {
- 0xCE, 0xFA, 0xED, 0xFE, 0x0C, 0x00, 0x00, 0x00,
- 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x28, 0x01, 0x00, 0x00,
- 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
- 0x31, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x74, 0x65,
- 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x54, 0x45,
- 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2A, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x78, 0x01, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x63, 0x73, 0x74, 0x72, 0x69, 0x6E,
- 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x6E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0xA0, 0x01, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
- 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x80, 0xB5, 0x6F, 0x46,
- 0x82, 0xB0, 0x40, 0xF2, 0x18, 0x00, 0xC0, 0xF2,
- 0x00, 0x00, 0x78, 0x44, 0x00, 0x21, 0xC0, 0xF2,
- 0x00, 0x01, 0x01, 0x91, 0xFF, 0xF7, 0xF2, 0xFF,
- 0x00, 0x21, 0xC0, 0xF2, 0x00, 0x01, 0x00, 0x90,
- 0x08, 0x46, 0x02, 0xB0, 0x80, 0xBD, 0x68, 0x65,
- 0x6C, 0x6C, 0x6F, 0x0A, 0x00, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x6D,
- 0x0A, 0x00, 0x00, 0xB9, 0x2A, 0x00, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0xB1, 0x0E, 0x00, 0x00, 0x00,
- 0x06, 0x00, 0x00, 0xA9, 0x2A, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xA1, 0x0E, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x0F, 0x01, 0x08, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x5F,
- 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x00
- };
- std::unique_ptr<NormalizedFile> f =
- fromBinary(fileBytes, sizeof(fileBytes), "armv7");
-
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
- EXPECT_EQ((int)(f->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_EQ(f->sections.size(), 2UL);
- const Section& text = f->sections[0];
- EXPECT_TRUE(text.segmentName.equals("__TEXT"));
- EXPECT_TRUE(text.sectionName.equals("__text"));
- EXPECT_EQ(text.type, S_REGULAR);
- EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)text.alignment, 4U);
- EXPECT_EQ(text.address, Hex64(0x0));
- EXPECT_EQ(text.content.size(), 42UL);
- EXPECT_EQ((int)(text.content[0]), 0x80);
- EXPECT_EQ((int)(text.content[1]), 0xB5);
- EXPECT_TRUE(text.indirectSymbols.empty());
- EXPECT_EQ(text.relocations.size(), 5UL);
- const Relocation& call = text.relocations[0];
- EXPECT_EQ(call.offset, Hex32(0x18));
- EXPECT_EQ(call.scattered, false);
- EXPECT_EQ(call.type, ARM_THUMB_RELOC_BR22);
- EXPECT_EQ(call.length, 2);
- EXPECT_EQ(call.isExtern, true);
- EXPECT_EQ(call.symbol, 1U);
- const Relocation& movt = text.relocations[1];
- EXPECT_EQ(movt.offset, Hex32(0xA));
- EXPECT_EQ(movt.scattered, true);
- EXPECT_EQ(movt.type, ARM_RELOC_HALF_SECTDIFF);
- EXPECT_EQ(movt.length, 3);
- EXPECT_EQ(movt.value, Hex32(0x2A));
- const Relocation& movtPair = text.relocations[2];
- EXPECT_EQ(movtPair.offset, Hex32(0x18));
- EXPECT_EQ(movtPair.scattered, true);
- EXPECT_EQ(movtPair.type, ARM_RELOC_PAIR);
- EXPECT_EQ(movtPair.length, 3);
- EXPECT_EQ(movtPair.value, Hex32(0xE));
- const Relocation& movw = text.relocations[3];
- EXPECT_EQ(movw.offset, Hex32(0x6));
- EXPECT_EQ(movw.scattered, true);
- EXPECT_EQ(movw.type, ARM_RELOC_HALF_SECTDIFF);
- EXPECT_EQ(movw.length, 2);
- EXPECT_EQ(movw.value, Hex32(0x2A));
- const Relocation& movwPair = text.relocations[4];
- EXPECT_EQ(movwPair.offset, Hex32(0x0));
- EXPECT_EQ(movwPair.scattered, true);
- EXPECT_EQ(movwPair.type, ARM_RELOC_PAIR);
- EXPECT_EQ(movwPair.length, 2);
- EXPECT_EQ(movwPair.value, Hex32(0xE));
-
- const Section& cstring = f->sections[1];
- EXPECT_TRUE(cstring.segmentName.equals("__TEXT"));
- EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
- EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
- EXPECT_EQ(cstring.attributes, SectionAttr(0));
- EXPECT_EQ((uint16_t)cstring.alignment, 1U);
- EXPECT_EQ(cstring.address, Hex64(0x02A));
- EXPECT_EQ(cstring.content.size(), 7UL);
- EXPECT_EQ((int)(cstring.content[0]), 0x68);
- EXPECT_EQ((int)(cstring.content[1]), 0x65);
- EXPECT_EQ((int)(cstring.content[2]), 0x6c);
- EXPECT_TRUE(cstring.indirectSymbols.empty());
- EXPECT_TRUE(cstring.relocations.empty());
-
- EXPECT_EQ(f->localSymbols.size(), 0UL);
- EXPECT_EQ(f->globalSymbols.size(), 1UL);
- const Symbol& mainLabel = f->globalSymbols[0];
- EXPECT_TRUE(mainLabel.name.equals("_main"));
- EXPECT_EQ(mainLabel.type, N_SECT);
- EXPECT_EQ(mainLabel.sect, 1);
- EXPECT_EQ(mainLabel.scope, SymbolScope(N_EXT));
- EXPECT_EQ(mainLabel.value, Hex64(0x0));
- EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
- const Symbol& printfLabel = f->undefinedSymbols[0];
- EXPECT_TRUE(printfLabel.name.equals("_printf"));
- EXPECT_EQ(printfLabel.type, N_UNDF);
- EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
-}
-
-TEST(BinaryReaderTest, hello_obj_ppc) {
- FILEBYTES = {
- 0xFE, 0xED, 0xFA, 0xCE, 0x00, 0x00, 0x00, 0x12,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x28,
- 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x01, 0x44,
- 0x00, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x00, 0x07,
- 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x74, 0x65,
- 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x54, 0x45,
- 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x44,
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x90,
- 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x63, 0x73, 0x74, 0x72, 0x69, 0x6E,
- 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x5F, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x07,
- 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
- 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x01, 0xB8,
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0xD0,
- 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0B,
- 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x7C, 0x08, 0x02, 0xA6,
- 0xBF, 0xC1, 0xFF, 0xF8, 0x90, 0x01, 0x00, 0x08,
- 0x94, 0x21, 0xFF, 0xB0, 0x7C, 0x3E, 0x0B, 0x78,
- 0x42, 0x9F, 0x00, 0x05, 0x7F, 0xE8, 0x02, 0xA6,
- 0x3C, 0x5F, 0x00, 0x00, 0x38, 0x62, 0x00, 0x2C,
- 0x4B, 0xFF, 0xFF, 0xDD, 0x38, 0x00, 0x00, 0x00,
- 0x7C, 0x03, 0x03, 0x78, 0x80, 0x21, 0x00, 0x00,
- 0x80, 0x01, 0x00, 0x08, 0x7C, 0x08, 0x03, 0xA6,
- 0xBB, 0xC1, 0xFF, 0xF8, 0x4E, 0x80, 0x00, 0x20,
- 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x01, 0xD3,
- 0xAB, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x44,
- 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
- 0xAC, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x44,
- 0xA1, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x18,
- 0x00, 0x00, 0x00, 0x01, 0x0F, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x5F,
- 0x70, 0x72, 0x69, 0x6E, 0x74, 0x66, 0x00, 0x00
- };
- std::unique_ptr<NormalizedFile> f =
- fromBinary(fileBytes, sizeof(fileBytes), "ppc");
-
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc);
- EXPECT_EQ((int)(f->fileType), MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_EQ(f->sections.size(), 2UL);
- const Section& text = f->sections[0];
- EXPECT_TRUE(text.segmentName.equals("__TEXT"));
- EXPECT_TRUE(text.sectionName.equals("__text"));
- EXPECT_EQ(text.type, S_REGULAR);
- EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)text.alignment, 4U);
- EXPECT_EQ(text.address, Hex64(0x0));
- EXPECT_EQ(text.content.size(), 68UL);
- EXPECT_EQ((int)(text.content[0]), 0x7C);
- EXPECT_EQ((int)(text.content[1]), 0x08);
- EXPECT_TRUE(text.indirectSymbols.empty());
- EXPECT_EQ(text.relocations.size(), 5UL);
- const Relocation& bl = text.relocations[0];
- EXPECT_EQ(bl.offset, Hex32(0x24));
- EXPECT_EQ(bl.type, PPC_RELOC_BR24);
- EXPECT_EQ(bl.length, 2);
- EXPECT_EQ(bl.isExtern, true);
- EXPECT_EQ(bl.symbol, 1U);
- const Relocation& lo = text.relocations[1];
- EXPECT_EQ(lo.offset, Hex32(0x20));
- EXPECT_EQ(lo.scattered, true);
- EXPECT_EQ(lo.type, PPC_RELOC_LO16_SECTDIFF);
- EXPECT_EQ(lo.length, 2);
- EXPECT_EQ(lo.value, Hex32(0x44));
- const Relocation& loPair = text.relocations[2];
- EXPECT_EQ(loPair.offset, Hex32(0x0));
- EXPECT_EQ(loPair.scattered, true);
- EXPECT_EQ(loPair.type, PPC_RELOC_PAIR);
- EXPECT_EQ(loPair.length, 2);
- EXPECT_EQ(loPair.value, Hex32(0x18));
- const Relocation& ha = text.relocations[3];
- EXPECT_EQ(ha.offset, Hex32(0x1C));
- EXPECT_EQ(ha.scattered, true);
- EXPECT_EQ(ha.type, PPC_RELOC_HA16_SECTDIFF);
- EXPECT_EQ(ha.length, 2);
- EXPECT_EQ(ha.value, Hex32(0x44));
- const Relocation& haPair = text.relocations[4];
- EXPECT_EQ(haPair.offset, Hex32(0x2c));
- EXPECT_EQ(haPair.scattered, true);
- EXPECT_EQ(haPair.type, PPC_RELOC_PAIR);
- EXPECT_EQ(haPair.length, 2);
- EXPECT_EQ(haPair.value, Hex32(0x18));
-
- const Section& cstring = f->sections[1];
- EXPECT_TRUE(cstring.segmentName.equals("__TEXT"));
- EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
- EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
- EXPECT_EQ(cstring.attributes, SectionAttr(0));
- EXPECT_EQ((uint16_t)cstring.alignment, 4U);
- EXPECT_EQ(cstring.address, Hex64(0x044));
- EXPECT_EQ(cstring.content.size(), 7UL);
- EXPECT_EQ((int)(cstring.content[0]), 0x68);
- EXPECT_EQ((int)(cstring.content[1]), 0x65);
- EXPECT_EQ((int)(cstring.content[2]), 0x6c);
- EXPECT_TRUE(cstring.indirectSymbols.empty());
- EXPECT_TRUE(cstring.relocations.empty());
-
- EXPECT_EQ(f->localSymbols.size(), 0UL);
- EXPECT_EQ(f->globalSymbols.size(), 1UL);
- const Symbol& mainLabel = f->globalSymbols[0];
- EXPECT_TRUE(mainLabel.name.equals("_main"));
- EXPECT_EQ(mainLabel.type, N_SECT);
- EXPECT_EQ(mainLabel.sect, 1);
- EXPECT_EQ(mainLabel.scope, SymbolScope(N_EXT));
- EXPECT_EQ(mainLabel.value, Hex64(0x0));
- EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
- const Symbol& printfLabel = f->undefinedSymbols[0];
- EXPECT_TRUE(printfLabel.name.equals("_printf"));
- EXPECT_EQ(printfLabel.type, N_UNDF);
- EXPECT_EQ(printfLabel.scope, SymbolScope(N_EXT));
-
- SmallString<128> tmpFl;
- std::error_code ec =
- llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
- EXPECT_FALSE(ec);
- llvm::Error ec2 = writeBinary(*f, tmpFl);
- EXPECT_FALSE(ec2);
- llvm::sys::fs::remove(tmpFl);
-}
+++ /dev/null
-//===- lld/unittest/MachOTests/MachONormalizedFileBinaryWriterTests.cpp ---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/FileSystem.h"
-#include "gtest/gtest.h"
-#include <cassert>
-#include <memory>
-#include <system_error>
-#include <vector>
-
-using llvm::StringRef;
-using llvm::MemoryBuffer;
-using llvm::SmallString;
-using llvm::Twine;
-using llvm::ErrorOr;
-using namespace llvm::MachO;
-using namespace lld::mach_o::normalized;
-
-// Parses binary mach-o file at specified path and returns
-// ownership of buffer to mb parameter and ownership of
-// Normalized file to nf parameter.
-static void fromBinary(StringRef path, std::unique_ptr<MemoryBuffer> &mb,
- std::unique_ptr<NormalizedFile> &nf, StringRef archStr) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = MemoryBuffer::getFile(path);
- std::error_code ec = mbOrErr.getError();
- EXPECT_FALSE(ec);
- mb = std::move(mbOrErr.get());
-
- llvm::Expected<std::unique_ptr<NormalizedFile>> r =
- lld::mach_o::normalized::readBinary(
- mb, lld::MachOLinkingContext::archFromName(archStr));
- EXPECT_FALSE(!r);
- nf.reset(r->release());
-}
-
-static Relocation
-makeReloc(unsigned addr, bool rel, bool ext, RelocationInfoType type,
- unsigned sym) {
- Relocation result;
- result.offset = addr;
- result.scattered = false;
- result.type = type;
- result.length = 2;
- result.pcRel = rel;
- result.isExtern = ext;
- result.value = 0;
- result.symbol = sym;
- return result;
-}
-
-static Relocation
-makeScatReloc(unsigned addr, RelocationInfoType type, unsigned value) {
- Relocation result;
- result.offset = addr;
- result.scattered = true;
- result.type = type;
- result.length = 2;
- result.pcRel = false;
- result.isExtern = true;
- result.value = value;
- result.symbol = 0;
- return result;
-}
-
-static Symbol
-makeUndefSymbol(StringRef name) {
- Symbol sym;
- sym.name = name;
- sym.type = N_UNDF;
- sym.scope = N_EXT;
- sym.sect = NO_SECT;
- sym.desc = 0;
- sym.value = 0;
- return sym;
-}
-
-
-static Symbol
-makeSymbol(StringRef name, unsigned addr) {
- Symbol sym;
- sym.name = name;
- sym.type = N_SECT;
- sym.scope = N_EXT;
- sym.sect = 1;
- sym.desc = 0;
- sym.value = addr;
- return sym;
-}
-
-static Symbol
-makeThumbSymbol(StringRef name, unsigned addr) {
- Symbol sym;
- sym.name = name;
- sym.type = N_SECT;
- sym.scope = N_EXT;
- sym.sect = 1;
- sym.desc = N_ARM_THUMB_DEF;
- sym.value = addr;
- return sym;
-}
-
-TEST(BinaryWriterTest, obj_relocs_x86_64) {
- SmallString<128> tmpFl;
- {
- NormalizedFile f;
- f.arch = lld::MachOLinkingContext::arch_x86_64;
- f.fileType = MH_OBJECT;
- f.flags = MH_SUBSECTIONS_VIA_SYMBOLS;
- f.os = lld::MachOLinkingContext::OS::macOSX;
- f.sections.resize(1);
- Section& text = f.sections.front();
- text.segmentName = "__TEXT";
- text.sectionName = "__text";
- text.type = S_REGULAR;
- text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS);
- text.alignment = 16;
- text.address = 0;
- const uint8_t textBytes[] = {
- 0xe8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x05,
- 0x00, 0x00, 0x00, 0x00, 0xff, 0x35, 0x00, 0x00,
- 0x00, 0x00, 0x8b, 0x05, 0x00, 0x00, 0x00, 0x00,
- 0xc6, 0x05, 0xff, 0xff, 0xff, 0xff, 0x12, 0xc7,
- 0x05, 0xfc, 0xff, 0xff, 0xff, 0x78, 0x56, 0x34,
- 0x12, 0x48, 0x8b, 0x3d, 0x00, 0x00, 0x00, 0x00 };
-
- text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
- text.relocations.push_back(makeReloc(0x01, false, true, X86_64_RELOC_BRANCH, 1));
- text.relocations.push_back(makeReloc(0x08, false, true, X86_64_RELOC_GOT_LOAD, 1));
- text.relocations.push_back(makeReloc(0x0E, false, true, X86_64_RELOC_GOT, 1));
- text.relocations.push_back(makeReloc(0x14, false, true, X86_64_RELOC_SIGNED, 1));
- text.relocations.push_back(makeReloc(0x1A, false, true, X86_64_RELOC_SIGNED_1, 1));
- text.relocations.push_back(makeReloc(0x21, false, true, X86_64_RELOC_SIGNED_4, 1));
- text.relocations.push_back(makeReloc(0x2C, false, true, X86_64_RELOC_TLV, 2));
-
- f.undefinedSymbols.push_back(makeUndefSymbol("_bar"));
- f.undefinedSymbols.push_back(makeUndefSymbol("_tbar"));
-
- std::error_code ec =
- llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
- EXPECT_FALSE(ec);
- llvm::Error ec2 = writeBinary(f, tmpFl);
- EXPECT_FALSE(ec2);
- }
-
- std::unique_ptr<MemoryBuffer> bufferOwner;
- std::unique_ptr<NormalizedFile> f2;
- fromBinary(tmpFl, bufferOwner, f2, "x86_64");
-
- EXPECT_EQ(lld::MachOLinkingContext::arch_x86_64, f2->arch);
- EXPECT_EQ(MH_OBJECT, f2->fileType);
- EXPECT_EQ(FileFlags(MH_SUBSECTIONS_VIA_SYMBOLS), f2->flags);
-
- EXPECT_TRUE(f2->localSymbols.empty());
- EXPECT_TRUE(f2->globalSymbols.empty());
- EXPECT_EQ(2UL, f2->undefinedSymbols.size());
- const Symbol& barUndef = f2->undefinedSymbols[0];
- EXPECT_TRUE(barUndef.name.equals("_bar"));
- EXPECT_EQ(N_UNDF, barUndef.type);
- EXPECT_EQ(SymbolScope(N_EXT), barUndef.scope);
- const Symbol& tbarUndef = f2->undefinedSymbols[1];
- EXPECT_TRUE(tbarUndef.name.equals("_tbar"));
- EXPECT_EQ(N_UNDF, tbarUndef.type);
- EXPECT_EQ(SymbolScope(N_EXT), tbarUndef.scope);
-
- EXPECT_EQ(1UL, f2->sections.size());
- const Section& text = f2->sections[0];
- EXPECT_TRUE(text.segmentName.equals("__TEXT"));
- EXPECT_TRUE(text.sectionName.equals("__text"));
- EXPECT_EQ(S_REGULAR, text.type);
- EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)text.alignment, 16U);
- EXPECT_EQ(text.address, Hex64(0x0));
- EXPECT_EQ(48UL, text.content.size());
- const Relocation& call = text.relocations[0];
- EXPECT_EQ(call.offset, Hex32(0x1));
- EXPECT_EQ(call.type, X86_64_RELOC_BRANCH);
- EXPECT_EQ(call.length, 2);
- EXPECT_EQ(call.isExtern, true);
- EXPECT_EQ(call.symbol, 1U);
- const Relocation& gotLoad = text.relocations[1];
- EXPECT_EQ(gotLoad.offset, Hex32(0x8));
- EXPECT_EQ(gotLoad.type, X86_64_RELOC_GOT_LOAD);
- EXPECT_EQ(gotLoad.length, 2);
- EXPECT_EQ(gotLoad.isExtern, true);
- EXPECT_EQ(gotLoad.symbol, 1U);
- const Relocation& gotUse = text.relocations[2];
- EXPECT_EQ(gotUse.offset, Hex32(0xE));
- EXPECT_EQ(gotUse.type, X86_64_RELOC_GOT);
- EXPECT_EQ(gotUse.length, 2);
- EXPECT_EQ(gotUse.isExtern, true);
- EXPECT_EQ(gotUse.symbol, 1U);
- const Relocation& signed0 = text.relocations[3];
- EXPECT_EQ(signed0.offset, Hex32(0x14));
- EXPECT_EQ(signed0.type, X86_64_RELOC_SIGNED);
- EXPECT_EQ(signed0.length, 2);
- EXPECT_EQ(signed0.isExtern, true);
- EXPECT_EQ(signed0.symbol, 1U);
- const Relocation& signed1 = text.relocations[4];
- EXPECT_EQ(signed1.offset, Hex32(0x1A));
- EXPECT_EQ(signed1.type, X86_64_RELOC_SIGNED_1);
- EXPECT_EQ(signed1.length, 2);
- EXPECT_EQ(signed1.isExtern, true);
- EXPECT_EQ(signed1.symbol, 1U);
- const Relocation& signed4 = text.relocations[5];
- EXPECT_EQ(signed4.offset, Hex32(0x21));
- EXPECT_EQ(signed4.type, X86_64_RELOC_SIGNED_4);
- EXPECT_EQ(signed4.length, 2);
- EXPECT_EQ(signed4.isExtern, true);
- EXPECT_EQ(signed4.symbol, 1U);
-
- bufferOwner.reset(nullptr);
- std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
- EXPECT_FALSE(ec);
-}
-
-
-
-TEST(BinaryWriterTest, obj_relocs_x86) {
- SmallString<128> tmpFl;
- {
- NormalizedFile f;
- f.arch = lld::MachOLinkingContext::arch_x86;
- f.fileType = MH_OBJECT;
- f.flags = MH_SUBSECTIONS_VIA_SYMBOLS;
- f.os = lld::MachOLinkingContext::OS::macOSX;
- f.sections.resize(1);
- Section& text = f.sections.front();
- text.segmentName = "__TEXT";
- text.sectionName = "__text";
- text.type = S_REGULAR;
- text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS);
- text.alignment = 16;
- text.address = 0;
- const uint8_t textBytes[] = {
- 0xe8, 0xfb, 0xff, 0xff, 0xff, 0xa1, 0x00, 0x00,
- 0x00, 0x00, 0x8b, 0xb0, 0xfb, 0xff, 0xff, 0xff,
- 0x8b, 0x80, 0x11, 0x00, 0x00, 0x00 };
-
- text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
- text.relocations.push_back(makeReloc(0x01, true, true, GENERIC_RELOC_VANILLA, 0));
- text.relocations.push_back(makeReloc(0x06, false, true, GENERIC_RELOC_VANILLA, 0));
- text.relocations.push_back(makeScatReloc(0x0c, GENERIC_RELOC_LOCAL_SECTDIFF, 0));
- text.relocations.push_back(makeScatReloc(0x0, GENERIC_RELOC_PAIR, 5));
- text.relocations.push_back(makeReloc(0x12, true, true, GENERIC_RELOC_TLV, 1));
-
- f.undefinedSymbols.push_back(makeUndefSymbol("_bar"));
- f.undefinedSymbols.push_back(makeUndefSymbol("_tbar"));
-
- std::error_code ec =
- llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
- EXPECT_FALSE(ec);
- llvm::Error ec2 = writeBinary(f, tmpFl);
- EXPECT_FALSE(ec2);
- }
- std::unique_ptr<MemoryBuffer> bufferOwner;
- std::unique_ptr<NormalizedFile> f2;
- fromBinary(tmpFl, bufferOwner, f2, "i386");
-
- EXPECT_EQ(lld::MachOLinkingContext::arch_x86, f2->arch);
- EXPECT_EQ(MH_OBJECT, f2->fileType);
- EXPECT_EQ(FileFlags(MH_SUBSECTIONS_VIA_SYMBOLS), f2->flags);
-
- EXPECT_TRUE(f2->localSymbols.empty());
- EXPECT_TRUE(f2->globalSymbols.empty());
- EXPECT_EQ(2UL, f2->undefinedSymbols.size());
- const Symbol& barUndef = f2->undefinedSymbols[0];
- EXPECT_TRUE(barUndef.name.equals("_bar"));
- EXPECT_EQ(N_UNDF, barUndef.type);
- EXPECT_EQ(SymbolScope(N_EXT), barUndef.scope);
- const Symbol& tbarUndef = f2->undefinedSymbols[1];
- EXPECT_TRUE(tbarUndef.name.equals("_tbar"));
- EXPECT_EQ(N_UNDF, tbarUndef.type);
- EXPECT_EQ(SymbolScope(N_EXT), tbarUndef.scope);
-
- EXPECT_EQ(1UL, f2->sections.size());
- const Section& text = f2->sections[0];
- EXPECT_TRUE(text.segmentName.equals("__TEXT"));
- EXPECT_TRUE(text.sectionName.equals("__text"));
- EXPECT_EQ(S_REGULAR, text.type);
- EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)text.alignment, 16U);
- EXPECT_EQ(text.address, Hex64(0x0));
- EXPECT_EQ(22UL, text.content.size());
- const Relocation& call = text.relocations[0];
- EXPECT_EQ(call.offset, Hex32(0x1));
- EXPECT_EQ(call.scattered, false);
- EXPECT_EQ(call.type, GENERIC_RELOC_VANILLA);
- EXPECT_EQ(call.pcRel, true);
- EXPECT_EQ(call.length, 2);
- EXPECT_EQ(call.isExtern, true);
- EXPECT_EQ(call.symbol, 0U);
- const Relocation& absLoad = text.relocations[1];
- EXPECT_EQ(absLoad.offset, Hex32(0x6));
- EXPECT_EQ(absLoad.scattered, false);
- EXPECT_EQ(absLoad.type, GENERIC_RELOC_VANILLA);
- EXPECT_EQ(absLoad.pcRel, false);
- EXPECT_EQ(absLoad.length, 2);
- EXPECT_EQ(absLoad.isExtern, true);
- EXPECT_EQ(absLoad.symbol,0U);
- const Relocation& pic1 = text.relocations[2];
- EXPECT_EQ(pic1.offset, Hex32(0xc));
- EXPECT_EQ(pic1.scattered, true);
- EXPECT_EQ(pic1.type, GENERIC_RELOC_LOCAL_SECTDIFF);
- EXPECT_EQ(pic1.length, 2);
- EXPECT_EQ(pic1.value, 0U);
- const Relocation& pic2 = text.relocations[3];
- EXPECT_EQ(pic2.offset, Hex32(0x0));
- EXPECT_EQ(pic1.scattered, true);
- EXPECT_EQ(pic2.type, GENERIC_RELOC_PAIR);
- EXPECT_EQ(pic2.length, 2);
- EXPECT_EQ(pic2.value, 5U);
- const Relocation& tlv = text.relocations[4];
- EXPECT_EQ(tlv.offset, Hex32(0x12));
- EXPECT_EQ(tlv.type, GENERIC_RELOC_TLV);
- EXPECT_EQ(tlv.length, 2);
- EXPECT_EQ(tlv.isExtern, true);
- EXPECT_EQ(tlv.symbol, 1U);
-
- // lld::errs() << "temp = " << tmpFl << "\n";
- bufferOwner.reset(nullptr);
- std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
- EXPECT_FALSE(ec);
-}
-
-
-
-TEST(BinaryWriterTest, obj_relocs_armv7) {
- SmallString<128> tmpFl;
- {
- NormalizedFile f;
- f.arch = lld::MachOLinkingContext::arch_armv7;
- f.fileType = MH_OBJECT;
- f.flags = MH_SUBSECTIONS_VIA_SYMBOLS;
- f.os = lld::MachOLinkingContext::OS::macOSX;
- f.sections.resize(1);
- Section& text = f.sections.front();
- text.segmentName = "__TEXT";
- text.sectionName = "__text";
- text.type = S_REGULAR;
- text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS);
- text.alignment = 4;
- text.address = 0;
- const uint8_t textBytes[] = {
- 0xff, 0xf7, 0xfe, 0xef, 0x40, 0xf2, 0x05, 0x01,
- 0xc0, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xbf };
-
- text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
- text.relocations.push_back(makeReloc(0x00, true, true,
- ARM_THUMB_RELOC_BR22, 2));
- text.relocations.push_back(makeScatReloc(0x04,
- ARM_RELOC_HALF_SECTDIFF, 0x10));
- text.relocations.push_back(makeScatReloc(0x00,
- ARM_RELOC_PAIR, 0xC));
- text.relocations.push_back(makeScatReloc(0x08,
- ARM_RELOC_HALF_SECTDIFF, 0x10));
- text.relocations.push_back(makeScatReloc(0x00,
- ARM_RELOC_PAIR, 0xC));
- text.relocations.push_back(makeReloc(0x0C, false, true,
- ARM_RELOC_VANILLA, 2));
-
- f.globalSymbols.push_back(makeThumbSymbol("_foo", 0x00));
- f.globalSymbols.push_back(makeThumbSymbol("_foo2", 0x10));
- f.undefinedSymbols.push_back(makeUndefSymbol("_bar"));
-
- std::error_code ec =
- llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
- EXPECT_FALSE(ec);
- llvm::Error ec2 = writeBinary(f, tmpFl);
- EXPECT_FALSE(ec2);
- }
- std::unique_ptr<MemoryBuffer> bufferOwner;
- std::unique_ptr<NormalizedFile> f2;
- fromBinary(tmpFl, bufferOwner, f2, "armv7");
-
- EXPECT_EQ(lld::MachOLinkingContext::arch_armv7, f2->arch);
- EXPECT_EQ(MH_OBJECT, f2->fileType);
- EXPECT_EQ(FileFlags(MH_SUBSECTIONS_VIA_SYMBOLS), f2->flags);
-
- EXPECT_TRUE(f2->localSymbols.empty());
- EXPECT_EQ(2UL, f2->globalSymbols.size());
- const Symbol& fooDef = f2->globalSymbols[0];
- EXPECT_TRUE(fooDef.name.equals("_foo"));
- EXPECT_EQ(N_SECT, fooDef.type);
- EXPECT_EQ(1, fooDef.sect);
- EXPECT_EQ(SymbolScope(N_EXT), fooDef.scope);
- const Symbol& foo2Def = f2->globalSymbols[1];
- EXPECT_TRUE(foo2Def.name.equals("_foo2"));
- EXPECT_EQ(N_SECT, foo2Def.type);
- EXPECT_EQ(1, foo2Def.sect);
- EXPECT_EQ(SymbolScope(N_EXT), foo2Def.scope);
-
- EXPECT_EQ(1UL, f2->undefinedSymbols.size());
- const Symbol& barUndef = f2->undefinedSymbols[0];
- EXPECT_TRUE(barUndef.name.equals("_bar"));
- EXPECT_EQ(N_UNDF, barUndef.type);
- EXPECT_EQ(SymbolScope(N_EXT), barUndef.scope);
-
- EXPECT_EQ(1UL, f2->sections.size());
- const Section& text = f2->sections[0];
- EXPECT_TRUE(text.segmentName.equals("__TEXT"));
- EXPECT_TRUE(text.sectionName.equals("__text"));
- EXPECT_EQ(S_REGULAR, text.type);
- EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)text.alignment, 4U);
- EXPECT_EQ(text.address, Hex64(0x0));
- EXPECT_EQ(18UL, text.content.size());
- const Relocation& blx = text.relocations[0];
- EXPECT_EQ(blx.offset, Hex32(0x0));
- EXPECT_EQ(blx.scattered, false);
- EXPECT_EQ(blx.type, ARM_THUMB_RELOC_BR22);
- EXPECT_EQ(blx.pcRel, true);
- EXPECT_EQ(blx.length, 2);
- EXPECT_EQ(blx.isExtern, true);
- EXPECT_EQ(blx.symbol, 2U);
- const Relocation& movw1 = text.relocations[1];
- EXPECT_EQ(movw1.offset, Hex32(0x4));
- EXPECT_EQ(movw1.scattered, true);
- EXPECT_EQ(movw1.type, ARM_RELOC_HALF_SECTDIFF);
- EXPECT_EQ(movw1.length, 2);
- EXPECT_EQ(movw1.value, 0x10U);
- const Relocation& movw2 = text.relocations[2];
- EXPECT_EQ(movw2.offset, Hex32(0x0));
- EXPECT_EQ(movw2.scattered, true);
- EXPECT_EQ(movw2.type, ARM_RELOC_PAIR);
- EXPECT_EQ(movw2.length, 2);
- EXPECT_EQ(movw2.value, Hex32(0xC));
- const Relocation& movt1 = text.relocations[3];
- EXPECT_EQ(movt1.offset, Hex32(0x8));
- EXPECT_EQ(movt1.scattered, true);
- EXPECT_EQ(movt1.type, ARM_RELOC_HALF_SECTDIFF);
- EXPECT_EQ(movt1.length, 2);
- EXPECT_EQ(movt1.value, Hex32(0x10));
- const Relocation& movt2 = text.relocations[4];
- EXPECT_EQ(movt2.offset, Hex32(0x0));
- EXPECT_EQ(movt2.scattered, true);
- EXPECT_EQ(movt2.type, ARM_RELOC_PAIR);
- EXPECT_EQ(movt2.length, 2);
- EXPECT_EQ(movt2.value, Hex32(0xC));
- const Relocation& absPointer = text.relocations[5];
- EXPECT_EQ(absPointer.offset, Hex32(0xC));
- EXPECT_EQ(absPointer.type, ARM_RELOC_VANILLA);
- EXPECT_EQ(absPointer.length, 2);
- EXPECT_EQ(absPointer.isExtern, true);
- EXPECT_EQ(absPointer.symbol, 2U);
-
- // lld::errs() << "temp = " << tmpFl << "\n";
- bufferOwner.reset(nullptr);
- std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
- EXPECT_FALSE(ec);
-}
-
-
-
-TEST(BinaryWriterTest, obj_relocs_ppc) {
- SmallString<128> tmpFl;
- {
- NormalizedFile f;
- f.arch = lld::MachOLinkingContext::arch_ppc;
- f.fileType = MH_OBJECT;
- f.flags = MH_SUBSECTIONS_VIA_SYMBOLS;
- f.os = lld::MachOLinkingContext::OS::macOSX;
- f.sections.resize(1);
- Section& text = f.sections.front();
- text.segmentName = "__TEXT";
- text.sectionName = "__text";
- text.type = S_REGULAR;
- text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS);
- text.alignment = 4;
- text.address = 0;
- const uint8_t textBytes[] = {
- 0x48, 0x00, 0x00, 0x01, 0x40, 0x82, 0xff, 0xfc,
- 0x3c, 0x62, 0x00, 0x00, 0x3c, 0x62, 0x00, 0x00,
- 0x80, 0x63, 0x00, 0x24, 0x80, 0x63, 0x00, 0x24,
- 0x3c, 0x40, 0x00, 0x00, 0x3c, 0x60, 0x00, 0x00,
- 0x80, 0x42, 0x00, 0x28, 0x80, 0x63, 0x00, 0x28,
- 0x60, 0x00, 0x00, 0x00 };
-
- text.content = llvm::makeArrayRef(textBytes, sizeof(textBytes));
- text.relocations.push_back(makeReloc(0x00, true, true,
- PPC_RELOC_BR24, 2));
- text.relocations.push_back(makeReloc(0x04, true, true,
- PPC_RELOC_BR14, 2));
- text.relocations.push_back(makeScatReloc(0x08,
- PPC_RELOC_HI16_SECTDIFF, 0x28));
- text.relocations.push_back(makeScatReloc(0x24,
- PPC_RELOC_PAIR, 0x4));
- text.relocations.push_back(makeScatReloc(0x0C,
- PPC_RELOC_HA16_SECTDIFF, 0x28));
- text.relocations.push_back(makeScatReloc(0x24,
- PPC_RELOC_PAIR, 0x4));
- text.relocations.push_back(makeScatReloc(0x10,
- PPC_RELOC_LO16_SECTDIFF, 0x28));
- text.relocations.push_back(makeScatReloc(0x00,
- PPC_RELOC_PAIR, 0x4));
- text.relocations.push_back(makeScatReloc(0x14,
- PPC_RELOC_LO14_SECTDIFF, 0x28));
- text.relocations.push_back(makeScatReloc(0x00,
- PPC_RELOC_PAIR, 0x4));
- text.relocations.push_back(makeReloc(0x18, false, false,
- PPC_RELOC_HI16, 1));
- text.relocations.push_back(makeReloc(0x28, false, false,
- PPC_RELOC_PAIR, 0));
- text.relocations.push_back(makeReloc(0x1C, false, false,
- PPC_RELOC_HA16, 1));
- text.relocations.push_back(makeReloc(0x28, false, false,
- PPC_RELOC_PAIR, 0));
- text.relocations.push_back(makeReloc(0x20, false, false,
- PPC_RELOC_LO16, 1));
- text.relocations.push_back(makeReloc(0x00, false, false,
- PPC_RELOC_PAIR, 0));
- text.relocations.push_back(makeReloc(0x24, false, false,
- PPC_RELOC_LO14, 1));
- text.relocations.push_back(makeReloc(0x00, false, false,
- PPC_RELOC_PAIR, 0));
-
- f.globalSymbols.push_back(makeSymbol("_foo", 0x00));
- f.globalSymbols.push_back(makeSymbol("_foo2", 0x28));
- f.undefinedSymbols.push_back(makeUndefSymbol("_bar"));
-
- std::error_code ec =
- llvm::sys::fs::createTemporaryFile(Twine("xx"), "o", tmpFl);
- EXPECT_FALSE(ec);
- llvm::Error ec2 = writeBinary(f, tmpFl);
- EXPECT_FALSE(ec2);
- }
- std::unique_ptr<MemoryBuffer> bufferOwner;
- std::unique_ptr<NormalizedFile> f2;
- fromBinary(tmpFl, bufferOwner, f2, "ppc");
-
- EXPECT_EQ(lld::MachOLinkingContext::arch_ppc, f2->arch);
- EXPECT_EQ(MH_OBJECT, f2->fileType);
- EXPECT_EQ(FileFlags(MH_SUBSECTIONS_VIA_SYMBOLS), f2->flags);
-
- EXPECT_TRUE(f2->localSymbols.empty());
- EXPECT_EQ(2UL, f2->globalSymbols.size());
- const Symbol& fooDef = f2->globalSymbols[0];
- EXPECT_TRUE(fooDef.name.equals("_foo"));
- EXPECT_EQ(N_SECT, fooDef.type);
- EXPECT_EQ(1, fooDef.sect);
- EXPECT_EQ(SymbolScope(N_EXT), fooDef.scope);
- const Symbol& foo2Def = f2->globalSymbols[1];
- EXPECT_TRUE(foo2Def.name.equals("_foo2"));
- EXPECT_EQ(N_SECT, foo2Def.type);
- EXPECT_EQ(1, foo2Def.sect);
- EXPECT_EQ(SymbolScope(N_EXT), foo2Def.scope);
-
- EXPECT_EQ(1UL, f2->undefinedSymbols.size());
- const Symbol& barUndef = f2->undefinedSymbols[0];
- EXPECT_TRUE(barUndef.name.equals("_bar"));
- EXPECT_EQ(N_UNDF, barUndef.type);
- EXPECT_EQ(SymbolScope(N_EXT), barUndef.scope);
-
- EXPECT_EQ(1UL, f2->sections.size());
- const Section& text = f2->sections[0];
- EXPECT_TRUE(text.segmentName.equals("__TEXT"));
- EXPECT_TRUE(text.sectionName.equals("__text"));
- EXPECT_EQ(S_REGULAR, text.type);
- EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)text.alignment, 4U);
- EXPECT_EQ(text.address, Hex64(0x0));
- EXPECT_EQ(44UL, text.content.size());
- const Relocation& br24 = text.relocations[0];
- EXPECT_EQ(br24.offset, Hex32(0x0));
- EXPECT_EQ(br24.scattered, false);
- EXPECT_EQ(br24.type, PPC_RELOC_BR24);
- EXPECT_EQ(br24.pcRel, true);
- EXPECT_EQ(br24.length, 2);
- EXPECT_EQ(br24.isExtern, true);
- EXPECT_EQ(br24.symbol, 2U);
- const Relocation& br14 = text.relocations[1];
- EXPECT_EQ(br14.offset, Hex32(0x4));
- EXPECT_EQ(br14.scattered, false);
- EXPECT_EQ(br14.type, PPC_RELOC_BR14);
- EXPECT_EQ(br14.pcRel, true);
- EXPECT_EQ(br14.length, 2);
- EXPECT_EQ(br14.isExtern, true);
- EXPECT_EQ(br14.symbol, 2U);
- const Relocation& pichi1 = text.relocations[2];
- EXPECT_EQ(pichi1.offset, Hex32(0x8));
- EXPECT_EQ(pichi1.scattered, true);
- EXPECT_EQ(pichi1.type, PPC_RELOC_HI16_SECTDIFF);
- EXPECT_EQ(pichi1.length, 2);
- EXPECT_EQ(pichi1.value, 0x28U);
- const Relocation& pichi2 = text.relocations[3];
- EXPECT_EQ(pichi2.offset, Hex32(0x24));
- EXPECT_EQ(pichi2.scattered, true);
- EXPECT_EQ(pichi2.type, PPC_RELOC_PAIR);
- EXPECT_EQ(pichi2.length, 2);
- EXPECT_EQ(pichi2.value, 0x4U);
- const Relocation& picha1 = text.relocations[4];
- EXPECT_EQ(picha1.offset, Hex32(0xC));
- EXPECT_EQ(picha1.scattered, true);
- EXPECT_EQ(picha1.type, PPC_RELOC_HA16_SECTDIFF);
- EXPECT_EQ(picha1.length, 2);
- EXPECT_EQ(picha1.value, 0x28U);
- const Relocation& picha2 = text.relocations[5];
- EXPECT_EQ(picha2.offset, Hex32(0x24));
- EXPECT_EQ(picha2.scattered, true);
- EXPECT_EQ(picha2.type, PPC_RELOC_PAIR);
- EXPECT_EQ(picha2.length, 2);
- EXPECT_EQ(picha2.value, 0x4U);
- const Relocation& piclo1 = text.relocations[6];
- EXPECT_EQ(piclo1.offset, Hex32(0x10));
- EXPECT_EQ(piclo1.scattered, true);
- EXPECT_EQ(piclo1.type, PPC_RELOC_LO16_SECTDIFF);
- EXPECT_EQ(piclo1.length, 2);
- EXPECT_EQ(piclo1.value, 0x28U);
- const Relocation& piclo2 = text.relocations[7];
- EXPECT_EQ(piclo2.offset, Hex32(0x0));
- EXPECT_EQ(piclo2.scattered, true);
- EXPECT_EQ(piclo2.type, PPC_RELOC_PAIR);
- EXPECT_EQ(piclo2.length, 2);
- EXPECT_EQ(piclo2.value, 0x4U);
- const Relocation& picloa1 = text.relocations[8];
- EXPECT_EQ(picloa1.offset, Hex32(0x14));
- EXPECT_EQ(picloa1.scattered, true);
- EXPECT_EQ(picloa1.type, PPC_RELOC_LO14_SECTDIFF);
- EXPECT_EQ(picloa1.length, 2);
- EXPECT_EQ(picloa1.value, 0x28U);
- const Relocation& picloa2 = text.relocations[9];
- EXPECT_EQ(picloa2.offset, Hex32(0x0));
- EXPECT_EQ(picloa2.scattered, true);
- EXPECT_EQ(picloa2.type, PPC_RELOC_PAIR);
- EXPECT_EQ(picloa2.length, 2);
- EXPECT_EQ(picloa2.value, 0x4U);
- const Relocation& abshi1 = text.relocations[10];
- EXPECT_EQ(abshi1.offset, Hex32(0x18));
- EXPECT_EQ(abshi1.scattered, false);
- EXPECT_EQ(abshi1.type, PPC_RELOC_HI16);
- EXPECT_EQ(abshi1.length, 2);
- EXPECT_EQ(abshi1.symbol, 1U);
- const Relocation& abshi2 = text.relocations[11];
- EXPECT_EQ(abshi2.offset, Hex32(0x28));
- EXPECT_EQ(abshi2.scattered, false);
- EXPECT_EQ(abshi2.type, PPC_RELOC_PAIR);
- EXPECT_EQ(abshi2.length, 2);
- EXPECT_EQ(abshi2.symbol, 0U);
- const Relocation& absha1 = text.relocations[12];
- EXPECT_EQ(absha1.offset, Hex32(0x1C));
- EXPECT_EQ(absha1.scattered, false);
- EXPECT_EQ(absha1.type, PPC_RELOC_HA16);
- EXPECT_EQ(absha1.length, 2);
- EXPECT_EQ(absha1.symbol, 1U);
- const Relocation& absha2 = text.relocations[13];
- EXPECT_EQ(absha2.offset, Hex32(0x28));
- EXPECT_EQ(absha2.scattered, false);
- EXPECT_EQ(absha2.type, PPC_RELOC_PAIR);
- EXPECT_EQ(absha2.length, 2);
- EXPECT_EQ(absha2.symbol, 0U);
- const Relocation& abslo1 = text.relocations[14];
- EXPECT_EQ(abslo1.offset, Hex32(0x20));
- EXPECT_EQ(abslo1.scattered, false);
- EXPECT_EQ(abslo1.type, PPC_RELOC_LO16);
- EXPECT_EQ(abslo1.length, 2);
- EXPECT_EQ(abslo1.symbol, 1U);
- const Relocation& abslo2 = text.relocations[15];
- EXPECT_EQ(abslo2.offset, Hex32(0x00));
- EXPECT_EQ(abslo2.scattered, false);
- EXPECT_EQ(abslo2.type, PPC_RELOC_PAIR);
- EXPECT_EQ(abslo2.length, 2);
- EXPECT_EQ(abslo2.symbol, 0U);
- const Relocation& absloa1 = text.relocations[16];
- EXPECT_EQ(absloa1.offset, Hex32(0x24));
- EXPECT_EQ(absloa1.scattered, false);
- EXPECT_EQ(absloa1.type, PPC_RELOC_LO14);
- EXPECT_EQ(absloa1.length, 2);
- EXPECT_EQ(absloa1.symbol, 1U);
- const Relocation& absloa2 = text.relocations[17];
- EXPECT_EQ(absloa2.offset, Hex32(0x00));
- EXPECT_EQ(absloa2.scattered, false);
- EXPECT_EQ(absloa2.type, PPC_RELOC_PAIR);
- EXPECT_EQ(absloa2.length, 2);
- EXPECT_EQ(absloa2.symbol, 0U);
-
- bufferOwner.reset(nullptr);
- std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
- EXPECT_FALSE(ec);
-}
+++ /dev/null
-//===- lld/unittest/MachOTests/MachONormalizedFileToAtomsTests.cpp --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/YAMLTraits.h"
-#include "gtest/gtest.h"
-#include <cstdint>
-#include <memory>
-
-using namespace lld::mach_o::normalized;
-using namespace llvm::MachO;
-
-TEST(ToAtomsTest, empty_obj_x86_64) {
- NormalizedFile f;
- f.arch = lld::MachOLinkingContext::arch_x86_64;
- llvm::Expected<std::unique_ptr<const lld::File>> atom_f =
- normalizedToAtoms(f, "", false);
- EXPECT_FALSE(!atom_f);
- EXPECT_EQ(0U, (*atom_f)->defined().size());
-}
-
-TEST(ToAtomsTest, basic_obj_x86_64) {
- NormalizedFile f;
- f.arch = lld::MachOLinkingContext::arch_x86_64;
- Section textSection;
- static const uint8_t contentBytes[] = { 0x90, 0xC3, 0xC3, 0xC4 };
- const unsigned contentSize = sizeof(contentBytes) / sizeof(contentBytes[0]);
- textSection.content = llvm::makeArrayRef(contentBytes, contentSize);
- f.sections.push_back(textSection);
- Symbol fooSymbol;
- fooSymbol.name = "_foo";
- fooSymbol.type = N_SECT;
- fooSymbol.scope = N_EXT;
- fooSymbol.sect = 1;
- fooSymbol.value = 0;
- f.globalSymbols.push_back(fooSymbol);
- Symbol barSymbol;
- barSymbol.name = "_bar";
- barSymbol.type = N_SECT;
- barSymbol.scope = N_EXT;
- barSymbol.sect = 1;
- barSymbol.value = 2;
- f.globalSymbols.push_back(barSymbol);
- Symbol undefSym;
- undefSym.name = "_undef";
- undefSym.type = N_UNDF;
- f.undefinedSymbols.push_back(undefSym);
- Symbol bazSymbol;
- bazSymbol.name = "_baz";
- bazSymbol.type = N_SECT;
- bazSymbol.scope = N_EXT | N_PEXT;
- bazSymbol.sect = 1;
- bazSymbol.value = 3;
- f.localSymbols.push_back(bazSymbol);
-
- llvm::Expected<std::unique_ptr<const lld::File>> atom_f =
- normalizedToAtoms(f, "", false);
- EXPECT_FALSE(!atom_f);
- const lld::File &file = **atom_f;
- EXPECT_EQ(3U, file.defined().size());
- auto it = file.defined().begin();
- const lld::DefinedAtom *atom1 = *it;
- ++it;
- const lld::DefinedAtom *atom2 = *it;
- ++it;
- const lld::DefinedAtom *atom3 = *it;
- const lld::UndefinedAtom *atom4 = *file.undefined().begin();
- EXPECT_TRUE(atom1->name().equals("_foo"));
- EXPECT_EQ(2U, atom1->rawContent().size());
- EXPECT_EQ(0x90, atom1->rawContent()[0]);
- EXPECT_EQ(0xC3, atom1->rawContent()[1]);
- EXPECT_EQ(lld::Atom::scopeGlobal, atom1->scope());
-
- EXPECT_TRUE(atom2->name().equals("_bar"));
- EXPECT_EQ(1U, atom2->rawContent().size());
- EXPECT_EQ(0xC3, atom2->rawContent()[0]);
- EXPECT_EQ(lld::Atom::scopeGlobal, atom2->scope());
-
- EXPECT_TRUE(atom3->name().equals("_baz"));
- EXPECT_EQ(1U, atom3->rawContent().size());
- EXPECT_EQ(0xC4, atom3->rawContent()[0]);
- EXPECT_EQ(lld::Atom::scopeLinkageUnit, atom3->scope());
-
- EXPECT_TRUE(atom4->name().equals("_undef"));
- EXPECT_EQ(lld::Atom::definitionUndefined, atom4->definition());
-}
-
-TEST(ToAtomsTest, reservedUnitLength) {
- static const uint8_t debugInfoWithReservedLengthContent[12] = {
- 0xf0, 0xff, 0xff, 0xff // Reserved length value
- };
- static const uint8_t debugInfoWithValidBigLengthContent[12] = {
- 0xef, 0xff, 0xff, 0xff, // The maximum valid length value for DWARF32
- 0x00, 0x00 // Wrong version
- };
- static const uint8_t dummyContent[] = {0x00};
-
- NormalizedFile fReservedLength, fValidBigLength;
- fReservedLength.arch = lld::MachOLinkingContext::arch_x86;
- fValidBigLength.arch = lld::MachOLinkingContext::arch_x86;
- Section section;
- section.segmentName = "__DWARF";
- section.sectionName = "__debug_info";
- section.content = llvm::makeArrayRef(debugInfoWithReservedLengthContent);
- fReservedLength.sections.push_back(section);
- section.content = llvm::makeArrayRef(debugInfoWithValidBigLengthContent);
- fValidBigLength.sections.push_back(section);
- section.sectionName = "__debug_abbrev";
- section.content = llvm::makeArrayRef(dummyContent);
- fReservedLength.sections.push_back(section);
- fValidBigLength.sections.push_back(section);
- section.sectionName = "__debug_str";
- fReservedLength.sections.push_back(section);
- fValidBigLength.sections.push_back(section);
-
- auto resultReservedLength = normalizedToAtoms(fReservedLength, "foo", false);
- auto resultValidBigLength = normalizedToAtoms(fValidBigLength, "foo", false);
-
- // Both cases should return errors, but different.
- ASSERT_FALSE(resultReservedLength);
- ASSERT_FALSE(resultValidBigLength);
-
- EXPECT_STREQ("Malformed DWARF in foo",
- toString(resultReservedLength.takeError()).c_str());
- EXPECT_STREQ("Unsupported DWARF version in foo",
- toString(resultValidBigLength.takeError()).c_str());
-}
+++ /dev/null
-//===- lld/unittest/MachOTests/MachONormalizedFileYAMLTests.cpp -----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../../lib/ReaderWriter/MachO/MachONormalizedFile.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/MachO.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <system_error>
-
-using llvm::StringRef;
-using llvm::MemoryBuffer;
-using lld::mach_o::normalized::NormalizedFile;
-using lld::mach_o::normalized::Symbol;
-using lld::mach_o::normalized::Section;
-using lld::mach_o::normalized::Relocation;
-
-static std::unique_ptr<NormalizedFile> fromYAML(StringRef str) {
- std::unique_ptr<MemoryBuffer> mb(MemoryBuffer::getMemBuffer(str));
- llvm::Expected<std::unique_ptr<NormalizedFile>> r
- = lld::mach_o::normalized::readYaml(mb);
- EXPECT_FALSE(!r);
- return std::move(*r);
-}
-
-static void toYAML(const NormalizedFile &f, std::string &out) {
- llvm::raw_string_ostream ostr(out);
- std::error_code ec = lld::mach_o::normalized::writeYaml(f, ostr);
- EXPECT_TRUE(!ec);
-}
-
-// ppc is no longer supported, but it is here to test endianness handling.
-TEST(ObjectFileYAML, empty_ppc) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: ppc\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)(int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->sections.empty());
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_x86_64) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: x86_64\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)(int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->sections.empty());
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_x86) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: x86\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->sections.empty());
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_armv6) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: armv6\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv6);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->sections.empty());
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_armv7) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: armv7\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->sections.empty());
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, empty_armv7s) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: armv7s\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7s);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f->sections.empty());
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
-}
-
-TEST(ObjectFileYAML, roundTrip) {
- std::string intermediate;
- {
- NormalizedFile f;
- f.arch = lld::MachOLinkingContext::arch_x86_64;
- f.fileType = llvm::MachO::MH_OBJECT;
- f.flags = (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
- f.os = lld::MachOLinkingContext::OS::macOSX;
- toYAML(f, intermediate);
- }
- {
- std::unique_ptr<NormalizedFile> f2 = fromYAML(intermediate);
- EXPECT_EQ(f2->arch, lld::MachOLinkingContext::arch_x86_64);
- EXPECT_EQ((int)(f2->fileType), llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f2->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_TRUE(f2->sections.empty());
- EXPECT_TRUE(f2->localSymbols.empty());
- EXPECT_TRUE(f2->globalSymbols.empty());
- EXPECT_TRUE(f2->undefinedSymbols.empty());
- }
-}
-
-TEST(ObjectFileYAML, oneSymbol) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: x86_64\n"
- "file-type: MH_OBJECT\n"
- "global-symbols:\n"
- " - name: _main\n"
- " type: N_SECT\n"
- " scope: [ N_EXT ]\n"
- " sect: 1\n"
- " desc: [ ]\n"
- " value: 0x100\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_TRUE(f->sections.empty());
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
- EXPECT_EQ(f->globalSymbols.size(), 1UL);
- const Symbol& sym = f->globalSymbols[0];
- EXPECT_TRUE(sym.name.equals("_main"));
- EXPECT_EQ((int)(sym.type), llvm::MachO::N_SECT);
- EXPECT_EQ((int)(sym.scope), llvm::MachO::N_EXT);
- EXPECT_EQ(sym.sect, 1);
- EXPECT_EQ((int)(sym.desc), 0);
- EXPECT_EQ((uint64_t)sym.value, 0x100ULL);
-}
-
-TEST(ObjectFileYAML, oneSection) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: x86_64\n"
- "file-type: MH_OBJECT\n"
- "sections:\n"
- " - segment: __TEXT\n"
- " section: __text\n"
- " type: S_REGULAR\n"
- " attributes: [ S_ATTR_PURE_INSTRUCTIONS ]\n"
- " alignment: 2\n"
- " address: 0x12345678\n"
- " content: [ 0x90, 0x90 ]\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_TRUE(f->localSymbols.empty());
- EXPECT_TRUE(f->globalSymbols.empty());
- EXPECT_TRUE(f->undefinedSymbols.empty());
- EXPECT_EQ(f->sections.size(), 1UL);
- const Section& sect = f->sections[0];
- EXPECT_TRUE(sect.segmentName.equals("__TEXT"));
- EXPECT_TRUE(sect.sectionName.equals("__text"));
- EXPECT_EQ((uint32_t)(sect.type), (uint32_t)(llvm::MachO::S_REGULAR));
- EXPECT_EQ((uint32_t)(sect.attributes),
- (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)sect.alignment, 2U);
- EXPECT_EQ((uint64_t)sect.address, 0x12345678ULL);
- EXPECT_EQ(sect.content.size(), 2UL);
- EXPECT_EQ((int)(sect.content[0]), 0x90);
- EXPECT_EQ((int)(sect.content[1]), 0x90);
-}
-
-TEST(ObjectFileYAML, hello_x86_64) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: x86_64\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "sections:\n"
- " - segment: __TEXT\n"
- " section: __text\n"
- " type: S_REGULAR\n"
- " attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
- " alignment: 1\n"
- " address: 0x0000\n"
- " content: [ 0x55, 0x48, 0x89, 0xe5, 0x48, 0x8d, 0x3d, 0x00,\n"
- " 0x00, 0x00, 0x00, 0x30, 0xc0, 0xe8, 0x00, 0x00,\n"
- " 0x00, 0x00, 0x31, 0xc0, 0x5d, 0xc3 ]\n"
- " relocations:\n"
- " - offset: 0x0e\n"
- " type: X86_64_RELOC_BRANCH\n"
- " length: 2\n"
- " pc-rel: true\n"
- " extern: true\n"
- " symbol: 2\n"
- " - offset: 0x07\n"
- " type: X86_64_RELOC_SIGNED\n"
- " length: 2\n"
- " pc-rel: true\n"
- " extern: true\n"
- " symbol: 1\n"
- " - segment: __TEXT\n"
- " section: __cstring\n"
- " type: S_CSTRING_LITERALS\n"
- " attributes: [ ]\n"
- " alignment: 1\n"
- " address: 0x0016\n"
- " content: [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
- "global-symbols:\n"
- " - name: _main\n"
- " type: N_SECT\n"
- " scope: [ N_EXT ]\n"
- " sect: 1\n"
- " value: 0x0\n"
- "local-symbols:\n"
- " - name: L_.str\n"
- " type: N_SECT\n"
- " scope: [ ]\n"
- " sect: 2\n"
- " value: 0x16\n"
- "undefined-symbols:\n"
- " - name: _printf\n"
- " type: N_UNDF\n"
- " value: 0x0\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_EQ(f->sections.size(), 2UL);
-
- const Section& sect1 = f->sections[0];
- EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
- EXPECT_TRUE(sect1.sectionName.equals("__text"));
- EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
- EXPECT_EQ((uint32_t)(sect1.attributes),
- (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
- | llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)sect1.alignment, 1U);
- EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
- EXPECT_EQ(sect1.content.size(), 22UL);
- EXPECT_EQ((int)(sect1.content[0]), 0x55);
- EXPECT_EQ((int)(sect1.content[1]), 0x48);
- EXPECT_EQ(sect1.relocations.size(), 2UL);
- const Relocation& reloc1 = sect1.relocations[0];
- EXPECT_EQ(reloc1.offset, 0x0eU);
- EXPECT_FALSE(reloc1.scattered);
- EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::X86_64_RELOC_BRANCH);
- EXPECT_EQ(reloc1.length, 2);
- EXPECT_TRUE(reloc1.pcRel);
- EXPECT_TRUE(reloc1.isExtern);
- EXPECT_EQ(reloc1.symbol, 2U);
- EXPECT_EQ((int)(reloc1.value), 0);
- const Relocation& reloc2 = sect1.relocations[1];
- EXPECT_EQ(reloc2.offset, 0x07U);
- EXPECT_FALSE(reloc2.scattered);
- EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::X86_64_RELOC_SIGNED);
- EXPECT_EQ(reloc2.length, 2);
- EXPECT_TRUE(reloc2.pcRel);
- EXPECT_TRUE(reloc2.isExtern);
- EXPECT_EQ(reloc2.symbol, 1U);
- EXPECT_EQ((int)(reloc2.value), 0);
-
- const Section& sect2 = f->sections[1];
- EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
- EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
- EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
- EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
- EXPECT_EQ((uint16_t)sect2.alignment, 1U);
- EXPECT_EQ((uint64_t)sect2.address, 0x016ULL);
- EXPECT_EQ(sect2.content.size(), 7UL);
- EXPECT_EQ((int)(sect2.content[0]), 0x68);
- EXPECT_EQ((int)(sect2.content[1]), 0x65);
- EXPECT_EQ((int)(sect2.content[2]), 0x6c);
-
- EXPECT_EQ(f->globalSymbols.size(), 1UL);
- const Symbol& sym1 = f->globalSymbols[0];
- EXPECT_TRUE(sym1.name.equals("_main"));
- EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
- EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
- EXPECT_EQ(sym1.sect, 1);
- EXPECT_EQ((int)(sym1.desc), 0);
- EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
- EXPECT_EQ(f->localSymbols.size(), 1UL);
- const Symbol& sym2 = f->localSymbols[0];
- EXPECT_TRUE(sym2.name.equals("L_.str"));
- EXPECT_EQ((int)(sym2.type), llvm::MachO::N_SECT);
- EXPECT_EQ((int)(sym2.scope), 0);
- EXPECT_EQ(sym2.sect, 2);
- EXPECT_EQ((int)(sym2.desc), 0);
- EXPECT_EQ((uint64_t)sym2.value, 0x16ULL);
- EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
- const Symbol& sym3 = f->undefinedSymbols[0];
- EXPECT_TRUE(sym3.name.equals("_printf"));
- EXPECT_EQ((int)(sym3.type), llvm::MachO::N_UNDF);
- EXPECT_EQ((int)(sym3.scope), 0);
- EXPECT_EQ(sym3.sect, 0);
- EXPECT_EQ((int)(sym3.desc), 0);
- EXPECT_EQ((uint64_t)sym3.value, 0x0ULL);
-}
-
-TEST(ObjectFileYAML, hello_x86) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: x86\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "sections:\n"
- " - segment: __TEXT\n"
- " section: __text\n"
- " type: S_REGULAR\n"
- " attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
- " alignment: 1\n"
- " address: 0x0000\n"
- " content: [ 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0xe8, 0x00,\n"
- " 0x00, 0x00, 0x00, 0x58, 0x8d, 0x80, 0x16, 0x00,\n"
- " 0x00, 0x00, 0x89, 0x04, 0x24, 0xe8, 0xe6, 0xff,\n"
- " 0xff, 0xff, 0x31, 0xc0, 0x83, 0xc4, 0x08, 0x5d,\n"
- " 0xc3 ]\n"
- " relocations:\n"
- " - offset: 0x16\n"
- " type: GENERIC_RELOC_VANILLA\n"
- " length: 2\n"
- " pc-rel: true\n"
- " extern: true\n"
- " symbol: 1\n"
- " - offset: 0x0e\n"
- " scattered: true\n"
- " type: GENERIC_RELOC_LOCAL_SECTDIFF\n"
- " length: 2\n"
- " pc-rel: false\n"
- " value: 0x21\n"
- " - offset: 0x0\n"
- " scattered: true\n"
- " type: GENERIC_RELOC_PAIR\n"
- " length: 2\n"
- " pc-rel: false\n"
- " value: 0xb\n"
- " - segment: __TEXT\n"
- " section: __cstring\n"
- " type: S_CSTRING_LITERALS\n"
- " attributes: [ ]\n"
- " alignment: 1\n"
- " address: 0x0021\n"
- " content: [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
- "global-symbols:\n"
- " - name: _main\n"
- " type: N_SECT\n"
- " scope: [ N_EXT ]\n"
- " sect: 1\n"
- " value: 0x0\n"
- "undefined-symbols:\n"
- " - name: _printf\n"
- " type: N_UNDF\n"
- " value: 0x0\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_EQ(f->sections.size(), 2UL);
-
- const Section& sect1 = f->sections[0];
- EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
- EXPECT_TRUE(sect1.sectionName.equals("__text"));
- EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
- EXPECT_EQ((uint32_t)(sect1.attributes),
- (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
- | llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)sect1.alignment, 1U);
- EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
- EXPECT_EQ(sect1.content.size(), 33UL);
- EXPECT_EQ((int)(sect1.content[0]), 0x55);
- EXPECT_EQ((int)(sect1.content[1]), 0x89);
- EXPECT_EQ(sect1.relocations.size(), 3UL);
- const Relocation& reloc1 = sect1.relocations[0];
- EXPECT_EQ(reloc1.offset, 0x16U);
- EXPECT_FALSE(reloc1.scattered);
- EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::GENERIC_RELOC_VANILLA);
- EXPECT_EQ(reloc1.length, 2);
- EXPECT_TRUE(reloc1.pcRel);
- EXPECT_TRUE(reloc1.isExtern);
- EXPECT_EQ(reloc1.symbol, 1U);
- EXPECT_EQ((int)(reloc1.value), 0);
- const Relocation& reloc2 = sect1.relocations[1];
- EXPECT_EQ(reloc2.offset, 0x0eU);
- EXPECT_TRUE(reloc2.scattered);
- EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::GENERIC_RELOC_LOCAL_SECTDIFF);
- EXPECT_EQ(reloc2.length, 2);
- EXPECT_FALSE(reloc2.pcRel);
- EXPECT_EQ(reloc2.symbol, 0U);
- EXPECT_EQ((int)(reloc2.value), 0x21);
- const Relocation& reloc3 = sect1.relocations[2];
- EXPECT_EQ(reloc3.offset, 0U);
- EXPECT_TRUE(reloc3.scattered);
- EXPECT_EQ((int)reloc3.type, (int)llvm::MachO::GENERIC_RELOC_PAIR);
- EXPECT_EQ(reloc3.length, 2);
- EXPECT_FALSE(reloc3.pcRel);
- EXPECT_EQ(reloc3.symbol, 0U);
- EXPECT_EQ((int)(reloc3.value), 0xb);
-
- const Section& sect2 = f->sections[1];
- EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
- EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
- EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
- EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
- EXPECT_EQ((uint16_t)sect2.alignment, 1U);
- EXPECT_EQ((uint64_t)sect2.address, 0x021ULL);
- EXPECT_EQ(sect2.content.size(), 7UL);
- EXPECT_EQ((int)(sect2.content[0]), 0x68);
- EXPECT_EQ((int)(sect2.content[1]), 0x65);
- EXPECT_EQ((int)(sect2.content[2]), 0x6c);
-
- EXPECT_EQ(f->globalSymbols.size(), 1UL);
- const Symbol& sym1 = f->globalSymbols[0];
- EXPECT_TRUE(sym1.name.equals("_main"));
- EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
- EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
- EXPECT_EQ(sym1.sect, 1);
- EXPECT_EQ((int)(sym1.desc), 0);
- EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
- EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
- const Symbol& sym2 = f->undefinedSymbols[0];
- EXPECT_TRUE(sym2.name.equals("_printf"));
- EXPECT_EQ((int)(sym2.type), llvm::MachO::N_UNDF);
- EXPECT_EQ((int)(sym2.scope), 0);
- EXPECT_EQ(sym2.sect, 0);
- EXPECT_EQ((int)(sym2.desc), 0);
- EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
-}
-
-TEST(ObjectFileYAML, hello_armv6) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: armv6\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "sections:\n"
- " - segment: __TEXT\n"
- " section: __text\n"
- " type: S_REGULAR\n"
- " attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
- " alignment: 4\n"
- " address: 0x0000\n"
- " content: [ 0x80, 0x40, 0x2d, 0xe9, 0x10, 0x00, 0x9f, 0xe5,\n"
- " 0x0d, 0x70, 0xa0, 0xe1, 0x00, 0x00, 0x8f, 0xe0,\n"
- " 0xfa, 0xff, 0xff, 0xeb, 0x00, 0x00, 0xa0, 0xe3,\n"
- " 0x80, 0x80, 0xbd, 0xe8, 0x0c, 0x00, 0x00, 0x00 ]\n"
- " relocations:\n"
- " - offset: 0x1c\n"
- " scattered: true\n"
- " type: ARM_RELOC_SECTDIFF\n"
- " length: 2\n"
- " pc-rel: false\n"
- " value: 0x20\n"
- " - offset: 0x0\n"
- " scattered: true\n"
- " type: ARM_RELOC_PAIR\n"
- " length: 2\n"
- " pc-rel: false\n"
- " value: 0xc\n"
- " - offset: 0x10\n"
- " type: ARM_RELOC_BR24\n"
- " length: 2\n"
- " pc-rel: true\n"
- " extern: true\n"
- " symbol: 1\n"
- " - segment: __TEXT\n"
- " section: __cstring\n"
- " type: S_CSTRING_LITERALS\n"
- " attributes: [ ]\n"
- " alignment: 1\n"
- " address: 0x0020\n"
- " content: [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
- "global-symbols:\n"
- " - name: _main\n"
- " type: N_SECT\n"
- " scope: [ N_EXT ]\n"
- " sect: 1\n"
- " value: 0x0\n"
- "undefined-symbols:\n"
- " - name: _printf\n"
- " type: N_UNDF\n"
- " value: 0x0\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv6);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_EQ(f->sections.size(), 2UL);
-
- const Section& sect1 = f->sections[0];
- EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
- EXPECT_TRUE(sect1.sectionName.equals("__text"));
- EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
- EXPECT_EQ((uint32_t)(sect1.attributes),
- (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
- | llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)sect1.alignment, 4U);
- EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
- EXPECT_EQ(sect1.content.size(), 32UL);
- EXPECT_EQ((int)(sect1.content[0]), 0x80);
- EXPECT_EQ((int)(sect1.content[1]), 0x40);
- EXPECT_EQ(sect1.relocations.size(), 3UL);
- const Relocation& reloc1 = sect1.relocations[0];
- EXPECT_EQ(reloc1.offset, 0x1cU);
- EXPECT_TRUE(reloc1.scattered);
- EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::ARM_RELOC_SECTDIFF);
- EXPECT_EQ(reloc1.length, 2);
- EXPECT_FALSE(reloc1.pcRel);
- EXPECT_EQ(reloc1.symbol, 0U);
- EXPECT_EQ((int)(reloc1.value), 0x20);
- const Relocation& reloc2 = sect1.relocations[1];
- EXPECT_EQ(reloc2.offset, 0x0U);
- EXPECT_TRUE(reloc2.scattered);
- EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::ARM_RELOC_PAIR);
- EXPECT_EQ(reloc2.length, 2);
- EXPECT_FALSE(reloc2.pcRel);
- EXPECT_EQ(reloc2.symbol, 0U);
- EXPECT_EQ((int)(reloc2.value), 0xc);
- const Relocation& reloc3 = sect1.relocations[2];
- EXPECT_EQ(reloc3.offset, 0x10U);
- EXPECT_FALSE(reloc3.scattered);
- EXPECT_EQ((int)reloc3.type, (int)llvm::MachO::ARM_RELOC_BR24);
- EXPECT_EQ(reloc3.length, 2);
- EXPECT_TRUE(reloc3.pcRel);
- EXPECT_TRUE(reloc3.isExtern);
- EXPECT_EQ(reloc3.symbol, 1U);
- EXPECT_EQ((int)(reloc3.value), 0);
-
- const Section& sect2 = f->sections[1];
- EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
- EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
- EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
- EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
- EXPECT_EQ((uint16_t)sect2.alignment, 1U);
- EXPECT_EQ((uint64_t)sect2.address, 0x020ULL);
- EXPECT_EQ(sect2.content.size(), 7UL);
- EXPECT_EQ((int)(sect2.content[0]), 0x68);
- EXPECT_EQ((int)(sect2.content[1]), 0x65);
- EXPECT_EQ((int)(sect2.content[2]), 0x6c);
-
- EXPECT_EQ(f->globalSymbols.size(), 1UL);
- const Symbol& sym1 = f->globalSymbols[0];
- EXPECT_TRUE(sym1.name.equals("_main"));
- EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
- EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
- EXPECT_EQ(sym1.sect, 1);
- EXPECT_EQ((int)(sym1.desc), 0);
- EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
- EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
- const Symbol& sym2 = f->undefinedSymbols[0];
- EXPECT_TRUE(sym2.name.equals("_printf"));
- EXPECT_EQ((int)(sym2.type), llvm::MachO::N_UNDF);
- EXPECT_EQ((int)(sym2.scope), 0);
- EXPECT_EQ(sym2.sect, 0);
- EXPECT_EQ((int)(sym2.desc), 0);
- EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
-}
-
-TEST(ObjectFileYAML, hello_armv7) {
- std::unique_ptr<NormalizedFile> f = fromYAML(
- "---\n"
- "arch: armv7\n"
- "file-type: MH_OBJECT\n"
- "flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]\n"
- "sections:\n"
- " - segment: __TEXT\n"
- " section: __text\n"
- " type: S_REGULAR\n"
- " attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
- " alignment: 2\n"
- " address: 0x0000\n"
- " content: [ 0x80, 0xb5, 0x40, 0xf2, 0x06, 0x00, 0x6f, 0x46,\n"
- " 0xc0, 0xf2, 0x00, 0x00, 0x78, 0x44, 0xff, 0xf7,\n"
- " 0xf8, 0xef, 0x00, 0x20, 0x80, 0xbd ]\n"
- " relocations:\n"
- " - offset: 0x0e\n"
- " type: ARM_THUMB_RELOC_BR22\n"
- " length: 2\n"
- " pc-rel: true\n"
- " extern: true\n"
- " symbol: 1\n"
- " - offset: 0x08\n"
- " scattered: true\n"
- " type: ARM_RELOC_HALF_SECTDIFF\n"
- " length: 3\n"
- " pc-rel: false\n"
- " value: 0x16\n"
- " - offset: 0x06\n"
- " scattered: true\n"
- " type: ARM_RELOC_PAIR\n"
- " length: 3\n"
- " pc-rel: false\n"
- " value: 0xc\n"
- " - offset: 0x02\n"
- " scattered: true\n"
- " type: ARM_RELOC_HALF_SECTDIFF\n"
- " length: 2\n"
- " pc-rel: false\n"
- " value: 0x16\n"
- " - offset: 0x0\n"
- " scattered: true\n"
- " type: ARM_RELOC_PAIR\n"
- " length: 2\n"
- " pc-rel: false\n"
- " value: 0xc\n"
- " - segment: __TEXT\n"
- " section: __cstring\n"
- " type: S_CSTRING_LITERALS\n"
- " attributes: [ ]\n"
- " alignment: 1\n"
- " address: 0x0016\n"
- " content: [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
- "global-symbols:\n"
- " - name: _main\n"
- " type: N_SECT\n"
- " scope: [ N_EXT ]\n"
- " sect: 1\n"
- " desc: [ N_ARM_THUMB_DEF ]\n"
- " value: 0x0\n"
- "undefined-symbols:\n"
- " - name: _printf\n"
- " type: N_UNDF\n"
- " value: 0x0\n"
- "...\n");
- EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7);
- EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT);
- EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS);
- EXPECT_EQ(f->sections.size(), 2UL);
-
- const Section& sect1 = f->sections[0];
- EXPECT_TRUE(sect1.segmentName.equals("__TEXT"));
- EXPECT_TRUE(sect1.sectionName.equals("__text"));
- EXPECT_EQ((uint32_t)(sect1.type), (uint32_t)(llvm::MachO::S_REGULAR));
- EXPECT_EQ((uint32_t)(sect1.attributes),
- (uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
- | llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ((uint16_t)sect1.alignment, 2U);
- EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
- EXPECT_EQ(sect1.content.size(), 22UL);
- EXPECT_EQ((int)(sect1.content[0]), 0x80);
- EXPECT_EQ((int)(sect1.content[1]), 0xb5);
- EXPECT_EQ(sect1.relocations.size(), 5UL);
- const Relocation& reloc1 = sect1.relocations[0];
- EXPECT_EQ(reloc1.offset, 0x0eU);
- EXPECT_FALSE(reloc1.scattered);
- EXPECT_EQ((int)reloc1.type, (int)llvm::MachO::ARM_THUMB_RELOC_BR22);
- EXPECT_EQ(reloc1.length, 2);
- EXPECT_TRUE(reloc1.pcRel);
- EXPECT_TRUE(reloc1.isExtern);
- EXPECT_EQ(reloc1.symbol, 1U);
- EXPECT_EQ((int)(reloc1.value), 0);
- const Relocation& reloc2 = sect1.relocations[1];
- EXPECT_EQ(reloc2.offset, 0x8U);
- EXPECT_TRUE(reloc2.scattered);
- EXPECT_EQ((int)reloc2.type, (int)llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
- EXPECT_EQ(reloc2.length, 3);
- EXPECT_FALSE(reloc2.pcRel);
- EXPECT_EQ(reloc2.symbol, 0U);
- EXPECT_EQ((int)(reloc2.value), 0x16);
- const Relocation& reloc3 = sect1.relocations[2];
- EXPECT_EQ(reloc3.offset, 0x6U);
- EXPECT_TRUE(reloc3.scattered);
- EXPECT_EQ((int)reloc3.type, (int)llvm::MachO::ARM_RELOC_PAIR);
- EXPECT_EQ(reloc3.length, 3);
- EXPECT_FALSE(reloc3.pcRel);
- EXPECT_EQ(reloc3.symbol, 0U);
- EXPECT_EQ((int)(reloc3.value), 0xc);
- const Relocation& reloc4 = sect1.relocations[3];
- EXPECT_EQ(reloc4.offset, 0x2U);
- EXPECT_TRUE(reloc4.scattered);
- EXPECT_EQ((int)reloc4.type, (int)llvm::MachO::ARM_RELOC_HALF_SECTDIFF);
- EXPECT_EQ(reloc4.length, 2);
- EXPECT_FALSE(reloc4.pcRel);
- EXPECT_EQ(reloc4.symbol, 0U);
- EXPECT_EQ((int)(reloc4.value), 0x16);
- const Relocation& reloc5 = sect1.relocations[4];
- EXPECT_EQ(reloc5.offset, 0x0U);
- EXPECT_TRUE(reloc5.scattered);
- EXPECT_EQ((int)reloc5.type, (int)llvm::MachO::ARM_RELOC_PAIR);
- EXPECT_EQ(reloc5.length, 2);
- EXPECT_FALSE(reloc5.pcRel);
- EXPECT_EQ(reloc5.symbol, 0U);
- EXPECT_EQ((int)(reloc5.value), 0xc);
-
- const Section& sect2 = f->sections[1];
- EXPECT_TRUE(sect2.segmentName.equals("__TEXT"));
- EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
- EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
- EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
- EXPECT_EQ((uint16_t)sect2.alignment, 1U);
- EXPECT_EQ((uint64_t)sect2.address, 0x016ULL);
- EXPECT_EQ(sect2.content.size(), 7UL);
- EXPECT_EQ((int)(sect2.content[0]), 0x68);
- EXPECT_EQ((int)(sect2.content[1]), 0x65);
- EXPECT_EQ((int)(sect2.content[2]), 0x6c);
-
- EXPECT_EQ(f->globalSymbols.size(), 1UL);
- const Symbol& sym1 = f->globalSymbols[0];
- EXPECT_TRUE(sym1.name.equals("_main"));
- EXPECT_EQ((int)(sym1.type), llvm::MachO::N_SECT);
- EXPECT_EQ((int)(sym1.scope), llvm::MachO::N_EXT);
- EXPECT_EQ(sym1.sect, 1);
- EXPECT_EQ((int)(sym1.desc), (int)(llvm::MachO::N_ARM_THUMB_DEF));
- EXPECT_EQ((uint64_t)sym1.value, 0x0ULL);
- EXPECT_EQ(f->undefinedSymbols.size(), 1UL);
- const Symbol& sym2 = f->undefinedSymbols[0];
- EXPECT_TRUE(sym2.name.equals("_printf"));
- EXPECT_EQ((int)(sym2.type), llvm::MachO::N_UNDF);
- EXPECT_EQ((int)(sym2.scope), 0);
- EXPECT_EQ(sym2.sect, 0);
- EXPECT_EQ((int)(sym2.desc), 0);
- EXPECT_EQ((uint64_t)sym2.value, 0x0ULL);
-}
+++ /dev/null
-0xca, 0xfe, 0xba, 0xbe, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x07, 0x00,
-0x00, 0x00, 0x03, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00,
-0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40,
-0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xcf, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00,
-0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x98, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
-0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x5f, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xce, 0xfa, 0xed, 0xfe, 0x0c, 0x00, 0x00, 0x00, 0x09,
-0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00,
-0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00,
-0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74,
-0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
"lld-link",
"ld.lld",
"ld64.lld",
- "ld64.lld.darwinnew",
- "ld64.lld.darwinold",
"wasm-ld",
]
foreach(target, symlinks) {