编译调试objc4-841.13源码

编译调试objc4-841.13源码
Photo by Ryland Dean / Unsplash

从苹果开源网站https://opensource.apple.com/releases/下载最新源码,这里是objc4-841.13版本,各个版本需要处理的问题差别不是很大。编译环境如下

  • 系统: macOS 12.4 (21F79)
  • 工具: Xcode 13.4.1 (13F100)
  • 源码: objc4-841.13

下载好代码解压,打开后编译objc Target。下面按照错误出现的顺序,依次解决。

1、unable to find sdk 'macosx.internal'

分别选objc和objc-trampolines两个target,然后把Base SDK选为macOS。

2、'sys/reason.h' file not found

头文件缺失,只要找到对应的头文件添加到工程中就可以解决,首先在工程的根目录创建include文件夹,然后在工程的Build Settings->Header Search Paths添加$(SRCROOT)/include,并且把后面选项设置为recursive。

因为头文件是<sys/reason.h>,所以还要在include文件夹中创建sys文件夹。然后在xnu-8020.121.3的/bsd/sys目录下找到reason.h,复制到新建的/include/sys目录。

3、'mach-o/dyld_priv.h' file not found

需要先在include文件夹下面创建mach-o文件夹,然后在dyld-957的/include/mach-o目录下找到dyld_priv.h,复制到/include/mach-o目录下。

4、'os/lock_private.h' file not found

需要先在include文件夹下面创建os文件夹,然后在libplatform-273.100.5的/private/os目录下找到lock_private.h,复制到/include/os目录下。

5、Expected ','

删除文件中所有的bridgeos(3.0),带前面','一并删除,搜索替换即可,如下图

后面还会出现bridgeos相关的报错,一并删除即可。

6、'os/base_private.h' file not found

libplatform-220.100.1的/private/os目录下找到base_private.h,复制到/include/os目录下。

7、'pthread/tsd_private.h' file not found

需要先在include文件夹下面创建pthread文件夹,然后在libpthread-486.100.11的/private/pthread目录下找到tsd_private.h,复制到/include/pthread目录下。

8、'System/machine/cpu_capabilities.h' file not found

需要在include文件夹下创建System文件夹,然后再System文件夹下创建machine文件夹,然后在xnu-8020.121.3的/osfmk/machine目录下找到cpu_capabilities.h,复制到/include/System/machin目录下。

9、'os/tsd.h' file not found

在xnu-8020.121.3的/libsyscall/os下找到tsd.h文件,复制到/include/os目录下。

10、'pthread/spinlock_private.h' file not found

在libpthread-486.100.11的/private/pthread下找到spinlock_private.h,复制到/include/pthread目录下。

11、'os/feature_private.h' file not found

apple_internal_sdk的/usr/include/os目录中找到feature_private.h文件,复制到/include/os目录下。

12、'os/variant_private.h' file not found

Libc-1507.100.9 的/os目录下找到variant_private.h文件,复制到/include/os目录下。

13、'System/pthread_machdep.h' file not found

Libc-825.26的/pthreads目录下找到pthread_machdep.h,复制到/include/System目录下。

14、'CrashReporterClient.h' file not found

1.从Libc-825.26的/include目录下找到CrashReporterClient.h文件,复制到objc工程中自己创建的include目录下。

2.复制完成还是会报错

需要在报错文件中添加#define LIBC_NO_LIBCRASHREPORTERCLIENT

3.在Build Settings->Linking->Other Linker Flags里删掉"-lCrashReporterClient",因为后面运行的时候会报错ld: library not found for -lCrashReporterClient

15、Typedef redefinition with different types ('int' vs 'volatile OSSpinLock' (aka 'volatile int')) 等,

上面pthread_machdep.h中的四个报错,注释掉即可。

16、'os/bsd.h' file not found

注释掉即可,然后注释is_root_ramdisk方法和调用此方法的地方。

17、'os/reason_private.h' file not found

从xnu-8020.121.3的/libkern/os的目录下找到reason_private.h,复制到/include/os目录下。

18、'objc-shared-cache.h' file not found

从dyld-957的/include目录中找到objc-shared-cache.h,复制到objc工程的include目录下。

19、Use of undeclared identifier 'dyld_platform_version_*

注释或者删除即可。

20、'_simple.h' file not found

从libplatform-220.100.1的/private目录找到_simple.h,复制到objc工程的include目录。

21、'os/linker_set.h' file not found

从xnu-8020.121.3的/bsd/sys目录找到linker_set.h,复制到/include/os目录。

22、'Block_private.h' file not found

libclosure-79.1根目录找到Block_private.h,复制到objc工程的include目录。

23、'Cambria/Traps.h' file not found和'Cambria/Cambria.h' file not found

注释掉。第二个图片除了红色框住的,都注释掉。就算头文件正常导入,也会提示以下错误

24、'kern/restartable.h' file not found

在xnu-8020.121.3的/osfmk/kern找到restartable.h,然后在objc工程的include目录下创建kern文件夹,再把找到的文件复制进去。

25、ld: library not found for -loah

在Build Settings -> Linking -> Other Linker Flags里删掉-loah

26、'_static_assert' declared as an array with a negative size

注释掉。

27、SDK "macosx.internal" cannot be located.

选择 target -> objc -> Build Phases -> Run Script(markgc),把脚本文本 macosx.internal 改成 macosx。

到这一步,应该就可以正常地编译了。


调试部分,需新建个target->macOS->Command Line Tool

然后在新建的target-> Frameworks and Libraries -> 添加编译出来的libobjc.A.dylib

然后在新建的target->Build Settings->Enable hardened runtime设置为NO

在新建的target里面随便新建个类文件,并且在main文件中初始化个对象。然后在objc的alloc方法打断点

并且在main文件打断点

运行,如果alloc没有断住,需要检查Enable hardened runtime是否设置为NO,如果第二个没断住,需要在Compile Sources中把main文件移动到对上面。


按照以上步骤处理完成,就会得到一份可以编译调试的objc代码。

Read more

Category和关联对象

Category和关联对象

Category也就是分类,可以在没有类定义的情况下为现有类添加方法、属性、协议,众所周知是不能增加成员变量的,但是是可以通过关联对象给类增加的。 struct category_t { const char *name; classref_t cls; WrappedPtr instanceMethods; WrappedPtr classMethods; struct protocol_list_t *protocols; struct property_list_t *instanceProperties; // Fields below this point are not always present on disk. struct property_list_t *_classProperties; method_list_t *methodsF

By LEMON
内存管理-AutoreleasePool

内存管理-AutoreleasePool

AutoreleasePool(自动释放池)是Objective-C中的一种内存自动回收机制,它可以延迟加入AutoreleasePool中的变量release的时机。 @autoreleasepool { ... }可以通过 clang -rewrite-objc 命令转成C++代码如下 /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; } 然后可以从objc源码中找到__AtAutoreleasePool的定义 struct __AtAutoreleasePool { __AtAutoreleasePool() { atautoreleasepoolobj = objc_autoreleasePoolPush(); } ~__AtAutoreleasePool() { objc_autoreleasePoolPop(atautoreleasepoolobj); } void * atautoreleasepoolobj; }; 这个结构体先

By LEMON
如何为macOS应用开发插件

如何为macOS应用开发插件

本文章只用于学习和交流,转载请注明出处。 玩过越狱手机的应该都了解,iOS的越狱插件是可以为系统或者应用添加一些特色的功能的。越狱插件的开发,已经有完整的工具链,并且插件的加载运行Substrate框架已经为我们做好。 更改应用的功能实现有两种方法,一种是通过反编译工具更改汇编代码后生成新的可执行文件。另一种是写一个动态库,然后注入到可执行文件。第一种适合简单的逻辑修改,毕竟用汇编实现功能是需要很大的工作量的。 第二种要怎么注入呢?了解Mach-O 二进制文件的应该知道,Mach-O 二进制文件Load Commands中的 LC_LOAD_DYLIB 标头告诉 macOS在执行期间要加载哪些动态库 (dylib)。所以我们只需要在二进制文件中添加一条LC_LOAD_DYLIB就可以。而insert_dylib工具已经为我们实现了添加的功能。所以现在唯一需要考虑的就是插件如何开发。 废话不多说,现在就以mac版的迅雷为例开发一款属于我们自己的插件。首先下载最新版本的迅雷(版本5.0.2)。然后用Xcode新建一个macOS下的Framework,如下 新建完目录结构如下,如果

By LEMON
深入分析objc_msgSend尾调用优化

深入分析objc_msgSend尾调用优化

无意间看到了这篇文章 iOS objc_msgSend尾调用优化详解,讲的是在Release模式下,当某函数的最后一项操作是调用另外一个函数,编译器会生成调转至另一函数所需的指令码,而且不会向调用堆栈中推入新的“栈帧”(frame stack),以实现栈帧复用。 栈帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等等。所以在每一次函数调用之前,需要保存下执行的环境,以确保正常返回到调用位置。下面是- (void)viewDidLoad方法的汇编代码 可以看出在调用[super viewDidLoad]之前,先申请栈空间,然后保存x29和x30寄存器的值,调用结束后恢复寄存器的值,然后平栈。x29寄存器也就是fp寄存器,保存栈底的地址。x30寄存器也就是lr寄存器,保存返回地址。那栈帧复用又是怎么实现的呢?本着知其然知其所以然的精神,深入研究下。用下文章中的例子 - (NSInteger)func1:(NSInteger)num{ if (num >= 2000000) { return num; } return

By LEMON
京ICP备15024336号-4