+uintptr_t ImageLoaderMachO::bindIndirectSymbol(uintptr_t* ptrToBind, const struct macho_section* sect, const char* symbolName, uintptr_t targetAddr, ImageLoader* targetImage, const LinkContext& context)
+{
+ if ( context.verboseBind ) {
+ const char* path = NULL;
+ if ( targetImage != NULL )
+ path = targetImage->getShortName();
+ fprintf(stderr, "dyld: bind: %s:%s$%s = %s:%s, *0x%08lx = 0x%08lx\n",
+ this->getShortName(), symbolName, (((sect->flags & SECTION_TYPE)==S_NON_LAZY_SYMBOL_POINTERS) ? "non_lazy_ptr" : "lazy_ptr"),
+ path, symbolName, (uintptr_t)ptrToBind, targetAddr);
+ }
+ if ( context.bindingHandler != NULL ) {
+ const char* path = NULL;
+ if ( targetImage != NULL )
+ path = targetImage->getShortName();
+ targetAddr = (uintptr_t)context.bindingHandler(path, symbolName, (void *)targetAddr);
+ }
+#if __i386__
+ // i386 has special self-modifying stubs that change from "CALL rel32" to "JMP rel32"
+ if ( ((sect->flags & SECTION_TYPE) == S_SYMBOL_STUBS) && ((sect->flags & S_ATTR_SELF_MODIFYING_CODE) != 0) && (sect->reserved2 == 5) ) {
+ uint8_t* const jmpTableEntryToPatch = (uint8_t*)ptrToBind;
+ uint32_t rel32 = targetAddr - (((uint32_t)ptrToBind)+5);
+ //fprintf(stderr, "rewriting stub at %p\n", jmpTableEntryToPatch);
+ jmpTableEntryToPatch[0] = 0xE9; // JMP rel32
+ jmpTableEntryToPatch[1] = rel32 & 0xFF;
+ jmpTableEntryToPatch[2] = (rel32 >> 8) & 0xFF;
+ jmpTableEntryToPatch[3] = (rel32 >> 16) & 0xFF;
+ jmpTableEntryToPatch[4] = (rel32 >> 24) & 0xFF;
+ }
+ else
+#endif
+ *ptrToBind = targetAddr;
+ return targetAddr;
+}
+