mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-30 17:21:10 +00:00
ld64.lld: Add janky support for tbd files
With this, a simple hello world links against libSystem.tbd and the old ld64.lld linker kind of works again with newer SDKs. The motivation here is to have an arm64 cross linker that's good enough to be able to run simple configure link checks on non-mac systems for generating config.h files. Once -flavor darwinnew can link arm64, we'll switch to that.
This commit is contained in:
parent
7be1661fc6
commit
ba5087f130
@ -17,6 +17,8 @@
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/TextAPI/MachO/InterfaceFile.h"
|
||||
#include "llvm/TextAPI/MachO/TextAPIReader.h"
|
||||
#include <unordered_map>
|
||||
|
||||
namespace lld {
|
||||
@ -322,7 +324,8 @@ public:
|
||||
|
||||
void loadReExportedDylibs(FindDylib find) {
|
||||
for (ReExportedDylib &entry : _reExportedDylibs) {
|
||||
entry.file = find(entry.path);
|
||||
if (!entry.file)
|
||||
entry.file = find(entry.path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,7 +342,7 @@ public:
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
|
||||
StringRef installName) const {
|
||||
// First, check if requested symbol is directly implemented by this dylib.
|
||||
@ -373,6 +376,7 @@ private:
|
||||
|
||||
struct ReExportedDylib {
|
||||
ReExportedDylib(StringRef p) : path(p), file(nullptr) { }
|
||||
ReExportedDylib(StringRef p, MachODylibFile *file) : path(p), file(file) { }
|
||||
StringRef path;
|
||||
MachODylibFile *file;
|
||||
};
|
||||
@ -393,6 +397,70 @@ private:
|
||||
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
|
||||
|
||||
|
@ -540,6 +540,12 @@ MachOLinkingContext::searchDirForLibrary(StringRef path,
|
||||
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");
|
||||
|
@ -576,6 +576,26 @@ 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
|
||||
|
||||
@ -583,6 +603,7 @@ 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>(
|
||||
|
@ -1037,7 +1037,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
|
||||
|
||||
// Add all stabs.
|
||||
for (auto &stab : _stabs) {
|
||||
Symbol sym;
|
||||
lld::mach_o::normalized::Symbol sym;
|
||||
sym.type = static_cast<NListType>(stab.type);
|
||||
sym.scope = 0;
|
||||
sym.sect = stab.other;
|
||||
@ -1066,7 +1066,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
|
||||
AtomAndIndex ai = { atom, sect->finalSectionIndex, symbolScope };
|
||||
globals.push_back(ai);
|
||||
} else {
|
||||
Symbol sym;
|
||||
lld::mach_o::normalized::Symbol sym;
|
||||
sym.name = atom->name();
|
||||
sym.type = N_SECT;
|
||||
sym.scope = symbolScope;
|
||||
@ -1082,7 +1082,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
|
||||
char tmpName[16];
|
||||
sprintf(tmpName, "L%04u", tempNum++);
|
||||
StringRef tempRef(tmpName);
|
||||
Symbol sym;
|
||||
lld::mach_o::normalized::Symbol sym;
|
||||
sym.name = tempRef.copy(file.ownedAllocations);
|
||||
sym.type = N_SECT;
|
||||
sym.scope = 0;
|
||||
@ -1099,7 +1099,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
|
||||
std::sort(globals.begin(), globals.end(), AtomSorter());
|
||||
const uint32_t globalStartIndex = file.localSymbols.size();
|
||||
for (AtomAndIndex &ai : globals) {
|
||||
Symbol sym;
|
||||
lld::mach_o::normalized::Symbol sym;
|
||||
sym.name = ai.atom->name();
|
||||
sym.type = N_SECT;
|
||||
sym.scope = ai.scope;
|
||||
@ -1124,7 +1124,7 @@ llvm::Error Util::addSymbols(const lld::File &atomFile,
|
||||
std::sort(undefs.begin(), undefs.end(), AtomSorter());
|
||||
const uint32_t start = file.globalSymbols.size() + file.localSymbols.size();
|
||||
for (AtomAndIndex &ai : undefs) {
|
||||
Symbol sym;
|
||||
lld::mach_o::normalized::Symbol sym;
|
||||
uint16_t desc = 0;
|
||||
if (!rMode) {
|
||||
uint8_t ordinal = 0;
|
||||
|
@ -223,10 +223,11 @@ Atom::Scope atomScope(uint8_t scope) {
|
||||
llvm_unreachable("unknown scope value!");
|
||||
}
|
||||
|
||||
void appendSymbolsInSection(const std::vector<Symbol> &inSymbols,
|
||||
uint32_t sectionIndex,
|
||||
SmallVector<const Symbol *, 64> &outSyms) {
|
||||
for (const Symbol &sym : inSymbols) {
|
||||
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;
|
||||
@ -286,13 +287,14 @@ llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
|
||||
}
|
||||
|
||||
// Find all symbols in this section.
|
||||
SmallVector<const Symbol *, 64> symbols;
|
||||
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 Symbol *lhs, const Symbol *rhs) -> bool {
|
||||
[](const lld::mach_o::normalized::Symbol *lhs,
|
||||
const lld::mach_o::normalized::Symbol *rhs) -> bool {
|
||||
if (lhs == rhs)
|
||||
return false;
|
||||
// First by address.
|
||||
@ -300,7 +302,7 @@ llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
|
||||
uint64_t rhsAddr = rhs->value;
|
||||
if (lhsAddr != rhsAddr)
|
||||
return lhsAddr < rhsAddr;
|
||||
// If same address, one is an alias so sort by scope.
|
||||
// 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)
|
||||
@ -339,8 +341,8 @@ llvm::Error processSymboledSection(DefinedAtom::ContentType atomType,
|
||||
scatterable, copyRefs);
|
||||
}
|
||||
|
||||
const Symbol *lastSym = nullptr;
|
||||
for (const Symbol *sym : symbols) {
|
||||
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.
|
||||
@ -550,7 +552,7 @@ llvm::Error convertRelocs(const Section §ion,
|
||||
auto atomBySymbol = [&] (uint32_t symbolIndex, const lld::Atom **result)
|
||||
-> llvm::Error {
|
||||
// Find symbol from index.
|
||||
const Symbol *sym = nullptr;
|
||||
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();
|
||||
|
42
lld/test/mach-o/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd
Normal file
42
lld/test/mach-o/Inputs/MacOSX.sdk/usr/lib/libSystem.tbd
Normal file
@ -0,0 +1,42 @@
|
||||
--- !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/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/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/libsystem_m.dylib'
|
||||
current-version: 0001.001.1
|
||||
parent-umbrella: System
|
||||
exports:
|
||||
- archs: [ 'x86_64' ]
|
||||
symbols: [ ___nan ]
|
||||
...
|
21
lld/test/mach-o/stub-link.s
Normal file
21
lld/test/mach-o/stub-link.s
Normal file
@ -0,0 +1,21 @@
|
||||
# REQUIRES: x86
|
||||
|
||||
# RUN: mkdir -p %t
|
||||
#
|
||||
# RUN: llvm-mc -filetype obj -triple x86_64-apple-darwin %s -o %t/test.o
|
||||
# RUN: ld64.lld -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
|
Loading…
Reference in New Issue
Block a user