mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-27 23:51:56 +00:00
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:
parent
e686c1d7ef
commit
f9b13d6766
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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());
|
||||
|
129
lld/test/mach-o/use-simple-dylib.yaml
Normal file
129
lld/test/mach-o/use-simple-dylib.yaml
Normal 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
|
Loading…
Reference in New Issue
Block a user