iOS_objc4-818.2 源码编译调试

学习OC底层,少不了要研究源码,今天就编译调试一下objc4-818.2 源码,探索OC底层。

准备工作

  • mac OS 11.4
  • Xcode 12.4
  • objc4-818.2
objc4-818.2 下载地址

opensource.apple.com/
或者
opensource.apple.com/tarballs/
搜索objc

开始配置

直接编译遇到的问题

16230321954181.jpg

16230324943525.jpg

error: unable to find sdk 'macosx.internal' (in target 'objc-trampolines' from project 'objc') warning: Traditional headermap style is no longer supported; please migrate to using separate headermaps and set 'ALWAYS_SEARCH_USER_PATHS' to NO. (in target 'objc-trampolines' from project 'objc')

解决方法

16230327805521.jpg

  • 系统要求的macOS版本需要处理

选择 target -> objc -> Build Settings -> Base SDK -> 选择 macOS 让系统给你进行匹配

注:需要修改objc和objc-trampolines两个target

16230333240390.jpg
选择 target -> objc -> Build Settings
搜索always 将ALWAYS_SEARCH_USER_PATHS 设置为NO

注:需要修改objc和objc-trampolines两个target

文件查漏补缺

准备好以下资源

16230638082919.jpg

'sys/reason.h' file not found

16230343525131.jpg

  • 大家可以通过 Apple source 在 xnu-7195.101.1/bsd/sys/reason.h 路径自行下载
  • 还可以通过谷歌中输入reason.h site:opensource.apple.com 定向检索

把找到的文件加入到工程里面。例如:

  • 我在根目录创建了一个 OSCommon 文件
  • 创建 sys 文件
  • reason.h 文件加入进去

目前还不行,一定给我们的工程设置文件检索路径

  • 选择 target -> objc -> Build Settings
  • 在工程的 Header Serach Paths 中添加搜索路径 $(SRCROOT)/OSCommon

上面的报错情况处理方式都是和 'sys/reason.h' file not found 一样的解决

文件补漏情况如下:

1.'sys/reason.h' file not found
xnu-7195.101.1/bsd/sys/reason.h 下载

2.'mach-o/dyld_priv.h' file not found
dyld-851.27/include/mach-o/dyld_priv.h 下载

3.'os/lock_private.h' file not found 'os/base_private.h' file not found
libplatform-220.100.1/private/os/lock_private.h 、base_private.h(220.100.1之后版本没有这个文件)

4.'pthread/tsd_private.h' file not found 'pthread/spinlock_private.h' file not found
libpthread-454.100.8/private/pthread/tsd_private.h、spinlock_private.h

5.'System/machine/cpu_capabilities.h' file not found
xnu-7195.101.1/osfmk/machine/cpu_capabilities.h

6.'os/tsd.h' file not found
xnu-7195.101.1/libsyscall/os/tsd.h

7.'System/pthread_machdep.h' file not found
最新版本没有这个文件,下载Libc-825.40.1 源码
Libc-825.40.1/pthreads/pthread_machdep.h

8.'CrashReporterClient.h' file not found
最新版本没有这个文件,下载Libc-825.40 源码
Libc-825.40.1/include/CrashReporterClient.h

9.'os/feature_private.h' file not found
删除#include <os/feature_private.h> // os_feature_enabled_simple()

10.'_simple.h' file not found
libplatform-220.100.1/private/_simple.h

11.'os/linker_set.h' file not found
Libc-1439.100.3/os/linker_set.h

12.'Cambria/Traps.h' file not found
删除掉

#if TARGET_OS_OSX
#include <Cambria/Traps.h>
#include <Cambria/Cambria.h>
#endif
复制代码

13.'kern/restartable.h' file not found
xnu-7195.101.1/osfmk/kern/restartable.h

14.'objc-shared-cache.h' file not found
dyld-851.27/include/objc-shared-cache.h

15.'objc-bp-assist.h' file not found
文件 objc-bp-assist.h 本应在 objc4-818.2 源码 中,但官方没有提供,所以只能在 objc-os.mm 文件中注释该引用!

16.'Block_private.h' file not found
libclosure-79 –> Block_private.h

17.'os/reason_private.h' file not found
xnu-7195.101.1/libkern/os/reason_private.h

18.'os/variant_private.h' file not found
Libc-1439.100.3/os/reason_private.h

缺失的library

library not found for -lCrashReporterClient

  • 选择 target -> objc -> Build Settings
  • Other Linker Flags 中删除 -lCrashReporterClient ( DebugRelease 都删了)

16231317257580.jpg

library not found for -loah

  • 选择 target -> objc -> Build Settings
  • Other Linker Flags 中删除 -loah ( DebugRelease 都删了)

错误处理

文件报错
1.dyld_priv.h 报错

去掉 bridgeos(3.0)

2.lock_private.h报错

去掉bridgeos(4.0)

3.导入CrashReporterClient.h报错

可以通过以下方式解决

  • 需要在 Build Settings -> Preprocessor Macros 中加入:LIBC_NO_LIBCRASHREPORTERCLIENT
4.variant_private.h报错

去掉错误处的bridgeos

5.其他错误
  1. os_feature_enabled_simple()

注释了 feature_private.h 文件之后,某些地方使用的该文件的函数,也将报错
/objc4-818.2/runtime/objc-runtime.mm:451:10: error: use of undeclared identifier ‘os_feature_enabled_simple’
if (!os_feature_enabled_simple(objc4, preoptimizedCaches, true)) {
1 error generated.

对于未经声明的 os_feature_enabled_simple() 函数,只能注释!
/// objc-runtime.mm 文件的 void environ_init(void) 函数中

//        DisablePreoptCaches = true;
//    }
复制代码

2.Mismatch in debug-ness macros
注释掉

Use of undeclared identifier 'oah_is_current_process_translated'
复制代码

删除

#if TARGET_OS_OSX
        if (oah_is_current_process_translated()) {
            kern_return_t ret = objc_thread_get_rip(threads[count], (uint64_t*)&pc);
            if (ret != KERN_SUCCESS) {
                pc = PC_SENTINEL;
            }
        } else {
            pc = _get_pc_for_thread (threads[count]);
        }
#else
复制代码

4.在 objc-runtime.mm 文件的 void environ_init(void) 函数中找不到 dyld_fall_2020_os_versions 、objc4 、preoptimizedCaches 三个宏定义!

我们不妨现在 objc-runtime.mm 文件函数void environ_init(void)的上面声明这几个宏!

5.不被识别的宏定义 dyld_platform_version_

分析错误日志:发现是找不到定义的 dyld_platform_version_macOS_10_13!objc 项目中很多地方都要相关的宏定义 dyld_platform_version_ ,都会报错 use of undeclared identifier!
由于一些文件找不到的缘故,此处不得不使用旧版本的代码来处理,在 dyld_priv.h 文件定义几个相关宏:

#define DYLD_MACOSX_VERSION_10_11 0x000A0B00
#define DYLD_MACOSX_VERSION_10_12 0x000A0C00
#define DYLD_MACOSX_VERSION_10_13 0x000A0D00
#define DYLD_MACOSX_VERSION_10_14 0x000A0E00
复制代码

16230616526169.jpg

6.不匹配的函数
dyld_program_sdk_at_least()
既然 dyld_program_sdk_at_least() 函数不适配,继续使用老版本的判断方法:

/// if (!dyld_program_sdk_at_least(DYLD_MACOSX_VERSION_10_13)) {
if (!(dyld_get_program_sdk_version() >= DYLD_MACOSX_VERSION_10_13)) {

/// if (!dyld_program_sdk_at_least(dyld_platform_version_macOS_10_11)) {
if (!(dyld_get_program_sdk_version() >= DYLD_MACOSX_VERSION_10_11)) {

复制代码

7.NsObject.h

Use of undeclared identifier 'dyld_platform_version_bridgeOS_2_0'
Use of undeclared identifier 'dyld_platform_version_iOS_10_0'
Use of undeclared identifier 'dyld_platform_version_macOS_10_12'
Use of undeclared identifier 'dyld_platform_version_tvOS_10_0'
Use of undeclared identifier 'dyld_platform_version_watchOS_3_0'
复制代码

16231300524346.jpg
注释掉

#define sdkIsAtLeast(x, i, t, w, b)                                    \
    (dyld_program_sdk_at_least(dyld_platform_version_macOS_ ## x)   || \
     dyld_program_sdk_at_least(dyld_platform_version_iOS_ ## i)     || \
     dyld_program_sdk_at_least(dyld_platform_version_tvOS_ ## t)    || \
     dyld_program_sdk_at_least(dyld_platform_version_watchOS_ ## w) || \
     dyld_program_sdk_at_least(dyld_platform_version_bridgeOS_ ## b))
复制代码

修改为

#if TARGET_OS_OSX
#   define DYLD_OS_VERSION(x, i, t, w, b) DYLD_MACOSX_VERSION_##x
#   define sdkVersion() dyld_get_program_sdk_version()

#elif TARGET_OS_IOS
#   define DYLD_OS_VERSION(x, i, t, w, b) DYLD_IOS_VERSION_##i
#   define sdkVersion() dyld_get_program_sdk_version()

#elif TARGET_OS_TV
    // dyld does not currently have distinct constants for tvOS
#   define DYLD_OS_VERSION(x, i, t, w, b) DYLD_IOS_VERSION_##t
#   define sdkVersion() dyld_get_program_sdk_version()

#elif TARGET_OS_BRIDGE
#   if TARGET_OS_WATCH
#       error bridgeOS 1.0 not supported
#   endif
    // fixme don't need bridgeOS versioning yet
#   define DYLD_OS_VERSION(x, i, t, w, b) DYLD_IOS_VERSION_##t
#   define sdkVersion() dyld_get_program_sdk_bridge_os_version()

#elif TARGET_OS_WATCH
#   define DYLD_OS_VERSION(x, i, t, w, b) DYLD_WATCHOS_VERSION_##w
    // watchOS has its own API for compatibility reasons
#   define sdkVersion() dyld_get_program_sdk_watch_os_version()

#else
#   error unknown OS
#endif

#define sdkIsOlderThan(x, i, t, w, b)                           \
            (sdkVersion() < DYLD_OS_VERSION(x, i, t, w, b))
#define sdkIsAtLeast(x, i, t, w, b)                             \
            (sdkVersion() >= DYLD_OS_VERSION(x, i, t, w, b))

// Allow bare 0 to be used in DYLD_OS_VERSION() and sdkIsOlderThan()
#define DYLD_MACOSX_VERSION_0 0
#define DYLD_IOS_VERSION_0 0
#define DYLD_TVOS_VERSION_0 0
#define DYLD_WATCHOS_VERSION_0 0
#define DYLD_BRIDGEOS_VERSION_0 0
复制代码

8.objc-runtime-new.mm报错

'_static_assert' declared as an array with a negative size
复制代码

注释掉

libobjc.order错误

can't open order file: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/AppleInternal/OrderFiles/libobjc.order
复制代码
  • 选择 target -> objc -> Build Settings
  • 在工程的 Order File 中添加搜索路径 $(SRCROOT)/libobjc.order

16231315171808.jpg

Xcode 脚本编译问题
SDK "macosx.internal" cannot be located.
sh -c '/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -sdk macosx.internal -find clang++ 2> /dev/null' failed with exit code 16384: (null) (errno=No such file or directory)
unable to find utility "clang++", not a developer tool or in PATH
复制代码
  • 选择 target -> objc -> Build Phases -> Run Script(markgc)
  • 把脚本文本 macosx.internal 改成 macosx

长出一口气,编译成功了?

objc 编译调试

  • 新建一个 Target : Test

File -> New->Target...->macOS->Applation->Command Line Tool

16231332535561.jpg

  • 绑定二进制依赖关系

16231334045078.jpg

  • 运行代码进入源码,大家可以自由编译调试咯!
调试遇到的问题

16231345585899.jpg

打了断点以后发现无法断到断点处,这里我们进行一下处理,在TestBuild PhasesComplie Sources中,把main.m放到第一位

16231345987675.jpg

参考:
juejin.cn/post/684490…
www.jianshu.com/p/881a70537…
blog.csdn.net/cairo123/ar…

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享