From ae95986f6a7351ea2c82d52338facb8784fa01c1 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Thu, 30 Jul 2026 08:34:41 +0000 Subject: [PATCH 2/3] [tapi] Don't drop classic-symtab exports absent from the export trie readSymbols() builds a map of exports from the LC_DYLD_INFO export trie, then walks the symbol table and, for each SF_Exported symbol, looked it up in that map and skipped it (continue) when not found. This silently drops every exported symbol of a dylib that has no export trie. Classic dylibs from macOS 10.5 and earlier - which is every ppc/ppc64 dylib of interest - use the classic LC_SYMTAB / LC_DYSYMTAB LINKEDIT and carry no LC_DYLD_INFO trie (compressed LINKEDIT arrived in 10.6). For those, object->exports() yields nothing, the map is empty, and the reader produced a valid-but-empty .tbd: it builds, but the output is wrong. Fall back to the symbol table's own export flag when a symbol is missing from the trie, treating it as exported. This mirrors what the LLVM TextAPI DylibReader already does (BinaryReader/DylibReader.cpp), and also handles stripped or malformed tries. Symbols present in the trie continue to use its richer flags (weak/thread-local/reexport). Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01PrKAYGVW1tzwQAAoTGXVfM --- src/tapi/lib/Core/MachOReader.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/tapi/lib/Core/MachOReader.cpp b/src/tapi/lib/Core/MachOReader.cpp index ba4849d..9c4bfcf 100644 --- a/src/tapi/lib/Core/MachOReader.cpp +++ b/src/tapi/lib/Core/MachOReader.cpp @@ -367,9 +367,16 @@ static Error readSymbols(MachOObjectFile *object, API &api, linkage = APILinkage::External; else if (flags & SymbolRef::SF_Exported) { auto it = exports.find(name.str()); - if (it == exports.end()) - continue; - std::tie(apiFlags, linkage) = it->second; + // A symbol may be exported per the symbol table yet absent from the + // export trie: classic (pre-macOS 10.6) dylibs have no LC_DYLD_INFO trie + // at all, and it is also possible to craft a dylib whose trie is stripped + // or conflicts with the symbol table. In those cases fall back to the + // symbol table's own export flag instead of dropping the symbol, which + // would otherwise silently omit every export of a classic ppc/ppc64 dylib. + if (it != exports.end()) + std::tie(apiFlags, linkage) = it->second; + else + linkage = APILinkage::Exported; } else if (flags & SymbolRef::SF_Hidden) linkage = APILinkage::Internal; else -- 2.43.0