解密 deepin-IDE:如何实现简单灵活的调试技术?


前不久深度科技旗下deepin社区发布了自己的 IDE:deepin-IDE,得到了全网用户尤其是开源社区用户的广泛关注,目前在 GitHub(https://github.com/linuxdeepin/deepin-unioncode)仓库的 star 数量已经达到 600 多个,说明大家的热情还是很高涨的。

为了从技术层面给大家的热情做一个反馈,本文试着将 deepin-IDE 内部的一些实现方法进行分享,希望能够解答友友们的疑惑并得到积极的反馈。

本篇挑了大家关心的“调试”部分进行分享。需要说明的是,deepin-IDE 的调试功能是选用 DAP(Debug Adapter Protocol )调试适配协议实现的,所以整体架构是围绕该协议搭建的,至于 DAP 具体是什么,让我们带着问号往下看。

什么是 DAP 协议

DAP 即调试适配协议( Debug Adapter Protocol ),顾名思义,它是用来对多种调试器进行抽象统一的适配层,将原有 IDE 和调试工具直接交互的模式更改为和 DAP 进行交互。该模式可以让 IDE 集成多种调试器变得更简单,且灵活性更好。

 IDE 中的调试功能有许多小功能组成,包括单步执行、断点、查看变量值等,常规的实现方式是在每个 IDE 中去实现这些逻辑,且因为调试工具的接口不同,还需要为每个调试工具做一些适配工作,这将导致大量且重复的工作,如下图所示:

调试适配器协议背后的想法是标准化一个抽象协议,用于开发工具如何与具体调试器通信。这个思想和 LSP(Language Server Protocol)和 BSP(Build Server Protocol)类似,都是通过协议去统一相同功能在不同工具之间的差异性。其所处位置如下图所示,其中左边为不同的开发工具,右边为不能同的调试器,不同于开发工具和调试器直接交互的方式,DAP 将这些交互统一了起来,让开发工具和调试工具都面向 DAP 编程。

上图中的交互是通过协议进行,所以不会像通过 API 的方式存在语言限制,可以更好的适应调试器的集成。

DAP 如何工作

以下部分解释了开发工具(例如 IDE 或编辑器)和调试适配器之间的交互,包括具体的协议格式说明、交互流程等。

调试会话

开发工具有两种基础的方式和调试器进行交互,分别是:

【单会话模式】

在这种模式下,开发工具启动一个调试适配器作为一个单独的进程并且通过标准的std接口进行通信。在调试会话的结束时调试适配器就终止,对于当前的调试会话,开发工具往往需要实现多个调试适配。

【多会话模式】

在这种模式下,开发工具不会启动调试适配器,而是假定它已经在运行并且会在特定端口上侦听连接尝试,对于每个调试会话,开发工具在特定端口上启动一个新的通信会话并在会话结束时断开连接。

在与调试适配器建立连接后,开发工具和调试适配器之间通过基础协议进行通信。

基础协议

基础协议由两部分组成,包括头和内容(类似于 HTTP),头部和内容部分通过“\r\n”进行分割:

【协议头】

协议头部分由字段组成, 每个头字段由一个键和一个值组成,用‘:’(一个冒号和一个空格)分隔, 每个头字段都以“\r\n“结尾。由于最后一个协议头字段和整个协议头本身都以 \r\n 终止,并且由于协议头是强制性的,所以消息的内容部分总是在(并唯一标识)两个 \r\n 序列之前。当前只支持一个协议头字段:

头字段名 值类型 描述
Content-Length 数字 这个字段是必须的,用来记录内容字段的长度,单位是字节。

协议头部分使用的是“ASCII”编码。

【内容部分】

内容部分包含了实际要传输的数据,这些数据用 JSON 格式来描述请求、响应和事件。内容部分用的是 utf-8 编码

为了有个具体的认识,这里举个简单的例子。在调试过程中,开发人员经常会使用到下一步操作,在 DAP 中其协议为:

Content-Length: 119\r\n
\r\n
{
    "seq": 153,
    "type": "request",
    "command": "next",
    "arguments": {
        "threadId": 3
  }
}

类型是“请求”,命令是下一步,参数部分可以携带多个,这里是用的线程Id。 这个协议看着挺简单的,是吧?接下来就讲讲如何使用它。

使用方法

详细的使用方法这里就不涉及,因为用一个时序图就可以说明:

可以看到,初始化、请求、响应等必要的步骤都在图中。其中调试适配器可以理解为调试器的抽象,调试功能的最终执行者是由对应语言的调试工具实现的。

在 deepin-IDE 中的实现

在 deepin-IDE 中,调试功能的实现是结合 cppdap + debugmanager 实现的。

cppdap 是一款基于 C++ 开发的 SDK,基本实现了 DAP 的全量协议。 deepin-IDE 的客户端和服务端都是应用的该 SDK 进行开发,据此可以实现以下功能:

1.通信功能,包括服务端的 TCP 监听,客户端的 TCP 连接等;

2.DAP 协议的封装,并实现协议的串行化和解串行化;

3.提供注册回调功能,从而可以在回调内处理各种事件、请求等;

它的层级结构如下:

 cppdap 可以减少客户端和服务端不少工作量,也统一了两边的协议数据。而 debugmanager 可以理解为调试器的抽象,包含所有必要的调试要素。整体结构如下:

左边是客户端,右边是服务端,内部实现如下:

客户端实现

客户端包含了两个个主要功能,一个是和 DAP 服务端进行交互,发送调试命令或处理返回的数据;另一个是将DAP 数据转换后显示到用户界面,并响应界面发送的事件。概括起来就包含业务模块、事件模块、DAP 模块和界面4个部分。

业务模块

  • 业务模块包含了插件类、调试参数、调试管理类等,其中插件类负责插件加载、初始化、获取上下文等,调试管理类用来组合事件、DAP、界面几个模块。 事件模块

  • 事件模块包含两个子模块,分别是事件发送和事件接收,比如页面跳转事件、添加\移除断点事件等。 DAP 模块

DAP 模块基于 cppdap 开发,采用层级结构,底层是原始 DAP 协议封装,中间层是针对业务做的进一步封装,简化了向外提供的接口,最上层是对整个调试功能的整合,包括数据缓存、界面元素、命令收发。

  • 界面部分 界面模块包含堆栈界面、变量界面、断点列表、异步对话框等,用于 DAP 的数据展示。
  • 如上图所示,灰色部分为 DAP 客户端的界面呈现。

服务端实现

服务端的功能分为两个部分,一个是基于 cppdap 实现命令的收发,另一个是与 gdb 交互,实现调试程序的启动、暂停、退出等一系列动作。

DAP

  • 和客户端一样,服务端也是基于cppdap实现的通信和协议封装和解析。 调试工具

  • 和调试工具的交互是通过进程调用的方式实现,接收进程输出得到返回信息。如果调试工具本身支持 DAP 协议,则可以直接交互。

至此,本次的分享就到这儿啦!不知道你对 deepin-IDE 中的调试功能有所了解了吗?

温馨提示,deepin-IDE 还包含很多有意思的功能,如果大家感兴趣可以积极反馈,后续有机会再进行分享。

参考文档

debug-adapter-protocol

deepin-IDE 使用手册

内容来源:deepin社区

内容作者:deepin-mozart、toberyan


相關推薦

2023-09-05

deepin 社区正式官宣 deepin-IDE(深度集成开发环境)——由深度公司自主研发,具有多语言、跨平台兼容特性的轻量级集成开发环境。 功能介绍 deepin-IDE 除了包含 IDE 常用功能,如智能编辑器、高度可扩展的命令系统、工程

2023-04-08

传输,COMMON流主要是指未加密音视频流,由软总线进行加解密,调用者只需要把原始的音视频流数据传递给软总线,软总线保障数据的安全传输。 支持传输链路(WLAN/WiFi P2P/蓝牙BR)动态选择。根据双端设备支持的传输链路以及

2024-08-20

特性,在云计算、边缘计算、人工智能和教育等领域快速实现落地应用。Beta 预览版标志着 MoonBit 生态进入全新阶段,为用户提供更稳定、流畅的创新操作体验。 MoonBit自去年发布 alpha 版后,反响热烈。经过一年的高速迭代,Moo

2023-08-27

置 map-underscore-to-camel-case 不起作用的问题 修复:数据源解密器通过 Bean 注解配置和自定义配置配置不统一的问题 #I7UHUN:[Bug]: 解密器配置不统一 修复:使用 Hutool 的 BeanUtil.copyProperties 拷贝 Page 失败的问题 #I7VBUE:[Bug]: 使

2023-06-09

器来分摊请求量;如果你开发的游戏是有状态的,那么你如何解决请求分配的问题呢?在比如让你做一个类似 LOL、王者荣耀的匹配,将匹配好的玩家分配到一个房间中,之后这些玩家的请求都能在同一个游戏逻辑服上处理,这

2024-06-22

与物理链路解耦,增加连接成功率。 传输模块提供加解密接口,并支持Bind接口中途取消、超时可配置等能力。 IPC支持异步消息发送方信息、并提供高性能读写共享内存的JS北向接口能力。 IPC_Core和IPC_Single公共部分解耦

2022-05-23

密处理,而是扩展 @RequestParam 等注解实现逻辑实现数据加解密。支持使用自定义注解灵活配置加密策略以及数据缓存策略。 遵照知名开源项目方式,设计 Maven Dependencies 依赖继承结构,结构清晰明了、依赖干净无冗余、修改维

2023-09-26

、客户管理等功能。该系统采用自研的Nmqs通信层组件,实现了连接信息的加密,保证了数据的安全性。 WeMQ的项目背景源于对物联网设备调试过程中存在问题的深入研究和理解。通过提供开源的解决方案,WeMQ希望为物联网设备

2023-11-28

号、地址、邮箱、银行卡等 可自行扩展 无 数据加解密 采用 注解 + mybatis 拦截器 对存取数据期间自动加解密 支持多种策略 如BASE64、AES、RSA、SM2、SM4等 无 数据翻译 采用 注解 + jackson 序列化期间动态修改数据 数

2024-08-02

级助力器,让普通的 HTML 网页焕发出新的生命力。 HTMX 如何改变开发者的世界? 简化交互逻辑 HTMX 允许你在 HTML 元素上直接声明需要的交互行为,比如点击、悬停、拖拽等,不需要编写复杂的 JavaScript 代码。例如,你只需

2023-08-25

inkis_one-click_install_20230809.zip     — END —   如何成为社区贡献者 1 ► 官方文档贡献。发现文档的不足、优化文档,持续更新文档等方式参与社区贡献。通过文档贡献,让开发者熟悉如何提交 PR 和真正参与

2023-07-19

络通信的业务逻辑实现上。而业务框架正是解决业务逻辑如何方便实现这一问题上。业务框架是游戏框架的一部分,职责是简化程序员的业务逻辑实现,业务框架使程序员能够快速的开始编写游戏业务。 业务框架对于每个 actio

2023-09-07

络通信的业务逻辑实现上。而业务框架正是解决业务逻辑如何方便实现这一问题上。业务框架是游戏框架的一部分,职责是简化程序员的业务逻辑实现,业务框架使程序员能够快速的开始编写游戏业务。 业务框架对于每个 actio

2023-08-08

络通信的业务逻辑实现上。而业务框架正是解决业务逻辑如何方便实现这一问题上。业务框架是游戏框架的一部分,职责是简化程序员的业务逻辑实现,业务框架使程序员能够快速的开始编写游戏业务。 业务框架对于每个 actio