From: Tim Northover Date: Mon, 30 Jun 2014 09:11:38 +0000 (+0000) Subject: MachO: support atomization of dylibs. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f9b13d67662e842aa087ffb79a8d917e048e5388;p=platform%2Fupstream%2Fllvm.git MachO: support atomization of dylibs. For .dylib files, we refrain from actually creating any atoms until they're requested via the "exports" method. llvm-svn: 212027 --- diff --git a/lld/lib/ReaderWriter/MachO/Atoms.h b/lld/lib/ReaderWriter/MachO/Atoms.h index 9db091e..80cad29 100644 --- a/lld/lib/ReaderWriter/MachO/Atoms.h +++ b/lld/lib/ReaderWriter/MachO/Atoms.h @@ -117,6 +117,48 @@ private: 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 diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h index 0101350..d50e3ff 100644 --- a/lld/lib/ReaderWriter/MachO/File.h +++ b/lld/lib/ReaderWriter/MachO/File.h @@ -15,6 +15,9 @@ #include "Atoms.h" #include "lld/Core/Simple.h" +#include "lld/Core/SharedLibraryFile.h" + +#include namespace lld { namespace mach_o { @@ -156,7 +159,60 @@ private: NameToAtom _undefAtoms; }; +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 diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp index a328ec4..09ff83b 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp @@ -392,7 +392,8 @@ public: 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; diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index 61d68fa..56c5f44 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -195,6 +195,7 @@ 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: @@ -602,6 +603,19 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path, 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 { @@ -634,6 +648,8 @@ ErrorOr> 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: diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp index 69a1441..65f18d2 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp @@ -651,6 +651,8 @@ bool MachOYamlIOTaggedDocumentHandler::handledDocTag(llvm::yaml::IO &io, // 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()); diff --git a/lld/test/mach-o/use-simple-dylib.yaml b/lld/test/mach-o/use-simple-dylib.yaml new file mode 100644 index 0000000..024e983 --- /dev/null +++ b/lld/test/mach-o/use-simple-dylib.yaml @@ -0,0 +1,129 @@ +# RUN: lld -flavor darwin -arch x86_64 -print_atoms -r %s | FileCheck %s +# lld -flavor darwin -arch x86_64 -print_atoms -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