@@ -26,6 +26,12 @@ static MachoViewType* g_machoViewType = nullptr;
2626
2727namespace {
2828
29+ // Pseudo-library names used when an import's two-level-namespace ordinal refers to a special
30+ // dyld lookup mode rather than a concrete LC_LOAD_DYLIB entry.
31+ constexpr std::string_view kPseudoLibraryMainExecutable = " <main executable>" ;
32+ constexpr std::string_view kPseudoLibraryFlatLookup = " <flat lookup>" ;
33+ constexpr std::string_view kPseudoLibraryWeakLookup = " <weak lookup>" ;
34+
2935string CommandToString (uint32_t lcCommand)
3036{
3137 switch (lcCommand)
@@ -2286,11 +2292,13 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
22862292 BulkSymbolModification bulkSymbolModification (this );
22872293 m_symbolQueue = new SymbolQueue ();
22882294
2295+ std::unordered_map<std::string, std::string> symbolLibraryMapping;
2296+
22892297 try
22902298 {
22912299 // Add functions for all function symbols
22922300 m_logger->LogDebug (" Parsing symbol table\n " );
2293- ParseSymbolTable (reader, header, header.symtab , indirectSymbols, objcProcessor.get ());
2301+ ParseSymbolTable (reader, header, header.symtab , indirectSymbols, objcProcessor.get (), symbolLibraryMapping );
22942302 }
22952303 catch (std::exception&)
22962304 {
@@ -2314,7 +2322,6 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
23142322 objcProcessor->AddRelocatedPointer (relocationLocation, slidTarget);
23152323 }
23162324
2317- Ref<Metadata> symbolToLibraryMapping = new Metadata (KeyValueDataType);
23182325 for (auto & [relocation, name, ordinal] : header.bindingRelocations )
23192326 {
23202327 if (auto symbol = ResolveBindSymbol (this , header, name, ordinal); symbol)
@@ -2328,10 +2335,27 @@ bool MachoView::InitializeHeader(MachOHeader& header, bool isMainHeader, uint64_
23282335 m_logger->LogErrorF (" Failed to find symbol {:?} for bind at {:#x} (ordinal: {})" , name, relocation.address , ordinal);
23292336 }
23302337
2338+ string libName;
23312339 if (ordinal > 0 && ordinal - 1 < header.dylibs .size ())
2332- symbolToLibraryMapping->SetValueForKey (name, new Metadata (header.dylibs [ordinal - 1 ].first ));
2340+ libName = header.dylibs [ordinal - 1 ].first ;
2341+ else if (ordinal == BindSpecialDylibMainExecutable)
2342+ libName = kPseudoLibraryMainExecutable ;
2343+ else if (ordinal == BindSpecialDylibFlatLookup)
2344+ libName = kPseudoLibraryFlatLookup ;
2345+ else if (ordinal == BindSpecialDylibWeakLookup)
2346+ libName = kPseudoLibraryWeakLookup ;
2347+
2348+ if (!libName.empty ())
2349+ {
2350+ if (!GetExternalLibrary (libName))
2351+ AddExternalLibrary (libName, {}, true );
2352+ symbolLibraryMapping[name] = libName;
2353+ }
23332354 }
23342355
2356+ Ref<Metadata> symbolToLibraryMapping = new Metadata (KeyValueDataType);
2357+ for (const auto & [name, libName] : symbolLibraryMapping)
2358+ symbolToLibraryMapping->SetValueForKey (name, new Metadata (libName));
23352359 StoreMetadata (" SymbolExternalLibraryMapping" , std::move (symbolToLibraryMapping), true );
23362360
23372361 auto relocationHandler = m_arch->GetRelocationHandler (" Mach-O" );
@@ -3220,7 +3244,8 @@ void MachoView::ParseDynamicTable(BinaryReader& reader, MachOHeader& header, BNS
32203244
32213245
32223246void MachoView::ParseSymbolTable (BinaryReader& reader, MachOHeader& header, const symtab_command& symtab,
3223- const vector<uint32_t >& indirectSymbols, MachoObjCProcessor* objcProcessor)
3247+ const vector<uint32_t >& indirectSymbols, MachoObjCProcessor* objcProcessor,
3248+ std::unordered_map<std::string, std::string>& symbolLibraryMapping)
32243249{
32253250 if (header.ident .filetype == MH_DSYM)
32263251 {
@@ -3359,6 +3384,25 @@ void MachoView::ParseSymbolTable(BinaryReader& reader, MachOHeader& header, cons
33593384 else if ((sym.n_type & N_EXT))
33603385 {
33613386 type = ExternalSymbol;
3387+
3388+ // Record the owning library from the two-level-namespace ordinal in the high
3389+ // byte of n_desc. See GET_LIBRARY_ORDINAL in <mach-o/nlist.h>.
3390+ unsigned libraryOrdinal = (unsigned )(sym.n_desc >> 8 ) & 0xff ;
3391+ string libName;
3392+ if (libraryOrdinal >= 1 && libraryOrdinal <= 0xfd
3393+ && (size_t )(libraryOrdinal - 1 ) < header.dylibs .size ())
3394+ libName = header.dylibs [libraryOrdinal - 1 ].first ;
3395+ else if (libraryOrdinal == 0xfe ) // DYNAMIC_LOOKUP_ORDINAL
3396+ libName = kPseudoLibraryFlatLookup ;
3397+ else if (libraryOrdinal == 0xff ) // EXECUTABLE_ORDINAL
3398+ libName = kPseudoLibraryMainExecutable ;
3399+
3400+ if (!libName.empty ())
3401+ {
3402+ if (!GetExternalLibrary (libName))
3403+ AddExternalLibrary (libName, {}, true );
3404+ symbolLibraryMapping[symbol] = libName;
3405+ }
33623406 }
33633407 else
33643408 continue ;
@@ -3378,23 +3422,14 @@ void MachoView::ParseSymbolTable(BinaryReader& reader, MachOHeader& header, cons
33783422 auto pointerSymbolIter = pointerSymbols.find (i);
33793423 bool deferred = stubSymbolIter == stubSymbols.end () && pointerSymbolIter == pointerSymbols.end ();
33803424
3381- Ref<Symbol> symbolObj;
3382- if (header.dysymtab .nlocalsym && i >= header.dysymtab .ilocalsym && i < header.dysymtab .ilocalsym + header.dysymtab .nlocalsym )
3383- {
3384- symbolObj = DefineMachoSymbol (type, symbol, sym.n_value , LocalBinding, deferred);
3385- }
3386- else if (header.dysymtab .nextdefsym && i >= header.dysymtab .iextdefsym && i < header.dysymtab .iextdefsym + header.dysymtab .nextdefsym )
3387- {
3388- symbolObj = DefineMachoSymbol (type, symbol, sym.n_value , GlobalBinding, deferred);
3389- }
3390- else if (header.dysymtab .nundefsym && i >= header.dysymtab .iundefsym && i < header.dysymtab .iundefsym + header.dysymtab .nundefsym )
3391- {
3392- symbolObj = DefineMachoSymbol (type, symbol, sym.n_value , GlobalBinding, deferred);
3393- }
3394- else
3395- {
3396- symbolObj = DefineMachoSymbol (type, symbol, sym.n_value , GlobalBinding, deferred);
3397- }
3425+ BNSymbolBinding binding = GlobalBinding;
3426+ if (header.dysymtab .nlocalsym && i >= header.dysymtab .ilocalsym
3427+ && i < header.dysymtab .ilocalsym + header.dysymtab .nlocalsym )
3428+ binding = LocalBinding;
3429+ else if (type == ExternalSymbol && (sym.n_desc & N_WEAK_REF))
3430+ binding = WeakBinding;
3431+
3432+ Ref<Symbol> symbolObj = DefineMachoSymbol (type, symbol, sym.n_value , binding, deferred);
33983433
33993434 if (!symbolObj)
34003435 {
0 commit comments