天天看點

OpenHarmony上使用gdb調試init

作者:51CTO

OpenHarmony 适配新的開發闆時,啟動流程 init 大機率會出現問題。

OpenHarmony上使用gdb調試init

其為核心直接拉起的第一個使用者态程序,問題定位手段隻能依賴代碼走讀和增加調試列印,初始化過程中系統崩潰的問題就更難定位了。如果能使用 gdb 調試 init,會極大提高定位效率。

本文将詳細闡釋二次啟動的标準系統如何使用 gdb 調試 init。

用 gdb 調試 init

①編譯出帶 debug 資訊的調試版本

将 gdb 打包到系統鏡像中。init 不正常的情況下,系統無法正常啟動工作,無法使用 hdc 工具加載 gdb 工具,是以直接在制作鏡像時,将其打包到系統鏡像 bin 目錄下。

修改 device\board\hihope\rk3568\cfg\BUILD.gn 打包腳本如下,注意保證 gdb 工具已放置在此本目錄下。

OpenHarmony上使用gdb調試init

②調試版本鏡像帶符号

需要修改鏡像配置檔案,修改其大小限制,尤其是 system.img,編譯失敗時不會提示實際鏡像大小,需要修改到 5G 以上。

OpenHarmony上使用gdb調試init

③編譯調試版本,打開版本調試開關

./build.sh --product-name=XXX --gn-args="is_debug=true use_unstripped_as_runtime_outputs=true"           

上述 debug 版本隻能調試普通功能而不能調試 init,還需要對 init 服務的源碼進行部分适配修改,init 功能調試正常後,需将源碼恢複。

首先,在 init 挂載好 system、vendor 等鏡像,并将根目錄切換到 system 鏡像後。

在啟動第二階段 init 時,切換到 shell 下,停止 init 初始化流程,見下圖 B 處。

OpenHarmony上使用gdb調試init

​源碼詳見 base\startup\init\ services\init\standard\init.c。注意:A 處的 CloseStdio() 需要注釋掉。

考慮用 gdb 啟動 init 第二階段,init 絕大部分處理流程都在這一階段,從這裡開始就可以用 gdb 調試了,init 第一階段處理相對而言流程簡單一些,代碼走讀和調試列印基本就能解決問題。

在 init 主函數中去掉“不等于程序 1 就傳回的處理”,因為用 gdb 起 init 第二階段時,其程序非 1。

源碼詳見base\startup\init\services\init\main.c。

OpenHarmony上使用gdb調試init

init 程序中不初始化 Paramworkspace,前面 pid=1 的判斷,在 gdb 調試 init 時條件不成立,是以此處增加判斷 init 名就直接退出的處理。

源碼詳見 base\startup\init\services\param\base\param_base.c。

OpenHarmony上使用gdb調試init

做好了上述準備,就可以用 gdb 調試 init。

把系統啟動,改造後的 init 初始化第一階段完成後,會停在 shell 下,此時使用下述指令啟動 init 第二階段。

gdb --args /bin/init --second-stage           

為了調試 init 的子程序,還需要 gdb 下述指令:

set follow-fork-mode child           
OpenHarmony上使用gdb調試init

總結

本文章針對 OpenHarmony 系統在調試 init 初始化流程時,缺少高效的問題定位手段這一痛點,引入了嵌入式系統開發的主流調試工具——gdb,較長的描述了這一方法涉及到的版本編譯、适配點修改以及調試指令操作等細節處理,指導開發者提高定位init問題的效率。

需要注意,目前 gdb 調試 init 方法有局限,不适用輕量級系統、小型系統和一次啟動的标準系統。

繼續閱讀