[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-6532":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":26,"readmeContent":27,"aiSummary":28,"trendingCount":16,"starSnapshotCount":16,"syncStatus":29,"lastSyncTime":30,"discoverSource":31},6532,"fishhook","facebook\u002Ffishhook","facebook","A library that enables dynamically rebinding symbols in Mach-O binaries running on iOS.","",null,"C",5414,990,226,30,0,1,11,3,68.59,"BSD 3-Clause \"New\" or \"Revised\" License",false,"main",true,[],"2026-06-12 04:00:29","# fishhook\n\n__fishhook__ is a very simple library that enables dynamically rebinding symbols in Mach-O binaries running on iOS in the simulator and on device. This provides functionality that is similar to using [`DYLD_INTERPOSE`][interpose] on OS X. At Facebook, we've found it useful as a way to hook calls in libSystem for debugging\u002Ftracing purposes (for example, auditing for double-close issues with file descriptors).\n\n[interpose]: http:\u002F\u002Fopensource.apple.com\u002Fsource\u002Fdyld\u002Fdyld-210.2.3\u002Finclude\u002Fmach-o\u002Fdyld-interposing.h \"\u003Cmach-o\u002Fdyld-interposing.h>\"\n\n## Usage\n\nOnce you add `fishhook.h`\u002F`fishhook.c` to your project, you can rebind symbols as follows:\n```Objective-C\n#import \u003Cdlfcn.h>\n\n#import \u003CUIKit\u002FUIKit.h>\n\n#import \"AppDelegate.h\"\n#import \"fishhook.h\"\n \nstatic int (*orig_close)(int);\nstatic int (*orig_open)(const char *, int, ...);\n \nint my_close(int fd) {\n  printf(\"Calling real close(%d)\\n\", fd);\n  return orig_close(fd);\n}\n \nint my_open(const char *path, int oflag, ...) {\n  va_list ap = {0};\n  mode_t mode = 0;\n \n  if ((oflag & O_CREAT) != 0) {\n    \u002F\u002F mode only applies to O_CREAT\n    va_start(ap, oflag);\n    mode = va_arg(ap, int);\n    va_end(ap);\n    printf(\"Calling real open('%s', %d, %d)\\n\", path, oflag, mode);\n    return orig_open(path, oflag, mode);\n  } else {\n    printf(\"Calling real open('%s', %d)\\n\", path, oflag);\n    return orig_open(path, oflag, mode);\n  }\n}\n \nint main(int argc, char * argv[])\n{\n  @autoreleasepool {\n    rebind_symbols((struct rebinding[2]){{\"close\", my_close, (void *)&orig_close}, {\"open\", my_open, (void *)&orig_open}}, 2);\n \n    \u002F\u002F Open our own binary and print out first 4 bytes (which is the same\n    \u002F\u002F for all Mach-O binaries on a given architecture)\n    int fd = open(argv[0], O_RDONLY);\n    uint32_t magic_number = 0;\n    read(fd, &magic_number, 4);\n    printf(\"Mach-O Magic Number: %x \\n\", magic_number);\n    close(fd);\n \n    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n  }\n}\n```\n### Sample output\n```\nCalling real open('\u002Fvar\u002Fmobile\u002FApplications\u002F161DA598-5B83-41F5-8A44-675491AF6A2C\u002FTest.app\u002FTest', 0)\nMach-O Magic Number: feedface \nCalling real close(3)\n...\n```\n\n## How it works\n\n`dyld` binds lazy and non-lazy symbols by updating pointers in particular sections of the `__DATA` segment of a Mach-O binary. __fishhook__ re-binds these symbols by determining the locations to update for each of the symbol names passed to `rebind_symbols` and then writing out the corresponding replacements.\n\nFor a given image, the `__DATA` segment may contain two sections that are relevant for dynamic symbol bindings: `__nl_symbol_ptr` and `__la_symbol_ptr`. `__nl_symbol_ptr` is an array of pointers to non-lazily bound data (these are bound at the time a library is loaded) and `__la_symbol_ptr` is an array of pointers to imported functions that is generally filled by a routine called `dyld_stub_binder` during the first call to that symbol (it's also possible to tell `dyld` to bind these at launch). In order to find the name of the symbol that corresponds to a particular location in one of these sections, we have to jump through several layers of indirection. For the two relevant sections, the section headers (`struct section`s from `\u003Cmach-o\u002Floader.h>`) provide an offset (in the `reserved1` field) into what is known as the indirect symbol table. The indirect symbol table, which is located in the `__LINKEDIT` segment of the binary, is just an array of indexes into the symbol table (also in `__LINKEDIT`) whose order is identical to that of the pointers in the non-lazy and lazy symbol sections. So, given `struct section nl_symbol_ptr`, the corresponding index in the symbol table of the first address in that section is `indirect_symbol_table[nl_symbol_ptr->reserved1]`. The symbol table itself is an array of `struct nlist`s (see `\u003Cmach-o\u002Fnlist.h>`), and each `nlist` contains an index into the string table in `__LINKEDIT` which where the actual symbol names are stored. So, for each pointer `__nl_symbol_ptr` and `__la_symbol_ptr`, we are able to find the corresponding symbol and then the corresponding string to compare against the requested symbol names, and if there is a match, we replace the pointer in the section with the replacement.\n\nThe process of looking up the name of a given entry in the lazy or non-lazy pointer tables looks like this:\n![Visual explanation](http:\u002F\u002Fi.imgur.com\u002FHVXqHCz.png)","fishhook 是一个简单的库，允许在iOS模拟器和设备上运行的Mach-O二进制文件中动态重新绑定符号。其核心功能是通过修改Mach-O二进制文件中的`__DATA`段相关部分来实现符号重绑定，类似于macOS上的`DYLD_INTERPOSE`机制。该技术特别适用于需要拦截或调试系统调用（如libSystem中的函数）的场景，例如审计文件描述符的双关闭问题。鱼钩库以C语言编写，使用BSD 3-Clause许可证发布，在追求高效且灵活地进行动态链接调整的应用开发与维护过程中非常有用。",2,"2026-06-11 03:07:29","top_language"]