Macos14.0 调试苹果开源库objc
开源库下载
1、下载地址:https://opensource.apple.com/releases/
2、根据Mac版本选择相应的库


(图1)获取Mac系统版本

(图2)找到可下载的开源库列表
3、需要下载的库列表(这里拿macos14.0为例)
| 需下载列表 |
| dyld-1122.1 |
|
Libc-1583.0.14 Libc-825.26 |
| libclosure-90 |
| libplatform-306.0.1 |
| libpthread-519 |
| objc4-906 |
| xnu-10002.1.13 |
准备
1、解压objc,并打开objc.xcodeproj

2、创建target用于运行objc库,Xcode->File->New->Target

3、创建Command Line Tool类型的Target(也可以选择app类型),并命名为UseObjc(名称随意)

4、选中UseObjc target

5、添加库依赖libobjc.A.dylib



6、添加Target依赖,用于编译objc.A.dylib库,UseObjc不会主动编译objc.A.dylib库



7、关闭Harden Runtime,UseObjc->Build Settings->Enable Hardened Runtime 设置为NO

8、修改objc的target,修改Run Script(markgc),macosx.internal 修改为 macosx

9、修改objc/objc-env/objc-trampolines的target,base sdk和supported platforms都修改为macOS



处理头文件缺失
此时build UseObjc的Target,发现会报头文件找不到的问题,这时候需要我们从”开源库下载“中下载到的所有库中,寻找到所需头文件,举例如下
1、build objc target时找不到sys/reason.h

2、刚刚的下载的开源库中有此reason.h

3、为了快速找到reason.h,直接在此文件夹下”按名称“搜索reason.h

4、搜索到后,我们并没办法直接使用,因为objc target依赖的是sys/reason.h,而不是reason.h
4.1、为此在objc工程下新增Common(名称随意)文件夹

4.2、并在objc target的Header search path下添加Common文件夹,让程序可以寻址到Common文件夹

4.3、Common文件夹下创建sys目录,并将搜索到的reason.h文件拷贝到sys目录下,这样子才能按照sys/reason.h寻址

5、至此,重新运行UseObjc target,找不到sys/reason.h的问题已修复,但是还有其他头文件找不到的问题

整理Macos14.0需要的头文件
| 头文件 | 所属位置 |
| _simple.h | libplatform-libplatform-306.0.1/private/_simple.h |
| Block_private.h | libclosure-libclosure-90/Block_private.h |
| CrashReporterClient.h | Libc-Libc-825.26/include/CrashReporterClient.h |
| objc-shared-cache.h | dyld-dyld-1122.1/include/objc-shared-cache.h |
| kern/restartable.h | xnu-xnu-10002.1.13/osfmk/kern/restartable.h |
| mach-o/dyld_priv.h | dyld-dyld-1122.1/include/mach-o/dyld_priv.h |
| machine/cpu_capabilities.h | xnu-xnu-10002.1.13/osfmk/machine/cpu_capabilities.h |
| os/api.h | Libc-Libc-1583.0.14/os/api.h |
| os/base_private.h | xnu-xnu-10002.1.13/libkern/os/base_private.h |
| os/bsd.h | Libc-Libc-1583.0.14/libdarwin/h/bsd.h |
| os/linker_set.h | Libc-Libc-1583.0.14/os/linker_set.h |
| os/lock_private.h | private/os/lock_private.h |
| os/log_simple_private_impl.h | libplatform-libplatform-306.0.1/private/os/log_simple_private_impl.h |
| os/log_simple_private.h | libplatform-libplatform-306.0.1/private/os/log_simple_private.h |
| os/reason_private.h | xnu-xnu-10002.1.13/libkern/os/reason_private.h |
| os/tsd.h | xnu-xnu-10002.1.13/libsyscall/os/tsd.h |
| os/variant_private.h | Libc-Libc-1583.0.14/os/variant_private.h |
| pthread/tsd_private.h | libpthread-libpthread-519/private/pthread/tsd_private.h |
| sys/reason.h | xnu-xnu-10002.1.13/bsd/sys/reason.h |
| System/machine/cpu_capabilities.h | xnu-xnu-10002.1.13/osfmk/cpu_capabilities.h |
| System/pthread_machdep.h | Libc-Libc-825.26/pthreads/pthread_machdep.h |
| 其他头文件依赖 | 直接注释即可 |
如果懒得操作可直接下载我整理好的头文件:https://onebox.huawei.com/p/8191d42c36fad36c46a2d91d9e343697
处理异常
1、删除lCrashReporterClient和loah库的依赖,objc->Build Settings->other linker flags->删除这两个库

1、有些系统函数我们找不到,需要注释掉此处逻辑,
处理规则:
规则一:如果是if中的一个条件,直接删除,如果是唯一条件,则整个if语句都要注释掉,包括后面的else if/else
规则二:是函数调用中的参数,则整个函数调用都要注释掉
规则三:函数调用为”|“的一个参数,直接删除,如果是唯一参数,则注释整个逻辑
相关处理过程截图:











调试
UseObjc target的main函数中添加NSObject *obj = [NSObject alloc];看一下内存申请过程的逻辑,从下图可以看出alloc方法调用时,进入到了objc_alloc的c方法里面,这个很奇怪,为什么会发生这种事


按照常规逻辑应该有个+(id)alloc的类方法来承接,为什么会这样呢
从下图可以看出,在加载库时,会对部分方法进行重新设置实现,alloc和allocWithZone:都被替换为了objc_alloc和objc_allocWithZone的C方法

更多
更多的逻辑等待大家去探索
new的实现原理/内存分配的方式等
- 点赞
- 收藏
- 关注作者
评论(0)