内容简介:这篇文章会手把手教你如何用 VirtualBox 进行 macOS 内核的源码级调试。虽然这些步骤都是在 VirtualBox上进行的,但在 VMWare 上也是通用的,甚至更简单。如果你还没在 VirtualBox 上安装 macOS 镜像,你可以复用 VMWare 的 vmdk,也可以装个新的。重新安装系统需要 ISO 镜像,下面的命令可以将从如果你用了桥接,可以跳过这部分。
这篇文章会手把手教你如何用 VirtualBox 进行 macOS 内核的源码级调试。虽然这些步骤都是在 VirtualBox上进行的,但在 VMWare 上也是通用的,甚至更简单。
安装 VirtualBox 和 Sierra/High Sierra
如果你还没在 VirtualBox 上安装 macOS 镜像,你可以复用 VMWare 的 vmdk,也可以装个新的。重新安装系统需要 ISO 镜像,下面的命令可以将从 Mac app store 下载的 Sierra 转成 ISO。
macOS Sierra
$ export MAC_OS_IMG_DIR=/Applications/Install\ macOS\ Sierra.app $ hdiutil attach "$MAC_OS_IMG_DIR/Contents/SharedSupport/InstallESD.dmg" -noverify -nobrowse -mountpoint /Volumes/installesd $ hdiutil create -o /tmp/Sierra -size 8g -type SPARSE -layout SPUD -fs HFS+J $ hdiutil attach /tmp/Sierra.sparseimage -noverify -nobrowse -mountpoint /Volumes/install $ asr restore -source /Volumes/installesd/BaseSystem.dmg -target /Volumes/install -noprompt -noverify -erase $ rm /Volumes/OS\ X\ Base\ System/System/Installation/Packages $ cp -rp /Volumes/installesd/Packages /Volumes/OS\ X\ Base\ System/System/Installation/ $ cp -rp /Volumes/installesd/BaseSystem.dmg /Volumes/OS\ X\ Base\ System/BaseSystem.dmg $ cp -rp /Volumes/installesd/BaseSystem.chunklist /Volumes/OS\ X\ Base\ System/BaseSystem.chunklist $ hdiutil detach /Volumes/installesd $ hdiutil detach /Volumes/OS\ X\ Base\ System/ $ hdiutil resize -sectors min /tmp/Sierra.sparseimage $ hdiutil convert /tmp/Sierra.sparseimage -format UDTO -o /tmp/Sierra $ rm /tmp/Sierra.sparseimage $ mv /tmp/Sierra.cdr ~/Sierra.iso
macOS High Sierra
$ export MAC_OS_IMG_DIR=/Applications/Install\ macOS\ High\ Sierra.app $ hdiutil create -o /tmp/HighSierra.cdr -size 7316m -layout SPUD -fs HFS+J $ hdiutil attach /tmp/HighSierra.cdr.dmg -noverify -nobrowse -mountpoint /Volumes/install_build $ asr restore -source "$MAC_OS_IMG_DIR/Contents/SharedSupport/BaseSystem.dmg" -target /Volumes/install_build -noprompt -noverify -erase # 如果我们不拷贝安装文件,那么安装程序会从网络上下载镜像安装,如果我们拷贝镜像进入,安装时候会使用我们拷贝进入的安装文件,国内貌似只能本地安装 $ cp -rp "$MAC_OS_IMG_DIR/Contents/SharedSupport" /Volumes/OS\ X\ Base\ System/Install\ macOS\ High\ Sierra.app/Contents/ $ hdiutil detach /Volumes/OS\ X\ Base\ System $ hdiutil convert /tmp/HighSierra.cdr.dmg -format UDTO -o /tmp/HighSierra.iso $ mv /tmp/HighSierra.iso.cdr ~/HighSierra.iso $ rm -rf /tmp/HighSierra.cdr.dmg
网络设置
如果你用了桥接,可以跳过这部分。
如果用的是 NAT,需要为 KDP 开启端口转发。点击“网络”,选择“高级” -> “端口转发”,将 localhost 41139/UDP 转发到虚拟机的 41139/UDP,就能够访问到虚拟机的 41139 端口了。
显存调整到最大
取消软盘
内存设置
内存至少4GB
CPU设置
CPU至少2颗核心
3D加速
开启3D加速,提高性能
完成这一步,就可以安装系统了。
点击磁盘工具
显示出的界面如下
选择下面的"VBOX HARDDISK Media",然后选择"抹掉",如下图:
之后关闭窗口,返回上层窗口,选择" 重新安装 macOS "。进入真正系统安装流程。
安装完成后,从虚拟机中移除安装镜像
重启之后进入如下界面
我们需要安装启动引导
上述执行的命令如下:
fs1: cd "macOS Install Data" cd "Locked Files" cd "Boot Files" boot.efi
稍后会出现如下界面:
等待完成操作,就完成了引导部分的安装。重启之后,就是常规操作了。
安装 XCode
在你的主机上安装 XCode,通过 App store 安装最简单。 可以直接打开 XCode,也可以执行 sudo xcodebuild -license accept
接受 XCode license。
安装内核调试组件(KDK)
根据我们要调试的 macOS 版本从 Apple 开发者中心安装 KDK ,这里我的是10.12 build 16A323.
KDK 的安装目录是 /Library/Developer/KDKs
,提供的内核版本、符号、内核扩展都有 RELEASE、DEVELOPMENT、DEBUG 三种版本。不同之处在于 DEVELOPMENT 和 DEBUG 版比 RELEASE 版多了些断言和错误检查,DEBUG 版的最丰富。
注意:被调试的系统不需要安装 KDK。
修改 nvram boot-args
为了能够调试虚拟机,需要设置虚拟机上 nvram 中的 debug 项。除了 debug 的值外其他值也能被我们所用。下面是一些因垂斯挺的选项:
- -v:以 verbose 模式启动系统。
- kcsuffix:填写后缀以指定启动的内核。
- pmuflags:貌似大家都推荐把这项值设为1。然而 Apple’s Kernel Programming Guide 已经明确指出管理电源的看门狗定时器“只在台式机、笔记本的 G4 版本和台式机的 G5 版本及之前有作用”,其他的看门狗定时器“只在 OS X Server 中启用”。所以,虽然设置了也不影响,但这个选项真没什么卵用。
- debug:允许远程内核调试。 Apple docs 里有列出可用的标志。我常用的是
DB_LOG_PI_SCRN | DB_ARP | DB_NMI
。另外,control + option + command + shift + escape
可以触发不可屏蔽中断(NMI),继而引发调试器中断,超级方便。这对组合键跟 host key 的组合键冲突的时候用起来很难受,所以我把 host key 重新绑定成command + right
了。
修改 nvram
在 VMware 里,可用这样修改 nvram:
$ sudo nvram boot-args="-v debug=0x144"
在 virtualbox 里没那么简单,因为一重启修改的值就没了。还好从 virtualbox 手册的 3.13.2 看到了希望:
不能在运行的虚拟机内部操作 EFI 变量了(如:在Mac OS X 虚拟机里运行 nvram 来设置“boot-args”不管用了)。不过,可以通过给虚拟机发送附加数据”VBoxInternal2/EfiBootArgs” 来设置“boot-args”。…
因此,我们需要关闭虚拟机,在主机上运行命令:
$ VBoxManage list vms # 列出下条命令使用的 UUID "macOS 10.12.0" {9ad936f8-9360-44a6-ba3e-c4d92b4243e8} $ VBoxManage setextradata 9ad936f8-9360-44a6-ba3e-c4d92b4243e8 VBoxInternal2/EfiBootArgs "-v debug=0x144"
如果想个性化定制部分信息,可以执行如下命令修改参数,主要是屏幕,CPU等的属性信息, 不是必须 :
$ VBoxManage list vms # 列出下条命令使用的 UUID "macOS High Sierra" {c509e9db-80ac-4a8e-bf57-bdd6d1b7b741} $ VBoxManage modifyvm c509e9db-80ac-4a8e-bf57-bdd6d1b7b741 --cpuidset 00000001 000306a9 04100800 7fbae3ff bfebfbff $ VBoxManage setextradata c509e9db-80ac-4a8e-bf57-bdd6d1b7b741 "VBoxInternal/Devices/efi/0/Config/DmiSystemProduct" "MacBookPro11,3" $ VBoxManage setextradata c509e9db-80ac-4a8e-bf57-bdd6d1b7b741 "VBoxInternal/Devices/efi/0/Config/DmiSystemVersion" "1.0" $ VBoxManage setextradata c509e9db-80ac-4a8e-bf57-bdd6d1b7b741 "VBoxInternal/Devices/efi/0/Config/DmiBoardProduct" "Mac-2BD1B31983FE1663" $ VBoxManage setextradata c509e9db-80ac-4a8e-bf57-bdd6d1b7b741 "VBoxInternal/Devices/smc/0/Config/DeviceKey" "ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" $ VBoxManage setextradata c509e9db-80ac-4a8e-bf57-bdd6d1b7b741 "VBoxInternal/Devices/smc/0/Config/GetKeyFromRealSMC" 1
交换内核
前面我提到可以指定 kcsuffix
选项以调试不同版本的内核。内核文件在虚拟机的 /System/Library/Kernels
目录,然而这个目录受“系统完整性保护”机制保护(SIP)。所以要想使用 KDK 或者自己编译的内核,必须启动进入 recovery,把目标内核拷进 /System/Library/Kernels
目录,使 kextcache 失效,然后重新启动。
启动进入 recovery
在 VMware 里, cmd + R
就能进入 recovery 模式。virtualbox 要多几步。
启动虚拟机时,按住 F12
,然后选择 Boot Manager -> EFI Internal Shell
,就会看到 EFI Shell 的欢迎界面。输入命令进入 recovery:
FS2:\com.apple.recovery.boot\boot.efi
进入 recovery 的界面,打开终端,操作目标内核,并将 kextcache 设置为无效。
# mv /path/to/kernels/kernel.development /System/Library/Kernels # kextcache -invalidate /Volumes/Macintosh\ HD # reboot
如果需要禁用 SIP,在重启之前执行:
# csrutil disable Successfully disabled System Integrity Protection. Please restart the machine for the changes to take effect.
源码调试
下载要调试的版本的 XNU 源码。调试时,LLDB 会去 /Library/Caches/com.apple.xbs/Sources/xnu/xnu-...
目录寻找内核源码,所以可以把下载的源码放这个目录,也可以建一个符号链接指向源码目录。还有个方法是 设置 LLDB 的 target.source-map
变量:
lldb> settings set target.source-map /Library/Caches/com.apple.xbs/Sources/xnu/xnu-3789.1.32 /Users/kedy/Downloads/xnu-3789.1.32
早一些的 macOS 版本比如 Yosemite 就只能把源码放在 /SourceCache/xnu/
里。
安装 LLDB
终于到调试器了。下面会举例用的是 RELEASE 内核。
为了在 Sierra KDK 里用 XNU LLDB 宏,执行 pip install macholib
安装 macholib
模块。粘贴执行加载内核文件时提示我们要执行的命令。(如下)
触发 NMI 后(或者等待设置了 DB_HALT
的调试器暂停启动进程时),执行 kdp-remote <ip>
连接到调试进程(若使用的是 NAT 端口转发,ip 是 localhost)。(如下)
$ lldb /Library/Developer/KDKs/KDK_10.11.2_15C50.kdk/System/Library/Kernels/kernel (lldb) target create "/Library/Developer/KDKs/KDK_10.11.2_15C50.kdk/System/Library/Kernels/kernel" warning: 'kernel' contains a debug script. To run this script in this debug session: command script import "/Library/Developer/KDKs/KDK_10.11.2_15C50.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/kernel.py" To run all discovered debug scripts in this session: settings set target.load-script-from-symbol-file true Current executable set to '/Library/Developer/KDKs/KDK_10.11.2_15C50.kdk/System/Library/Kernels/kernel' (x86_64). (lldb) command script import "/Library/Developer/KDKs/KDK_10.11.2_15C50.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/kernel.py" Loading kernel debugging from /Library/Developer/KDKs/KDK_10.11.2_15C50.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/kernel.py LLDB version lldb-370.0.40 Swift-3.1 settings set target.process.python-os-plugin-path "/Library/Developer/KDKs/KDK_10.11.2_15C50.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/lldbmacros/core/operating_system.py" settings set target.trap-handler-names hndl_allintrs hndl_alltraps trap_from_kernel hndl_double_fault hndl_machine_check _fleh_prefabt _ExceptionVectorsBase _ExceptionVectorsTable _fleh_undef _fleh_dataabt _fleh_irq _fleh_decirq _fleh_fiq_generic _fleh_dec command script import "/Library/Developer/KDKs/KDK_10.11.2_15C50.kdk/System/Library/Kernels/kernel.dSYM/Contents/Resources/DWARF/../Python/lldbmacros/xnu.py" xnu debug macros loaded successfully. Run showlldbtypesummaries to enable type summaries. (lldb) kdp-remote 192.168.149.184 Version: Darwin Kernel Version 15.2.0: Fri Nov 13 19:56:56 PST 2015; root:xnu-3248.20.55~2/RELEASE_X86_64; UUID=17EA3101-D2E4-31BF-BDA9-931F51049F93; stext=0xffffff8007a00000 Kernel UUID: 17EA3101-D2E4-31BF-BDA9-931F51049F93 Load Address: 0xffffff8007a00000 Kernel slid 0x7800000 in memory. Loaded kernel file /Library/Developer/KDKs/KDK_10.11.2_15C50.kdk/System/Library/Kernels/kernel Target arch: x86_64 Instantiating threads completely from saved state in memory. Loading 82 kext modules warning: Can't find binary/dSYM for com.apple.kec.corecrypto (491718F5-B509-31DC-92B5-6BAC95E3F494) .warning: Can't find binary/dSYM for com.apple.kec.pthread (0888BA0A-49EE-394A-AEB1-1E5C6838A1F2) (omitted...) . done. kernel was compiled with optimization - stepping may behave oddly; variables may not be available. Process 1 stopped * thread #2, name = '0xffffff800db8b000', queue = '0x0', stop reason = signal SIGSTOP frame #0: 0xffffff8007bd655e kernel`Debugger(message=<unavailable>) at model_dep.c:1020 [opt] 1017 1018 doprnt_hide_pointers = old_doprnt_hide_pointers; 1019 __asm__("int3"); -> 1020 hw_atomic_sub(&debug_mode, 1); 1021 } 1022 1023 char * (lldb)
瞧,macOS 内核源码调试这就开始了!
参考链接
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Rationality for Mortals
Gerd Gigerenzer / Oxford University Press, USA / 2008-05-02 / USD 65.00
Gerd Gigerenzer's influential work examines the rationality of individuals not from the perspective of logic or probability, but from the point of view of adaptation to the real world of human behavio......一起来看看 《Rationality for Mortals》 这本书的介绍吧!
JS 压缩/解压工具
在线压缩/解压 JS 代码
UNIX 时间戳转换
UNIX 时间戳转换