From 570e6f6d3b06d72fffb38e99aad0a3829a27cce9 Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Sat, 5 Apr 2025 08:52:59 -0700 Subject: [PATCH 1/3] [llvm-nm] Fix how inlined dylibs are reported from tbd files An Inlined library is a dylib that is reexported from an umbrella or top level library. When this is encoded in tbd files, ensure we are reading the symbol table from the inlined library when `--add-inlinedinfo` is used as opposed to the top level lib. --- llvm/include/llvm/Object/TapiUniversal.h | 6 ++++-- llvm/lib/Object/TapiUniversal.cpp | 22 ++++++++++++++-------- llvm/test/tools/llvm-nm/tapi-files.test | 10 ++-------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/llvm/include/llvm/Object/TapiUniversal.h b/llvm/include/llvm/Object/TapiUniversal.h index fff66c28c1a41..857d7c127622f 100644 --- a/llvm/include/llvm/Object/TapiUniversal.h +++ b/llvm/include/llvm/Object/TapiUniversal.h @@ -110,9 +110,11 @@ class TapiUniversal : public Binary { static bool classof(const Binary *v) { return v->isTapiUniversal(); } private: + /// Attributes of a library that is inlined into a single TBD file. struct Library { - StringRef InstallName; - MachO::Architecture Arch; + const StringRef InstallName; + const MachO::Architecture Arch; + const size_t DocumentIdx; }; std::unique_ptr ParsedFile; diff --git a/llvm/lib/Object/TapiUniversal.cpp b/llvm/lib/Object/TapiUniversal.cpp index 74e0c519ddfdb..6fd87f7d73af6 100644 --- a/llvm/lib/Object/TapiUniversal.cpp +++ b/llvm/lib/Object/TapiUniversal.cpp @@ -29,25 +29,31 @@ TapiUniversal::TapiUniversal(MemoryBufferRef Source, Error &Err) } ParsedFile = std::move(Result.get()); - auto FlattenObjectInfo = [this](const auto &File) { + auto FlattenObjectInfo = [this](const auto &File, unsigned DocIdx) { StringRef Name = File->getInstallName(); for (const Architecture Arch : File->getArchitectures()) - Libraries.emplace_back(Library({Name, Arch})); + Libraries.emplace_back(Library({Name, Arch, DocIdx})); }; - - FlattenObjectInfo(ParsedFile); + size_t DocIdx = 0; + FlattenObjectInfo(ParsedFile, DocIdx); // Get inlined documents from tapi file. for (const std::shared_ptr &File : ParsedFile->documents()) - FlattenObjectInfo(File); + FlattenObjectInfo(File, DocIdx++); } TapiUniversal::~TapiUniversal() = default; Expected> TapiUniversal::ObjectForArch::getAsObjectFile() const { - return std::make_unique(Parent->getMemoryBufferRef(), - *Parent->ParsedFile, - Parent->Libraries[Index].Arch); + const auto &InlinedDocuments = Parent->ParsedFile->documents(); + const Library &CurrLib = Parent->Libraries[Index]; + assert((isTopLevelLib() || (InlinedDocuments.size() > CurrLib.DocumentIdx)) && + "Index into documents exceeds the container for them"); + InterfaceFile *IF = isTopLevelLib() + ? Parent->ParsedFile.get() + : InlinedDocuments[CurrLib.DocumentIdx].get(); + return std::make_unique(Parent->getMemoryBufferRef(), *IF, + CurrLib.Arch); } Expected> diff --git a/llvm/test/tools/llvm-nm/tapi-files.test b/llvm/test/tools/llvm-nm/tapi-files.test index bd3663a21861f..8dc8a7cf924f2 100644 --- a/llvm/test/tools/llvm-nm/tapi-files.test +++ b/llvm/test/tools/llvm-nm/tapi-files.test @@ -45,14 +45,8 @@ V3-NEXT: 0000000000000000 S _OBJC_METACLASS_$_NSString V3-NEXT: 0000000000000000 S _sym1 V3-NEXT: 0000000000000000 S _sym2 V3: /usr/lib/liba.dylib (for architecture x86_64): -V3-NEXT: 0000000000000000 S _OBJC_CLASS_$_NSBlockPredicate -V3-NEXT: 0000000000000000 S _OBJC_CLASS_$_NSString -V3-NEXT: 0000000000000000 S _OBJC_EHTYPE_$_NSString -V3-NEXT: 0000000000000000 S _OBJC_IVAR_$_NSBlockPredicate._block -V3-NEXT: 0000000000000000 S _OBJC_METACLASS_$_NSBlockPredicate -V3-NEXT: 0000000000000000 S _OBJC_METACLASS_$_NSString -V3-NEXT: 0000000000000000 S _sym1 -V3-NEXT: 0000000000000000 S _sym2 +V3-NEXT: 0000000000000000 S _sym10 +V3-NEXT: 0000000000000000 S _sym11 V4: /u/l/libFoo.dylib (for architecture i386): V4-NEXT: 00000000 S _sym1 From cba5ed3a0d84ca4dd6df9e79ea9859bd3a1e056c Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Sat, 5 Apr 2025 09:27:26 -0700 Subject: [PATCH 2/3] Use consistent type for idx --- llvm/lib/Object/TapiUniversal.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Object/TapiUniversal.cpp b/llvm/lib/Object/TapiUniversal.cpp index 6fd87f7d73af6..55fbd93c4e134 100644 --- a/llvm/lib/Object/TapiUniversal.cpp +++ b/llvm/lib/Object/TapiUniversal.cpp @@ -29,7 +29,7 @@ TapiUniversal::TapiUniversal(MemoryBufferRef Source, Error &Err) } ParsedFile = std::move(Result.get()); - auto FlattenObjectInfo = [this](const auto &File, unsigned DocIdx) { + auto FlattenObjectInfo = [this](const auto &File, size_t DocIdx) { StringRef Name = File->getInstallName(); for (const Architecture Arch : File->getArchitectures()) Libraries.emplace_back(Library({Name, Arch, DocIdx})); From 3acfa3901a43e57292a451451f1a6484104b9ada Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Tue, 8 Apr 2025 12:55:55 -0700 Subject: [PATCH 3/3] wrap index in std::optional bc it can be null --- llvm/include/llvm/Object/TapiUniversal.h | 2 +- llvm/lib/Object/TapiUniversal.cpp | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/Object/TapiUniversal.h b/llvm/include/llvm/Object/TapiUniversal.h index 857d7c127622f..558916f7af795 100644 --- a/llvm/include/llvm/Object/TapiUniversal.h +++ b/llvm/include/llvm/Object/TapiUniversal.h @@ -114,7 +114,7 @@ class TapiUniversal : public Binary { struct Library { const StringRef InstallName; const MachO::Architecture Arch; - const size_t DocumentIdx; + const std::optional DocumentIdx; }; std::unique_ptr ParsedFile; diff --git a/llvm/lib/Object/TapiUniversal.cpp b/llvm/lib/Object/TapiUniversal.cpp index 55fbd93c4e134..52f3a04d088f5 100644 --- a/llvm/lib/Object/TapiUniversal.cpp +++ b/llvm/lib/Object/TapiUniversal.cpp @@ -29,14 +29,15 @@ TapiUniversal::TapiUniversal(MemoryBufferRef Source, Error &Err) } ParsedFile = std::move(Result.get()); - auto FlattenObjectInfo = [this](const auto &File, size_t DocIdx) { + auto FlattenObjectInfo = [this](const auto &File, + std::optional DocIdx = std::nullopt) { StringRef Name = File->getInstallName(); for (const Architecture Arch : File->getArchitectures()) Libraries.emplace_back(Library({Name, Arch, DocIdx})); }; - size_t DocIdx = 0; - FlattenObjectInfo(ParsedFile, DocIdx); + FlattenObjectInfo(ParsedFile); // Get inlined documents from tapi file. + size_t DocIdx = 0; for (const std::shared_ptr &File : ParsedFile->documents()) FlattenObjectInfo(File, DocIdx++); } @@ -47,11 +48,13 @@ Expected> TapiUniversal::ObjectForArch::getAsObjectFile() const { const auto &InlinedDocuments = Parent->ParsedFile->documents(); const Library &CurrLib = Parent->Libraries[Index]; - assert((isTopLevelLib() || (InlinedDocuments.size() > CurrLib.DocumentIdx)) && - "Index into documents exceeds the container for them"); + assert( + (isTopLevelLib() || (CurrLib.DocumentIdx.has_value() && + (InlinedDocuments.size() > *CurrLib.DocumentIdx))) && + "Index into documents exceeds the container for them"); InterfaceFile *IF = isTopLevelLib() ? Parent->ParsedFile.get() - : InlinedDocuments[CurrLib.DocumentIdx].get(); + : InlinedDocuments[*CurrLib.DocumentIdx].get(); return std::make_unique(Parent->getMemoryBufferRef(), *IF, CurrLib.Arch); }