You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM64 iOS Release版二进制中无unwind信息的浮点函数如何展开?

ARM64 iOS Release 二进制浮点函数的栈展开方案

针对你遇到的这个ARM64 iOS Release版二进制函数——无__unwind_info/__eh_frame展开信息、序言涉及浮点寄存器保存无法使用紧凑展开但兼容DWARF格式的情况,可以通过以下几种方式完成栈展开:

一、手动解析函数序言完成栈展开

首先拆解给定的函数序言指令,明确栈帧布局和寄存器保存规则:

stp d15, d14, [sp,#-160]!  // 预分配160字节栈空间,同时保存d14、d15到栈顶(sp_old - 160)
stp d13, d12, [sp,#16]     // 保存d12、d13到 sp + 16(即sp_old - 144)
stp d11, d10, [sp,#32]     // 保存d10、d11到 sp + 32(即sp_old - 128)
stp d9, d8, [sp,#48]       // 保存d8、d9到 sp + 48(即sp_old - 112)
stp x28, x27, [sp,#64]     // 保存x27、x28到 sp + 64(即sp_old - 96)
stp x26, x25, [sp,#80]     // 保存x25、x26到 sp + 80(即sp_old - 80)
stp x24, x23, [sp,#96]     // 保存x23、x24到 sp + 96(即sp_old - 64)
stp x22, x21, [sp,#112]    // 保存x21、x22到 sp + 112(即sp_old - 48)
stp x20, x19, [sp,#128]    // 保存x19、x20到 sp + 128(即sp_old - 32)
stp x29, x30, [sp,#144]    // 保存x29(旧帧指针)、x30(返回地址)到 sp + 144(即sp_old - 16)
add x29, sp, #0x90         // 将新帧指针x29设置为 sp + 0x90(即sp_old - 16,刚好是旧x29的保存位置)
sub sp, sp, #0x190         // 额外分配400字节局部变量空间,总栈帧大小为160+400=560字节

基于上述分析,手动展开步骤如下:

  • 恢复上一级帧指针(旧x29):直接读取当前x29指向的内存值,即 *(uint64_t*)x29
  • 恢复返回地址(旧x30):读取当前x29+8位置的内存值,即 *(uint64_t*)(x29 + 8)
  • 恢复调用前的栈指针(sp_old):当前sp加上总栈帧大小560,即 sp + 0x230(0x160+0x190=0x230)
  • 若需要恢复浮点寄存器,从预分配的栈空间按对应偏移读取即可,比如d8保存在 sp + 48 位置,d9在 sp + 56 位置,以此类推。

二、借助LLDB工具实现辅助/自动展开

LLDB能够解析符合DWARF规则的函数序言,自动推导栈展开信息:

  1. 用LLDB加载目标二进制,在目标函数入口设置断点:breakpoint set -n <函数名>
  2. 断点命中后,直接执行 bt(或thread backtrace)命令,LLDB会自动解析序言的栈操作,完成栈展开。
  3. 若默认自动展开失效,可手动操作:
    • 执行 p/x *(uint64_t*)$x29 得到上一级帧指针
    • 执行 p/x *(uint64_t*)($x29 + 8) 得到上一级返回地址
    • 手动设置寄存器:register write x29 <旧x29值>、register write sp $sp + 0x230,再执行bt即可展开上一级栈帧。

三、手动构造DWARF CFI信息(长期分析场景)

如果需要让调试工具永久识别该函数的展开规则,可以手动构造DWARF调用帧信息(CFI)并注入到二进制中:

.cfi_startproc
.cfi_def_cfa sp, 0          // 调用前的CFA(调用帧地址)为sp
.cfi_offset x29, -16        // 旧x29保存在sp_old -16位置
.cfi_offset x30, -8         // 旧x30保存在sp_old -8位置
// 浮点寄存器偏移定义
.cfi_offset d8, -112
.cfi_offset d9, -104
.cfi_offset d10, -128
.cfi_offset d11, -120
.cfi_offset d12, -144
.cfi_offset d13, -136
.cfi_offset d14, -160
.cfi_offset d15, -152
.cfi_def_cfa_offset 560     // 总栈帧大小560字节
.cfi_endproc

将这段CFI信息嵌入到二进制的__eh_frame段,或通过调试符号注入工具关联到目标函数,后续调试工具即可自动识别展开规则。

内容的提问来源于stack exchange,提问作者Seva Alekseyev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 18:40:20