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
This commit is contained in:
Tim Northover 2014-06-30 09:11:38 +00:00
parent e686c1d7ef
commit f9b13d6766
6 changed files with 247 additions and 1 deletions

View File

@ -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

View File

@ -15,6 +15,9 @@
#include "Atoms.h"
#include "lld/Core/Simple.h"
#include "lld/Core/SharedLibraryFile.h"
#include <unordered_map>
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<DefinedAtom> &defined() const override {
return _definedAtoms;
}
const atom_collection<UndefinedAtom> &undefined() const override {
return _undefinedAtoms;
}
const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
return _sharedLibraryAtoms;
}
const atom_collection<AbsoluteAtom> &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<DefinedAtom> _definedAtoms;
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
mutable std::unordered_map<StringRef, SharedLibraryAtom *> _nameToAtom;
mutable llvm::BumpPtrAllocator _allocator;
};
} // end namespace mach_o
} // end namespace lld

View File

@ -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;

View File

@ -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<File>(std::move(file));
}
ErrorOr<std::unique_ptr<lld::File>>
normalizedDylibToAtoms(const NormalizedFile &normalizedFile, StringRef path,
bool copyRefs) {
std::unique_ptr<MachODylibFile> 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<File>(std::move(file));
}
} // anonymous namespace
namespace normalized {
@ -634,6 +648,8 @@ ErrorOr<std::unique_ptr<lld::File>>
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:

View File

@ -651,6 +651,8 @@ bool MachOYamlIOTaggedDocumentHandler::handledDocTag(llvm::yaml::IO &io,
// Step 2: parse normalized mach-o struct into atoms.
ErrorOr<std::unique_ptr<lld::File>> foe = normalizedToAtoms(nf, info->_path,
true);
info->_normalizeMachOFile = nullptr;
if (foe) {
// Transfer ownership to "out" File parameter.
std::unique_ptr<lld::File> f = std::move(foe.get());

View File

@ -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