Index: lib/ReaderWriter/MachO/Atoms.h =================================================================== --- lib/ReaderWriter/MachO/Atoms.h +++ lib/ReaderWriter/MachO/Atoms.h @@ -111,6 +111,48 @@ const DefinedAtom::Alignment _align; }; +class MachOSharedLibraryAtom : public SharedLibraryAtom { +public: + MachOSharedLibraryAtom(const File &file, StringRef name, + StringRef dylibInstallName) + : SharedLibraryAtom(), _file(file), _name(name), + _dylibInstallName(dylibInstallName) {} + virtual ~MachOSharedLibraryAtom() {} + + virtual StringRef loadName() const override { + return _dylibInstallName; + } + + virtual bool canBeNullAtRuntime() const override { + // FIXME: this may actually be changeable. For now, all symbols are strongly + // defined though. + return false; + } + + virtual const File& file() const override { + return _file; + } + + virtual StringRef name() const override { + return _name; + } + + virtual Type type() const override { + // Unused in MachO (I think). + return Type::Unknown; + } + + virtual uint64_t size() const override { + // Unused in MachO (I think) + return 0; + } + +private: + const File &_file; + StringRef _name; + StringRef _dylibInstallName; +}; + } // mach_o } // lld Index: lib/ReaderWriter/MachO/File.h =================================================================== --- lib/ReaderWriter/MachO/File.h +++ lib/ReaderWriter/MachO/File.h @@ -13,6 +13,9 @@ #include "Atoms.h" #include "lld/Core/Simple.h" +#include "lld/Core/SharedLibraryFile.h" + +#include namespace lld { namespace mach_o { @@ -88,6 +91,61 @@ llvm::BumpPtrAllocator _allocator; }; +class MachODylibFile : public SharedLibraryFile { +public: + MachODylibFile(StringRef path) : SharedLibraryFile(path), _dylib_name(path) {} + + virtual const SharedLibraryAtom *exports(StringRef name, + bool dataSymbolOnly) const { + // FIXME: we obviously need to record code/data if we're going to make + // proper use of dataSymbolOnly. + auto sym = _nameToAtom.find(name); + + if (sym == _nameToAtom.end()) + return nullptr; + + if (!sym->second) + sym->second = + new (_allocator) MachOSharedLibraryAtom(*this, name, _dylib_name); + + return sym->second; + } + + const atom_collection &defined() const override { + return _definedAtoms; + } + + const atom_collection &undefined() const override { + return _undefinedAtoms; + } + + const atom_collection &sharedLibrary() const override { + return _sharedLibraryAtoms; + } + + const atom_collection &absolute() const override { + return _absoluteAtoms; + } + + void addSharedLibraryAtom(StringRef name, bool copyRefs) { + if (copyRefs) { + name = name.copy(_allocator); + } + + _nameToAtom[name] = nullptr; + } + +private: + StringRef _dylib_name; + atom_collection_vector _definedAtoms; + atom_collection_vector _undefinedAtoms; + atom_collection_vector _sharedLibraryAtoms; + atom_collection_vector _absoluteAtoms; + + mutable std::unordered_map _nameToAtom; + mutable llvm::BumpPtrAllocator _allocator; +}; + } // end namespace mach_o } // end namespace lld Index: lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp =================================================================== --- lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp +++ lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp @@ -392,7 +392,8 @@ bool canParse(file_magic magic, StringRef ext, const MemoryBuffer &mb) const override { - if (magic != llvm::sys::fs::file_magic::macho_object) + if (magic != llvm::sys::fs::file_magic::macho_object && + magic != llvm::sys::fs::file_magic::macho_dynamically_linked_shared_lib) return false; if (mb.getBufferSize() < 32) return false; Index: lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp =================================================================== --- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -190,6 +190,7 @@ switch (scope) { case N_EXT: return Atom::scopeGlobal; + case N_PEXT: case N_PEXT | N_EXT: return Atom::scopeLinkageUnit; case 0: @@ -430,6 +431,19 @@ return std::unique_ptr(std::move(file)); } +ErrorOr> +normalizedDylibToAtoms(const NormalizedFile &normalizedFile, StringRef path, + bool copyRefs) { + std::unique_ptr file(new MachODylibFile(path)); + + for (auto &sym : normalizedFile.globalSymbols) { + assert((sym.scope & N_EXT) && "only expect external symbols here"); + file->addSharedLibraryAtom(sym.name, copyRefs); + } + + return std::unique_ptr(std::move(file)); +} + } // anonymous namespace namespace normalized { @@ -462,6 +476,8 @@ normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path, bool copyRefs) { switch (normalizedFile.fileType) { + case MH_DYLIB: + return normalizedDylibToAtoms(normalizedFile, path, copyRefs); case MH_OBJECT: return normalizedObjectToAtoms(normalizedFile, path, copyRefs); default: Index: lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp =================================================================== --- lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp +++ lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp @@ -651,6 +651,8 @@ // Step 2: parse normalized mach-o struct into atoms. ErrorOr> foe = normalizedToAtoms(nf, info->_path, true); + + info->_normalizeMachOFile = nullptr; if (foe) { // Transfer ownership to "out" File parameter. std::unique_ptr f = std::move(foe.get()); Index: test/mach-o/use-simple-dylib.yaml =================================================================== --- /dev/null +++ test/mach-o/use-simple-dylib.yaml @@ -0,0 +1,129 @@ +# RUN: lld -flavor darwin -arch x86_64 -output_filetype atomic-yaml -r %s -o - | FileCheck %s +# lld -flavor darwin -arch x86_64 -output_filetype atomic-yaml -r %s %p/Inputs/simple-dylib.yaml -o - | 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 + +--- !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 +... + + +# CHECK: undefined-atoms: +# CHECK: - name: _myStatic +# CHECK: - name: _myVariablePreviouslyKnownAsPrivateExtern +# CHECK: shared-library-atoms: +# CHECK: - name: _myHidden +# CHECK: load-name: {{.*}}use-simple-dylib.yaml +# CHECK: - name: _myGlobal +# CHECK: load-name: {{.*}}use-simple-dylib.yaml +# CHECK: - name: _myHiddenWeak +# CHECK: load-name: {{.*}}use-simple-dylib.yaml +# CHECK: - name: _myGlobalWeak +# CHECK: load-name: {{.*}}use-simple-dylib.yaml +# CHECK: - name: _myResolver +# CHECK: load-name: {{.*}}use-simple-dylib.yaml