diff --git a/llvm/include/llvm/Object/TapiUniversal.h b/llvm/include/llvm/Object/TapiUniversal.h --- a/llvm/include/llvm/Object/TapiUniversal.h +++ b/llvm/include/llvm/Object/TapiUniversal.h @@ -41,18 +41,22 @@ uint32_t getCPUType() const { auto Result = - MachO::getCPUTypeFromArchitecture(Parent->Architectures[Index]); + MachO::getCPUTypeFromArchitecture(Parent->ObjectsInfo[Index].second); return Result.first; } uint32_t getCPUSubType() const { auto Result = - MachO::getCPUTypeFromArchitecture(Parent->Architectures[Index]); + MachO::getCPUTypeFromArchitecture(Parent->ObjectsInfo[Index].second); return Result.second; } std::string getArchFlagName() const { - return MachO::getArchitectureName(Parent->Architectures[Index]); + return MachO::getArchitectureName(Parent->ObjectsInfo[Index].second); + } + + std::string getInstallName() const { + return Parent->ObjectsInfo[Index].first; } Expected> getAsObjectFile() const; @@ -86,21 +90,23 @@ object_iterator begin_objects() const { return ObjectForArch(this, 0); } object_iterator end_objects() const { - return ObjectForArch(this, Architectures.size()); + return ObjectForArch(this, ObjectsInfo.size()); } iterator_range objects() const { return make_range(begin_objects(), end_objects()); } - uint32_t getNumberOfObjects() const { return Architectures.size(); } + uint32_t getNumberOfObjects() const { return ObjectsInfo.size(); } // Cast methods. static bool classof(const Binary *v) { return v->isTapiUniversal(); } + using ObjectInfo = std::pair; + private: std::unique_ptr ParsedFile; - std::vector Architectures; + std::vector ObjectsInfo; }; } // end namespace object. diff --git a/llvm/include/llvm/TextAPI/MachO/InterfaceFile.h b/llvm/include/llvm/TextAPI/MachO/InterfaceFile.h --- a/llvm/include/llvm/TextAPI/MachO/InterfaceFile.h +++ b/llvm/include/llvm/TextAPI/MachO/InterfaceFile.h @@ -301,6 +301,20 @@ return UUIDs; } + /// Add additional InterfaceFile to + /// + ///\param Document the inlined framework used in main input + void addDocument(std::shared_ptr &&Document) { + Documents.emplace_back(std::move(Document)); + } + + /// Get the additional InterfaceFiles to + /// + /// \return Returns a list of the inlined frameworks + const std::vector> &getDocuments() const { + return Documents; + } + /// Add a symbol to the symbols list or extend an existing one. void addSymbol(SymbolKind Kind, StringRef Name, ArchitectureSet Architectures, SymbolFlags Flags = SymbolFlags::None); @@ -379,6 +393,7 @@ std::vector ReexportedLibraries; std::vector> UUIDs; SymbolMapType Symbols; + std::vector> Documents; }; } // end namespace MachO. diff --git a/llvm/lib/Object/TapiUniversal.cpp b/llvm/lib/Object/TapiUniversal.cpp --- a/llvm/lib/Object/TapiUniversal.cpp +++ b/llvm/lib/Object/TapiUniversal.cpp @@ -30,24 +30,30 @@ } ParsedFile = std::move(Result.get()); - auto Archs = ParsedFile->getArchitectures(); - for (auto Arch : Archs) - Architectures.emplace_back(Arch); + auto FlattenObjectInformation = [this](auto &File) { + auto Name = File->getInstallName(); + for (const auto Arch : File->getArchitectures()) + ObjectsInfo.emplace_back(std::make_pair(Name, Arch)); + }; + + FlattenObjectInformation(ParsedFile); + for (const auto &File : ParsedFile->getDocuments()) + FlattenObjectInformation(File); } TapiUniversal::~TapiUniversal() = default; Expected> TapiUniversal::ObjectForArch::getAsObjectFile() const { - return std::unique_ptr(new TapiFile(Parent->getMemoryBufferRef(), - *Parent->ParsedFile.get(), - Parent->Architectures[Index])); + return std::make_unique(Parent->getMemoryBufferRef(), + *Parent->ParsedFile.get(), + Parent->ObjectsInfo[Index].second); } Expected> TapiUniversal::create(MemoryBufferRef Source) { Error Err = Error::success(); - std::unique_ptr Ret(new TapiUniversal(Source, Err)); + auto Ret = std::make_unique(Source, Err); if (Err) return std::move(Err); return std::move(Ret); diff --git a/llvm/lib/TextAPI/MachO/TextStub.cpp b/llvm/lib/TextAPI/MachO/TextStub.cpp --- a/llvm/lib/TextAPI/MachO/TextStub.cpp +++ b/llvm/lib/TextAPI/MachO/TextStub.cpp @@ -637,6 +637,10 @@ auto File = std::unique_ptr( const_cast(Files.front())); + for (auto Iter = std::next(Files.begin()); Iter != Files.end(); ++Iter) + File->addDocument( + std::shared_ptr(const_cast(*Iter))); + if (YAMLIn.error()) return make_error(Ctx.ErrorMessage, YAMLIn.error()); @@ -652,6 +656,9 @@ std::vector Files; Files.emplace_back(&File); + for (auto Document : File.getDocuments()) + Files.emplace_back(Document.get()); + // Stream out yaml. YAMLOut << Files; diff --git a/llvm/test/Object/nm-tapi.test b/llvm/test/Object/nm-tapi.test --- a/llvm/test/Object/nm-tapi.test +++ b/llvm/test/Object/nm-tapi.test @@ -8,25 +8,31 @@ RUN: | FileCheck %s -check-prefix v3 v1: no symbols -v1: tapi-v1.tbd (for architecture armv7): +v1: tapi-v1.tbd +v1: /u/l/libfoo.dylib (for architecture armv7): v1: 00000000 S _sym -v1: tapi-v1.tbd (for architecture armv7s): +v1: tapi-v1.tbd +v1: /u/l/libfoo.dylib (for architecture armv7s): -v2: tapi-v2.tbd (for architecture armv7): +v2: tapi-v2.tbd +v2: /u/l/libfoo.dylib (for architecture armv7): v2: 00000000 S _sym1 v2: 00000000 S _sym2 v2: 00000000 S _sym3 -v2: tapi-v2.tbd (for architecture armv7s): +v2: tapi-v2.tbd +v2: /u/l/libfoo.dylib (for architecture armv7s): v2: 00000000 S _sym1 v2: 00000000 S _sym2 v2: 00000000 S _sym3 -v2: tapi-v2.tbd (for architecture arm64): +v2: tapi-v2.tbd +v2: /u/l/libfoo.dylib (for architecture arm64): v2: U _sym v2: 0000000000000000 S _sym1 v2: 0000000000000000 S _sym2 v2: 0000000000000000 S _sym3 -v3: tapi-v3.tbd (for architecture i386): +v3: tapi-v3.tbd +v3: /usr/lib/libfoo.dylib (for architecture i386): v3: 00000000 S _OBJC_CLASS_$_NSBlockPredicate v3: 00000000 S _OBJC_CLASS_$_NSString v3: 00000000 S _OBJC_EHTYPE_$_NSString @@ -36,7 +42,8 @@ v3: 00000000 S _sym1 v3: 00000000 S _sym2 v3: 00000000 S _sym3 -v3: tapi-v3.tbd (for architecture armv7): +v3: tapi-v3.tbd +v3: /usr/lib/libfoo.dylib (for architecture armv7): v3: 00000000 S _OBJC_CLASS_$_NSBlockPredicate v3: 00000000 S _OBJC_CLASS_$_NSString v3: 00000000 S _OBJC_EHTYPE_$_NSString @@ -45,7 +52,8 @@ v3: 00000000 S _OBJC_METACLASS_$_NSString v3: 00000000 S _sym1 v3: 00000000 S _sym2 -v3: tapi-v3.tbd (for architecture armv7s): +v3: tapi-v3.tbd +v3: /usr/lib/libfoo.dylib (for architecture armv7s): v3: 00000000 S _OBJC_CLASS_$_NSBlockPredicate v3: 00000000 S _OBJC_CLASS_$_NSString v3: 00000000 S _OBJC_EHTYPE_$_NSString @@ -54,3 +62,23 @@ v3: 00000000 S _OBJC_METACLASS_$_NSString v3: 00000000 S _sym1 v3: 00000000 S _sym2 +v3: tapi-v3.tbd +v3: /usr/lib/liba.dylib (for architecture armv7): +v3: 00000000 S _OBJC_CLASS_$_NSBlockPredicate +v3: 00000000 S _OBJC_CLASS_$_NSString +v3: 00000000 S _OBJC_EHTYPE_$_NSString +v3: 00000000 S _OBJC_IVAR_$_NSBlockPredicate._block +v3: 00000000 S _OBJC_METACLASS_$_NSBlockPredicate +v3: 00000000 S _OBJC_METACLASS_$_NSString +v3: 00000000 S _sym1 +v3: 00000000 S _sym2 +v3: tapi-v3.tbd +v3: /usr/lib/liba.dylib (for architecture armv7s): +v3: 00000000 S _OBJC_CLASS_$_NSBlockPredicate +v3: 00000000 S _OBJC_CLASS_$_NSString +v3: 00000000 S _OBJC_EHTYPE_$_NSString +v3: 00000000 S _OBJC_IVAR_$_NSBlockPredicate._block +v3: 00000000 S _OBJC_METACLASS_$_NSBlockPredicate +v3: 00000000 S _OBJC_METACLASS_$_NSString +v3: 00000000 S _sym1 +v3: 00000000 S _sym2 \ No newline at end of file diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -2080,7 +2080,8 @@ if (ObjOrErr) { auto &Obj = *ObjOrErr.get(); outs() << "\n" - << Obj.getFileName() << " (for architecture " + << Obj.getFileName() << "\n" + << I.getInstallName() << " (for architecture " << I.getArchFlagName() << ")" << ":\n"; dumpSymbolNamesFromObject(Obj, false, {}, I.getArchFlagName()); diff --git a/llvm/unittests/TextAPI/TextStubV3Tests.cpp b/llvm/unittests/TextAPI/TextStubV3Tests.cpp --- a/llvm/unittests/TextAPI/TextStubV3Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV3Tests.cpp @@ -128,6 +128,115 @@ std::equal(Exports.begin(), Exports.end(), std::begin(TBDv3Symbols))); } +TEST(TBDv3, ReadFile2) { + static const char tbd_v3_file1[] = + "--- !tapi-tbd-v3\n" + "archs: [ armv7, arm64 ]\n" + "uuids: [ 'armv7: 00000000-0000-0000-0000-000000000000',\n" + " 'arm64: 11111111-1111-1111-1111-111111111111']\n" + "platform: ios\n" + "flags: [ installapi ]\n" + "install-name: Test.dylib\n" + "current-version: 2.3.4\n" + "compatibility-version: 1.0\n" + "swift-abi-version: 1.1\n" + "parent-umbrella: Umbrella.dylib\n" + "exports:\n" + " - archs: [ armv7, arm64 ]\n" + " allowable-clients: [ clientA ]\n" + " re-exports: [ /usr/lib/libfoo.dylib ]\n" + " symbols: [ _sym1, _sym2, _sym3, _sym4, $ld$hide$os9.0$_sym1 ]\n" + " objc-classes: [ class1, class2 ]\n" + " objc-eh-types: [ class1 ]\n" + " objc-ivars: [ class1._ivar1, class1._ivar2 ]\n" + " weak-def-symbols: [ _weak1, _weak2 ]\n" + " thread-local-symbols: [ _tlv1, _tlv3 ]\n" + " - archs: [ armv7 ]\n" + " symbols: [ _sym5 ]\n" + " objc-classes: [ class3 ]\n" + " objc-ivars: [ class1._ivar3 ]\n" + " weak-def-symbols: [ _weak3 ]\n" + " thread-local-symbols: [ _tlv3 ]\n" + "--- !tapi-tbd-v3\n" + "archs: [ armv7, arm64 ]\n" + "platform: ios\n" + "install-name: TestInline.dylib\n" + "swift-abi-version: 1.1\n" + "exports:\n" + " - archs: [ armv7, arm64 ]\n" + " symbols: [ _sym5, _sym6 ]\n" + "...\n"; + + auto Result = TextAPIReader::get(MemoryBufferRef(tbd_v3_file1, "Test.tbd")); + EXPECT_TRUE(!!Result); + auto File = std::move(Result.get()); + EXPECT_EQ(File->getDocuments().size(), 1U); + EXPECT_EQ(FileType::TBD_V3, File->getFileType()); + auto Archs = AK_armv7 | AK_arm64; + EXPECT_EQ(Archs, File->getArchitectures()); + UUIDs uuids = {{AK_armv7, "00000000-0000-0000-0000-000000000000"}, + {AK_arm64, "11111111-1111-1111-1111-111111111111"}}; + EXPECT_EQ(uuids, File->uuids()); + EXPECT_EQ(PlatformKind::iOS, File->getPlatform()); + EXPECT_EQ(std::string("Test.dylib"), File->getInstallName()); + EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion()); + EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion()); + EXPECT_EQ(2U, File->getSwiftABIVersion()); + EXPECT_EQ(ObjCConstraintType::Retain_Release, File->getObjCConstraint()); + EXPECT_TRUE(File->isTwoLevelNamespace()); + EXPECT_TRUE(File->isApplicationExtensionSafe()); + EXPECT_TRUE(File->isInstallAPI()); + InterfaceFileRef client("clientA", Archs); + InterfaceFileRef reexport("/usr/lib/libfoo.dylib", Archs); + EXPECT_EQ(1U, File->allowableClients().size()); + EXPECT_EQ(client, File->allowableClients().front()); + EXPECT_EQ(1U, File->reexportedLibraries().size()); + EXPECT_EQ(reexport, File->reexportedLibraries().front()); + + ExportedSymbolSeq Exports; + for (const auto *Sym : File->symbols()) { + EXPECT_FALSE(Sym->isWeakReferenced()); + EXPECT_FALSE(Sym->isUndefined()); + Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName(), + Sym->isWeakDefined(), + Sym->isThreadLocalValue()}); + } + llvm::sort(Exports.begin(), Exports.end()); + + EXPECT_EQ(sizeof(TBDv3Symbols) / sizeof(ExportedSymbol), Exports.size()); + EXPECT_TRUE( + std::equal(Exports.begin(), Exports.end(), std::begin(TBDv3Symbols))); + + // Check Second Document + Exports.clear(); + auto Document = File->getDocuments().front(); + EXPECT_EQ(FileType::TBD_V3, Document->getFileType()); + EXPECT_EQ(Archs, File->getArchitectures()); + EXPECT_EQ(PlatformKind::iOS, Document->getPlatform()); + EXPECT_EQ(std::string("TestInline.dylib"), Document->getInstallName()); + EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCurrentVersion()); + EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCompatibilityVersion()); + EXPECT_EQ(2U, Document->getSwiftABIVersion()); + + for (const auto *Sym : Document->symbols()) { + EXPECT_FALSE(Sym->isWeakReferenced()); + EXPECT_FALSE(Sym->isUndefined()); + Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName(), + Sym->isWeakDefined(), + Sym->isThreadLocalValue()}); + } + llvm::sort(Exports.begin(), Exports.end()); + + ExportedSymbolSeq DocumentSymbols{ + {SymbolKind::GlobalSymbol, "_sym5", false, false}, + {SymbolKind::GlobalSymbol, "_sym6", false, false}, + }; + + EXPECT_EQ(DocumentSymbols.size(), Exports.size()); + EXPECT_TRUE( + std::equal(Exports.begin(), Exports.end(), DocumentSymbols.begin())); +} + TEST(TBDv3, WriteFile) { static const char tbd_v3_file3[] = "--- !tapi-tbd-v3\n" @@ -180,6 +289,82 @@ EXPECT_STREQ(tbd_v3_file3, Buffer.c_str()); } +TEST(TBDv3, WriteFile2) { + static const char tbd_v3_file3[] = + "--- !tapi-tbd-v3\n" + "archs: [ i386, x86_64 ]\n" + "platform: macosx\n" + "install-name: '/usr/lib/libfoo.dylib'\n" + "current-version: 1.2.3\n" + "compatibility-version: 0\n" + "swift-abi-version: 5\n" + "exports:\n" + " - archs: [ i386 ]\n" + " symbols: [ _sym1 ]\n" + " weak-def-symbols: [ _sym2 ]\n" + " thread-local-symbols: [ _sym3 ]\n" + " - archs: [ x86_64 ]\n" + " allowable-clients: [ clientA ]\n" + " re-exports: [ '/usr/lib/libfoo.dylib' ]\n" + " objc-classes: [ Class1 ]\n" + " objc-eh-types: [ Class1 ]\n" + " objc-ivars: [ Class1._ivar1 ]\n" + "--- !tapi-tbd-v3\n" + "archs: [ i386 ]\n" + "platform: macosx\n" + "install-name: '/usr/lib/libbar.dylib'\n" + "current-version: 0\n" + "compatibility-version: 0\n" + "swift-abi-version: 5\n" + "objc-constraint: none\n" + "exports:\n" + " - archs: [ i386 ]\n" + " symbols: [ _sym3, _sym4 ]\n" + "...\n"; + + InterfaceFile File; + File.setPath("libfoo.dylib"); + File.setInstallName("/usr/lib/libfoo.dylib"); + File.setFileType(FileType::TBD_V3); + File.setArchitectures(AK_i386 | AK_x86_64); + File.setPlatform(PlatformKind::macOS); + File.setCurrentVersion(PackedVersion(1, 2, 3)); + File.setTwoLevelNamespace(); + File.setApplicationExtensionSafe(); + File.setSwiftABIVersion(5); + File.setObjCConstraint(ObjCConstraintType::Retain_Release); + File.addAllowableClient("clientA", AK_x86_64); + File.addReexportedLibrary("/usr/lib/libfoo.dylib", AK_x86_64); + File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", AK_i386); + File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", AK_i386, + SymbolFlags::WeakDefined); + File.addSymbol(SymbolKind::GlobalSymbol, "_sym3", AK_i386, + SymbolFlags::ThreadLocalValue); + File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", AK_x86_64); + File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", AK_x86_64); + File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1", + AK_x86_64); + + // Inline document + InterfaceFile Document; + Document.setPath("libbar.dylib"); + Document.setInstallName("/usr/lib/libbar.dylib"); + Document.setFileType(FileType::TBD_V3); + Document.setArchitectures(AK_i386); + Document.setPlatform(PlatformKind::macOS); + Document.setTwoLevelNamespace(); + Document.setApplicationExtensionSafe(); + Document.setSwiftABIVersion(5); + Document.addSymbol(SymbolKind::GlobalSymbol, "_sym3", AK_i386); + Document.addSymbol(SymbolKind::GlobalSymbol, "_sym4", AK_i386); + File.addDocument(std::make_shared(std::move(Document))); + SmallString<4096> Buffer; + raw_svector_ostream OS(Buffer); + auto Result = TextAPIWriter::writeToStream(OS, File); + EXPECT_FALSE(Result); + EXPECT_STREQ(tbd_v3_file3, Buffer.c_str()); +} + TEST(TBDv3, Platform_macOS) { static const char tbd_v1_platform_macos[] = "--- !tapi-tbd-v3\n" "archs: [ x86_64 ]\n"