在之前的 《Flutter 又双叒叕可以在 iOS 26 的真机上 hotload》 和 《Flutter 在 iOS 真机 Debug 运行出现 Timed out *** to update》 我们聊过,由于 iOS 26 开始,Apple 正式禁止了 Debug 时 mprotect 的 RX 权限,导致了 Flutter 在 Debug 运行到 iOS 26 真机时会有 mprotect failed: Permission denied 的问题 。

在 iOS 上 Dart 不管是 JIT 运行还是进行 hotload 的时候,都需要涉及代码在内存从 RW 变成 RWX 的调整,

而为了快速解决这一问题,Flutter 官方之前临时实现了一个过度方案:

  • 让 Flutter 应用在需要执行 JIT 新代码时,“暂停下来”(断点),主动通知旁边的调试器,让调试器利用它的特权来帮忙把代码设置为“可执行”,然后再继续运行
  • 通过「双地址映射」让两个地址指向一个内存,一个写入,一个执行,然后利用 NOTIFY_DEBUGGER_ABOUT_RX_PAGES 的断点,让 lldb 执行授权赋予 RX ,做到在用一块内存上实现 Debug 时具备 RWX 的效果

对详细实现感兴趣的可以看之前的 《Flutter 又双叒叕可以在 iOS 26 的真机上 hotload》 ,而从临时实现方案就可以看出来,这一个非常 hack 补丁,并且这个方案预计会为每个代码空间页的分配增加约 500 毫秒的延迟,在加上实际工作中和 debugserver 还有等待 Xcode 建立调试会话的时间,让 iOS 在 Debug 开发中十分容易出现 Timed out *** to update 等问题。

事实上针对这类问题苹果也发现了“盲点”,特别还需要 Xcode 启动配合等繁琐操作,所以在 Xcode 16 增加了 devicectl 和 Xcode 的命令行调试器 lldb 协同工作的支持:

而针对这个问题,Flutter 在 Xcode 16 也终于实现了新的调整#173443,通过新的 devicectl + lldb 集成到 flutter run 命令来回归 Apple 官方的 debug 体系:

  • 通过 devicectl 实现安装启动: devicectl 作为在 Xcode 15 中引入的控制工具,它主要负责将编译好的应用包(.app)安装到物理设备上,并负责启动应用进程
  • 通过 lldb 实现 JIT 和调试运行:作为 LLVM 项目的一部分,lldb 是 Apple 标准的底层调试器,在新架构中它将作为核心的调试传输层,负责附加到由 devicectl 启动的应用进程,并建立起和 Dart VM 进行通信的桥梁

具体可以在 flutter_toolslldb.dart 看到,launchAppWithLLDBDebugger 启动之后,就会执行 lldb 的 attachAndStart

而对于 attachAndStart ,主要核心就有:

  • 启动一个定时器,如果一分钟内没有成功,提示超时
  • 设置一个断点 _setBreakpoint
  • 依附进程 _attachToAppProcess

那为什么需要在执行 lldb 的时候通过 _setBreakpoint 添加一个断点呢?实际上这就是在前面临时方案基础上的完善, _setBreakpoint 的主要目的就是:

  • 设置 NOTIFY_DEBUGGER_ABOUT_RX_PAGES 作为 lldb 的断点

  • 写入一个 _pythonScript 脚本,当断点触发时,利用 lldb 的权限执行脚本,创建一个新的 rx 内存

关于 NOTIFY_DEBUGGER_ABOUT_RX_PAGES 作为断点我们在之前讲过,它是 Dart VM 在 VirtualMemory::AllocateAligned 时,会通过 NOTIFY_DEBUGGER_ABOUT_RX_PAGES 触发,去让 lldb 用它的权限申请执行:

而对于在 lldb 里执行的 py 脚本,它主要是:

  • 当 Flutter 应用的 Dart VM 需要一块新的内存用于 JIT 编译时,调用这个名为 NOTIFY_DEBUGGER_ABOUT_RX_PAGES 的函数,这个调用会触发预设的断点

  • 断点触发后,_pythonScript 的代码立即被执行

    • 从寄存器 (x0, x1) 读取 Dart VM 请求的内存地址和长度

    • 利用 lldb 的 WriteMemory 向该内存地址写入数据,这个“写入”动作是关键,它会强制 iOS 系统为这块内存做好准备

  • 写入一个 b'IHELPED!' 的“回执”信号,以便 Dart VM 确认操作已成功

  • 执行完毕后,它返回 False,告诉 lldb “任务完成,请立即让应用继续运行”

之后,通过 lldb device process attach --pid 的方式,让进程被纳入“开发者调试上下文”,从而支持 JIT 权限:

前面说起来比较抽象,具体可以理解为:

_attachToAppProcess 获取“权限” :

因为系统的 W^X 安全策略,_attachToAppProcess 的核心作用就是利用 lldb 附加的特权,为整个应用进程解锁了这个限制。

在这一步完成之后,应用进程的状态从“不允许 JIT”变成了“理论上可以 JIT”,它获得了让内存页变为可读、可写、可执行 (RWX) 的可能性

但是,仅仅有可能性是不够的 ,因为Dart VM 在运行时和 hotload 是动态地、按需地需要新的可执行内页 page,它需要一个“机制”来实现,在需要的时候真正地去执行这个“将内存页变为 RWX”的操作,而 App 本身的 Dart VM 本身没有这个权限,所以它无法自己完成这个操作。

这时,它就像一个身处大楼内、知道自己需要打开一扇门,但自己手上没有钥匙的住户。

_setBreakpoint 建立“通信与执行机制”

_setBreakpoint 的作用就是建立这个缺失的机制,类似于:

  • 建立通信渠道:Dart VM 被设计成在需要新内存页时,会去调用 NOTIFY_DEBUGGER_ABOUT_RX_PAGES 函数,这就像住户去按下一个特定的“求助”门铃

  • 部署执行者_setBreakpoint 告诉 lldb “请一直监听这个‘求助’门铃 (NOTIFY_DEBUGGER_ABOUT_RX_PAGES)”,这就相当于雇佣了一位管家,让他守在门铃旁边

  • 下达具体指令_setBreakpoint 还通过 _pythonScript 告诉管家:“一旦门铃响起,你就用你手上的万能钥匙 (WriteMemory特权),去帮住户打开他指定的那扇门 (在指定地址和长度的内存上执行操作)。”

所以,完整的流程是这样的:

  • _attachToAppProcess:授予 lldb ,大楼的安全限制被解除了,你可以走进去,但是你没有钥匙,这是前提条件。

  • _setBreakpoint:管家 (_pythonScript) 被部署到位,并且明确了工作指令(监听门铃并开门),这是执行机制,当你需要 JIT 的时候,就去按下门铃

所以 _pythonScript 是 Flutter lldb 架构的连接点,它作为一个实时协议适配器,在 lldb 的原生世界和 Dart VM 服务的托管世界之间进行翻译。

自此, lldb attach 成功后,Dart VM 在启动时会尝试打开 JIT Compiler ,当然,如果 lldb 失败,它将回退到使用过去的 Xcode 自动化支持:

所以,随着全新的 iOS 26 稳定版即将发布,Flutter 也完成了它全新 LLDB 调试的适配迁移,不过也可以看出,iOS 上的 JIT 持续支持,确实不是一件容易的事情。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/920211.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/920211.shtml
英文地址,请注明出处:http://en.pswp.cn/news/920211.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习全流程拆解 _ 从数据到模型的科学之道

-—— 避开80%项目失败的隐形成本,掌握高效建模方法论*📌 一、明确目标:成败的起点 1. 问题定位 分类任务:区分二分类/多分类/多标签分类预测任务:标量预测(如房价)vs 向量预测(如股…

Android 广告轮播全实现:图片与视频混合展示的完整方案

广告轮播是移动应用中提升用户转化率的核心组件,尤其在电商、资讯类应用中应用广泛。传统轮播仅支持图片展示,而现代应用需要兼顾图片和视频内容以增强吸引力。本文将详细讲解如何实现一个支持图片与视频混合播放的高性能广告轮播,涵盖布局设…

AI大模型企业落地指南-笔记01

前言AI技术的发展趋势必然是越来越普及,越来越“技术平权”的。在未来10年内,AI将以各种方式“融入”人类世界,与人类乃至世界深度融合。一. 概念第1章 AI与大模型概述1.1 什么是AI人工智能(全称Artificial Intelligence&#xff…

Linux-孤儿进程和僵死进程

文章目录孤儿进程概述僵死进程概述孤儿进程 概述 父进程运行结束,子进程还在运行,此时,子进程就成了孤儿进程(Orphan Process)每当出现一个孤儿进程的时候,内核就把孤儿进程的父进程设置为 init &#xf…

【Redis 进阶】----主从复制(重点理解流程和原理)

在分布式系统中为了解决单点问题(某个服务器程序只有一个节点(只搞一个物理服务器来部署这个服务器程序)。可用性不高:如果这个机器挂了意味着服务就中断了;性能 / 支持的并发量比较有限)。通常会把数据复制…

【Redisson】redis最佳实践-RedissonUtils+Caffeine

RedissonUtils - 企业级 Redis 缓存工具库 - 二级缓存 项目地址: hhttps://gitee.com/chen934298133/redisson-utils问题反馈: Issues邮箱: chen934298133163.com 📖 项目简介 RedissonUtils 是一个基于 Redisson 的企业级 Redis 缓存工具库,提供了完…

QT(QTableWidget)

QT6QTableWidget QTableWidget是一种Item Widget组件,它以表格形式和管理数据,表格的每个单元格关联一个QTableWidgetItem对象,可以设置每个单元格的文字内容、字体、文字颜色、背景色、图标等,还可以有复选框。每个单元格还可以存…

Sentinel相关记录

系列文章目录 draft Sentinel 是阿里巴巴开源的 轻量级服务防护组件,主要用于实现以下功能:流量控制FlowRule(Rate Limiting):限制单位时间内的请求量,防止系统过载。 熔断降级DegradeRule(Ci…

2025年渗透测试面试题总结-29(题目+回答)

安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 二百四十一、XSS 设置Http-Only如何绕过 二百四十二、XSS攻击手段分类 二百四十三、高杀软覆盖工作组的渗…

如何用Wireshark捕获当前房间路由器和主机的数据包

一、前期工作 在我的这篇文章中: Wireshark USRP联合波形捕获(上)-CSDN博客 通过192.168.1.103这个主机ip筛选Wireshark捕获的数据包,认为Source和Direction中至少一个包含192.168.1.103才能代表路由器和主机之间的WiFi信号。 …

深度解析游戏引擎中的相机:视图矩阵

在现代游戏引擎中,相机系统是不可或缺的一部分。它决定了玩家在游戏中看到的视角和场景。而视图矩阵作为相机系统的核心组件之一,起到了至关重要的作用。本文将深入探讨视图矩阵的原理、计算方法及其在游戏引擎中的应用。 视图矩阵的基本概念 视图矩阵…

96、23种设计模式之原型模式(5/23)

原型模式(Prototype Pattern)是创建型设计模式的一种,其核心思想是通过复制现有对象(原型)来创建新对象,而非通过构造函数或工厂方法从头构建。该模式将对象的创建过程从构造逻辑转移到复制操作&#xff0c…

【python与生活】如何用Python写一个简单的自动整理文件的脚本?

用 Python 写一个自动整理文件的脚本很简单,核心思路是:按文件后缀(如 .jpg、.pdf)将文件分类,移动到对应的文件夹(如「图片」「文档」)中。以下是一个实用的实现方案,新手也能轻松修…

SELinux相关介绍

目录 1.SELinux 概述 2.SELinux 的执行模式 3.SELinux 的使用 1.SELinux 概述 SELinux( Security Enhanced Linux 安全性增强的Linux),由美国国家安全局 NSA(National Security Agency)开发,构建与 Kernel …

【C语言练习】汉诺塔

一、题目 介绍:汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆…

随机森林实战:在鸢尾花数据集上与决策树和逻辑斯蒂回归进行对比

前言 集成学习通过组合多个模型的优势,常能获得比单一模型更优的性能,随机森林便是其中的典型代表。它基于 Bagging 思想,通过对样本和特征的双重随机采样,构建多棵决策树并综合其结果,在降低过拟合风险的同时&#xf…

(计算机网络)TCP 三握中第三次 ACK 丢失会发生什么?

在 TCP 的三次握手过程中,如果 第三次 ACK 丢失,TCP 是如何保证连接可靠建立的呢?1️⃣ 场景说明第三次 ACK:客户端发送给服务器的 ACK,确认服务器的 SYN-ACK。假设该 ACK 在网络传输过程中丢失。2️⃣ 客户端状态客户…

容智Report Agent2.0重磅发布!重新定义企业数据分析AI时代

在数据成为生产要素之一的今天,很多企业依然面临这样的困境: 想要一份年度财务分析,财务团队可能要忙半个月甚至一个月;想查一个业务指标,要先找出在哪个系统,再申请权限、写SQL、调报表,折腾半…

高阶数据结构---ST表

hello大家好,今天是2025年8月23日,我要来给大家分享的是一个高阶数据结构---ST表。 一:引入 1.RMQ问题: 对于一个长度为 n 的序列,有 m 次查询操作,每次查询为一个区间 [l,r] 的最大值&#…

docker 安装nacos(vL2.5.0)

查找nacos 的所需的镜像版本 https://hub.docker.com/r/nacos/nacos-server/tags 拉取你所需的版本(我们用v2.5.0) docker pull nacos/nacos-server:v2.5.0 注意:因为我们需要挂载外配置文件 直接用volume 挂载目录 缺少初始文件报错 我们…