在上一篇文章中介绍了怎么编译并调试内核,当读者想阅览代码或者修正代码时会发现,没有任何代码提示和跳转。当调试内核的时候又发现,gdb命令太多了非常不方便,让人不禁思念有他———IDE的日子,那是多么惬意的时光。

前置常识

言语服务器协议(Language Server Protocol/LSP)

言语服务器协议(LSP)界说了编辑器或IDE与言语服务器之间运用的协议,言语服务器供给了主动完成、跳转界说、查找引证等言语功用。

为什么要提出言语服务器协议并添加言语服务器呢?

很久以前各IDE各自为营,例如Eclipse CDT(主要在Eclipse中供给C/C++支撑)是由Java编写,假如一个运用TypeScript编写的IDE(例如:Visual Studio Code)想供给C/C++的支撑就需求自己运用TypeScript从头写一套。

为了改善这样的局面,微软提出了LSP,将言语支撑和编辑器之间添加一层抽象,编辑器/IDE只要实现LSP协议就具有了杂乱的言语支撑功用,而关于言语服务器相同只需求重视实现LSP协议,而不限定运用何种言语。

关于更多言语服务器以及支撑LSP的IDE列表,请检查微软LSP官网

“Any problem in computer science can be solved by another layer of indirection.”

Clangd

Clangd是一个C++的言语服务器,他为C++言语供给了代码完成、编译过错、转到界说等功用。

下面是一个带有Clangd插件的Vs code,演示了代码完成功用:

使用VScode阅读Android Kernel代码并调试

装置 clangd

假如你本地有NDK环境,在NDK目录下已经有了clangd(/toolchains/llvm/prebuilt/linux-x86_64/bin/clangd)能够直接运用,假如想要独立装置,请检查文档

VScode装置clangd插件

能够直接在VScode中挑选View->Extensions翻开插件管理,然后搜索”clangd“单击装置

官方推荐Make sure the Microsoft C/C++ extension is**not**installed这儿先疏忽,在稍后装备文件中禁用。

装置后需求重载窗口,Ctrl+Shift+P并输入Reload Window

compile_commands.json

为了让clangd能够理解你的源代码,clangd需求知道你的构建标志,而这些信息一般由compile_commands.json文件来记录,这个文件中记录了编译中每个源代码的编译命令,一般由编译体系主动生成。

  • CMAKE经过传递CMAKE_EXPORT_COMPILE_COMMANDS=1来生成compile_commands.json
  • Bazel经过bazel-compile-commands-extractor来生成compile_commands.json
  • 关于make编译的项目,能够经过Bear来生成compile_commands.json

在具有compile_commands.json文件后,能够经过--compile-commands-dir选项来指定数据库地址。

VScode建立源码阅览环境

Android Kernel生成compile_commands.json

本章的Android Kernel源码环境建立参照上一篇文章

经过前置常识的介绍,为了让clangd了解Android Kernel,需求生成一个compile_commands.json文件,上文中介绍了Android Kernel的构建体系为bazel,所以自然想到运用bazel-compile-commands-extractor来生成compile_commands.json文件,Android官方早就想到了开发者有这样的需求,所以早就预制了一个target kernel_compile_commands并在build/kernel/kleaf/common_kernels.bzl中实现了该target。

使用VScode阅读Android Kernel代码并调试
使用VScode阅读Android Kernel代码并调试

在Android Kernel根目录直接运转tools/bazel run //common:kernel_x86_64_compile_commands就会在根目录下生成compile_commands.json。

源码导入VScode

  1. 直接运用VScode翻开common目录,这时候只能简单的检查文件,并没有代码提示等功用
  2. Ctrl+Shift+P并输入Open Workspece Settings(JSON) 并挑选,VScode会在根目录下生成.vscode/settings.json
    使用VScode阅读Android Kernel代码并调试
  3. 将下面代码复制到.vscode/settings.json,需求注意clangd.path的地址更换为读者本地途径 使用VScode阅读Android Kernel代码并调试
  4. 保存上面的settings.json,然后Ctrl+Shift+P并输入Reload Window,然后随便点击一个C文件,Clangd就会主动加载了,左下角会展现正在indexing,并在根目录下会生成.cache目录
    使用VScode阅读Android Kernel代码并调试
  5. 索引完成后,代码提示和符号跳转等功用就能够正常运用了。

VSCode调试内核

VSCode代码调试基于上一篇文章-运用GDB调试Kernel,在这儿简单列一下步骤,详细信息请参照上一篇文章

VScode调试插件装置

装置C/C++ Extension Pack和GDB Debug两个插件

装备VSCode lunch.json调试装备文件

Ctrl+Shift+D调出调试面板,点击create a lunch.json file挑选GDB Debug目标,这时会在.vscode下生成一个lunch.json文件,将下面的代码悉数替换 使用VScode阅读Android Kernel代码并调试 需求注意的是,因为Cuttlefish底层是由crosvm支撑的,对内核的调试支撑也是由crosvm中的gdb支撑的,这儿需求运用硬件断点才能正常Debug,所以运用hardwareBreakpoints将所有断点设置为硬件断点,否则将导致过错。

装备完成后,再次Reload Windows或者重启VScode

启动Cuttlefish

//切换到AOSP目录执行
source build/envsetup.sh
lunch aosp_cf_x86_64_phone-userdebug
launch_cvd -kernel_path /home/prosixe/ssd/Android/android-kernel/out/bzImage -initramfs_path /home/prosixe/ssd/Android/android-kernel/out/initramfs.img 

VScode调试

在你关心的当地设置断点,然后在VScode调试面板点击Start Debugging(F5),之后代码就会停在断点处。

使用VScode阅读Android Kernel代码并调试
使用VScode阅读Android Kernel代码并调试

总结

装备调试环境的进程中并不是一帆风顺,在调试进程中就遇见VScode添加断点vm异常重启的问题,而gdb命令行就顺畅运转,当搜索一大圈一无所获。只能阅览vscode-cpptools源码和GDB Remote Serial Protocol 文档,对比gdb命令行的协议数据。最后发现vscode的断点是break类型的,而crosvm需求hbread的断点才会正常,这和qemu虚拟机是有很大差异的,qemu无论是break还是hbreak都会正常suspend。

“工欲善其事,必先利其器”,功用丰富的IDE能够协助我们节省许多时刻,提高我们的学习体会。