先掌握一些 macOS 下的前置知识:
macho
Mach-O (Mach Object 的缩写)是 IOS/macOS 下的原生可执行文件格式,可用于可执行文件、共享库、动态加载的代码等等。
dylib
也被称为动态共享库、共享对象或动态链接库,简单来说 dylib
就是用于动态链接的库。
Load commands
Mach-O文件由头(Header)、装载指令(Load Commands)和数据(Data)组成。这些加载命令在Mach-O文件加载解析时,被内核加载器或者动态链接器调用,这些加载命令指定了二进制文件的布局和链接特性(内存布局、主线程的初始执行状态、依赖的动态链接的名称等)。
MachOView查看装载指令
otool查看装载指令
LoadCommands基本的加载命令的数据结构如下:
struct load_command {
uint32_t cmd; /* type of load command */
uint32_t cmdsize; /* total size of command in bytes */
};
cmd 字段代表当前加载命令的类型。
cmdsize 字段代表当前加载命令的大小。
加载命令类型的定义在 mach-o/loader.h 中,以 LC 为前缀的;所有的这些加载命令由系统内核加载器直接使用,或由动态链接器处理。其中几个常见的加载命令有LC_SEGMENT
、LC_LOAD_DYLINKER
、LC_LOAD_DYLIB
、LC_MAIN
、LC_CODE_SIGNATURE
、LC_ENCRYPTION_INFO
等。这里重点关注下 dylib 的加载,当cmd类型是LC_LOAD_DYLIB
、LC_LOAD_WEAK_DYLIB
与LC_REEXPORT_DYLIB
时,统一使用 dylib_command 结构体表示:
...
struct dylib_command {
uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,
LC_REEXPORT_DYLIB */
uint32_t cmdsize; /* includes pathname string */
struct dylib dylib; /* the library identification */
};
...
struct dylib {
union lc_str name; /* library's path name */
uint32_t timestamp; /* library's build time stamp */
uint32_t current_version; /* library's current version number */
uint32_t compatibility_version; /* library's compatibility vers number*/
};
在 macOS 中动态链接器在程序加载之前加载 DYLD_INSERT_LIBRARIES
此环境变量中指定的任何动态库,本质上是将动态库注入应用程序。写个例子测试一下:
example.dylib
// clang -shared -framework Foundation example_dylib.m -o libexample.dylib
#import <Foundation/Foundation.h>
static void __attribute__((constructor)) initialize(void){
NSLog(@"insert_dylib i'm here");
}
hello.m
// clang -framework Foundation hello.m -o hello
#import <Foundation/Foundation.h>
int main(int argc, char **argv) {
@autoreleasepool {
NSLog(@"HelloWorld!");
}
}
指定 libexample.dylib
并运行 $ DYLD_INSERT_LIBRARIES=./libexample.dylib ./hello
libexample.dylib 被提前加载执行,运行结果如下:
$ DYLD_INSERT_LIBRARIES=./libexample.dylib ./hello
2022-11-20 21:06:06.397 hello[17898:473695] insert_dylib i'm here
2022-11-20 21:06:06.398 hello[17898:473695] HelloWorld!
“DYLD_INSERT_LIBRARIES”
的限制