diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /lld/lib/ReaderWriter/MachO/File.h | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'lld/lib/ReaderWriter/MachO/File.h')
-rw-r--r-- | lld/lib/ReaderWriter/MachO/File.h | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h index 072702973f81..8d59656beab5 100644 --- a/lld/lib/ReaderWriter/MachO/File.h +++ b/lld/lib/ReaderWriter/MachO/File.h @@ -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 |