//
xiaoaoaode
Published on 2024-12-29 / 18 Visits
0

DevEco 鸿蒙模拟器 在 MacOS 15.2上启动崩溃的临时解决方案

省流

该Patch仅限DevEco Studio这一个版本的包

DevEco Studio 5.0.1 Release
Build #DS-233.14475.28.36.505310
构建版本:5.0.5.310, built on December 11, 2024
#!/bin/sh
cp Emulator.test Emulator.test.bak
echo -n "3B0000143A0000142A000014FFC300D1FD7B02A9FD830091A0831FF8E10B00F9E20700F9E80B40F9E80300F9E90340F9283940F908ED6492283900F9A0835FF8E10B40F9E20740F957A16A94FD7B42A9FFC30091C0035FD6" | xxd -r -p | dd of=Emulator.test bs=1 seek=$((0xCD90)) conv=notrunc
echo -n "C068F197" | xxd -r -p | dd of=Emulator.test bs=1 seek=$((0x3B2A9C)) conv=notrunc
xml_content='<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.hypervisor</key>
    <true/>
</dict>
</plist>'
echo "$xml_content" > /tmp/Emulator_entitlements.xml
sudo codesign -s - --entitlements /tmp/Emulator_entitlements.xml --force Emulator.test
rm /tmp/Emulator_entitlements.xml

参考:

Failure with macOS 15.2 on ARM64: Property 'host-arm-cpu.sme' not found (#2721) · 议题 · QEMU / QEMU · GitLab

qemu: disable SME for Apple Silicon · utmapp/UTM@acbf2ba

Use Apple silicon images on CI. by colinrtwhite · Pull Request #1793 · cashapp/redwood

详细分析

首先,分析可知鸿蒙的模拟器使用了qemu

启动崩溃之后,使用breakpad(google/breakpad: Mirror of Google Breakpad project) dump出详细的堆栈信息

注意breakpad最好使用depot获取软件源进行编译的方法,以方便在Mac下编译dump_syms工具,获取Emulator的调试信息

经过分析发现在如下调用逻辑中出现了Crash

11  Emulator!_error_handle_fatal + 0xec
12  Emulator!_error_propagate + 0x2c
13  Emulator!_error_propagator_cleanup + 0x20
14  Emulator!_glib_auto_cleanup_ErrorPropagator + 0x14
15  Emulator!_object_property_set + 0x140
16  Emulator!_object_property_set_qobject + 0x38
17  Emulator!_object_property_set_bool + 0x98
18  Emulator!_qdev_realize + 0x110
19  Emulator!_machvirt_init + 0x820
20  Emulator!_machine_run_board_init + 0x418
21  Emulator!_qemu_init_board + 0x3c
22  Emulator!_qmp_x_exit_preconfig + 0x48
23  Emulator!_qemu_init + 0x2128
24  Emulator!_RunQemuMain + 0x28
25  Emulator!EnterQemuMainLoop(int, char**) + 0x34

看不出太多的东西,搜索MacOS 15.2和qemu相关问题发现了这个可能的原因

Failure with macOS 15.2 on ARM64: Property 'host-arm-cpu.sme' not found (#2721) · 议题 · QEMU / QEMU · GitLab

但是在日志里没看出同款保存信息,不过还是先尝试打补丁

分析知这个版本的Emulator使用的是qemu7.1.0,所以拷贝源代码先进行编译

git clone --depth=1 https://github.com/qemu/qemu -b v7.1.0
cd qemu
mkdir build
cd build
../configure --target-list=aarch64-softmmu --enable-debug #尽量减少优化,使得函数尽可能多
make

构造一个如下类似的函数插入hvf_arm_get_host_cpu_features源码的合适位置编译

static void __attribute__ ((noinline)) patch (ARMISARegisters* dst, ARMISARegisters*src, size_t size)
{
    src->id_aa64pfr1 &= ~R_ID_AA64PFR1_SME_MASK;
    *dst = *src;
}

在反编译器里获取到一个可能的汇编,修改适配Emulator里的hvf_arm_get_host_cpu_features

SUB             SP, SP, #0x30
STP             X29, X30, [SP,#32]
ADD             X29, SP, #0x20
STUR            X0, [X29,#-8]
STR             X1, [SP,#16]
STR             X2, [SP,#8]
LDR             X8, [SP,#16]
STR             X8, [SP]
LDR             X9, [SP]
LDR             X8, [X9,#0x70]
AND             X8, X8, #0xFFFFFFFFF0FFFFFF
STR             X8, [X9,#0x70]
LDUR            X0, [X29,#-8]
LDR             X1, [SP,#16]
LDR             X2, [SP,#8]
BL              _memcpy
LDP             X29, X30, [SP,#32]
ADD             SP, SP, #0x30
RET

选择一个“看起来很空闲”的位置,将汇编打进去

我选择的是assert_hvf_ok这个函数,它的有些输出部分的代码对Emulator来说不是完全必要的

修改assert_hvf_ok函数的位置从0x10000CD90开始,dump下的16进制机器码如下

3B0000143A0000142A000014FFC300D1FD7B02A9FD830091A0831FF8E10B00F9E20700F9E80B40F9E80300F9E90340F9283940F908ED6492283900F9A0835FF8E10B40F9E20740F957A16A94FD7B42A9FFC30091C0035FD6

然后在hvf_arm_get_host_cpu_features,发现源码的这个部分代码

ahcf->isar = host_isar;

被编译器改写为了memcpy,所以替换此处的bl跳转的函数到我的patch函数位置即可

修改hvf_arm_get_host_cpu_features函数的位置从0x1003B2A9C开始,dump下的16进制机器码如下

C068F197

Patch好之后,一定要注意在重签名的时候添加一些hypervisor相关的东西,否则qemu在调用相关api的时候回报错HV_UNSUPPORTED(assert_hvf_ok这个函数打印出的日志里可能存在