本文是在qemu-virt64-aarch64下運(yùn)行smart-fetch的調(diào)試記錄
準(zhǔn)備
編譯
按照userapps的readme進(jìn)行編譯,編譯前鍵入如下命令,即可編譯出帶調(diào)試信息的userapps
xmake f --mode=debug
gdb配置
在調(diào)試過程中需要進(jìn)入內(nèi)核,所以需要同時(shí)加載內(nèi)核和應(yīng)用程序的elf符號表。設(shè)置.gdbinit文件如下:
target remote localhost:1234
file ../../../rt-thread/bsp/qemu-virt64-aarch64/rtthread.elf
add-symbol-file ../../apps/build/rootfs/bin/smart-fetch
首先使用readelf工具查看smart-fetch程序,發(fā)現(xiàn)其entry point是0x200000的_start,于是在gdb中打斷點(diǎn)b *0x200000(或b _start),在輸入smart-fetch后成功暫停
libc庫查看
本工程采用musl libc,可以自行下載查看源碼
調(diào)試記錄
以下按函數(shù)執(zhí)行的順序來進(jìn)行記錄
_start
該函數(shù)將當(dāng)前用戶態(tài)棧指針設(shè)置為0xffff80000000,為用戶空間較高的地址,之后跳到_start_c
_start_c
所傳入的參數(shù)*p地址為smart預(yù)先設(shè)置的0xfffffffff000。這里存放了應(yīng)用程序初始化所需的參數(shù),由操作系統(tǒng)設(shè)置,最后調(diào)用傳參為__libc_start_main(main, 1, "/bin/smart-fetch",_init,_fini, 0 )
__libc_start_main
首先獲得程序的環(huán)境變量(操作系統(tǒng)設(shè)置,含有操作系統(tǒng)名稱,執(zhí)行文件的信息等)
調(diào)用__init_libc(envp, "/bin/smart-fetch")
asm ( "" : "+r"(stage2) : : "memory" )表示保證在之后stage2采用更新后的值,避免使用緩存的值
__init_libc
該函數(shù)前面主要是通過envp來獲取一些程序信息如pagesize等,接下來執(zhí)行__init_tls和__init_ssp
__init_tls
該函數(shù)目的是初始化線程局部存儲(chǔ)(thread local storage)。它需要根據(jù)elf文件的類型為PT_TLS的段來對線程局部存儲(chǔ)進(jìn)行初始化。這里由于smart-fetch不是多線程程序,沒有PT_TLS類型的段,故該函數(shù)在這里沒有進(jìn)行實(shí)際的操作。
__init_ssp
該函數(shù)是初始化棧保護(hù)機(jī)制,但這里并未實(shí)現(xiàn)該機(jī)制。執(zhí)行dummy函數(shù),不做任何操作
libc_start_main_stage2
首先執(zhí)行__libc_start_init進(jìn)行初始化
之后調(diào)用main函數(shù)獲取返回值
之后調(diào)用exit(main_ret)來進(jìn)行清理
__libc_start_init
調(diào)用事先注冊好的初始化函數(shù)列表__init_array_start。
本處調(diào)用了frame_dummy函數(shù),該函數(shù)并不是musl庫里的函數(shù),而是gcc編譯時(shí)插入的函數(shù)。該函數(shù)調(diào)用初始化函數(shù)(即定義了__attribute__((constructor))的函數(shù)),并調(diào)用register_tm_clones來注冊多線程下的克隆函數(shù)。因?yàn)檫@個(gè)程序無初始化函數(shù)和多線程的特性,所以該函數(shù)實(shí)際上并未執(zhí)行任何操作。
exit
__funcs_on_exit:無操作
__libc_exit_fini:該函數(shù)對應(yīng)于__libc_start_init,調(diào)用解構(gòu)函數(shù),注銷多線程克隆函數(shù),在這里也沒有實(shí)質(zhì)性的操作
_stdio_exit:關(guān)閉所有打開文件及標(biāo)準(zhǔn)輸入、輸出、錯(cuò)誤文件
_Exit:調(diào)用SYS_exit_group系統(tǒng)調(diào)用,之后就是操作系統(tǒng)進(jìn)行資源回收
缺頁異常處理
當(dāng)訪問一個(gè)不存在頁時(shí),aarch改變的寄存器
sp 0xffff80000000 -> 0xffff0000002b6520
pc 0x20008 -> 0xffff0000000c6400
cpsr 0 -> 0x3c5
elr_el1 0x200000 -> 0x200008
sp_el0 0 -> 0xffff80000000
ESR_EL1 0-> 0x92000045
FAR_EL1 0 -> 0xffff7fffffd0
aarch64自動(dòng)做的事(通過對比缺頁觸發(fā)前后寄存器值得出):
-
寄存器
+關(guān)注
關(guān)注
31文章
5421瀏覽量
123328 -
存儲(chǔ)器
+關(guān)注
關(guān)注
38文章
7636瀏覽量
166407 -
RT-Thread
+關(guān)注
關(guān)注
32文章
1370瀏覽量
41510 -
GDB調(diào)試
+關(guān)注
關(guān)注
0文章
24瀏覽量
1616
發(fā)布評論請先 登錄
使用GDB調(diào)試Linux應(yīng)用程序
RT-Thread Smart 入門指南
RT-Smart的資料合集
快速上手RT-Thread Smart入門指南
分析一下在rt-smart操作系統(tǒng)中將一個(gè)應(yīng)用程序運(yùn)行起來要經(jīng)過哪些步驟
請問RT -SMART支持GDB調(diào)試嗎?
在rt-smart操作系統(tǒng)中將ELF應(yīng)用程序運(yùn)行起來要經(jīng)過哪些步驟
RT-Thread Smart快速上手
rt-smart應(yīng)用程序系統(tǒng)調(diào)用實(shí)現(xiàn)過程是怎么樣的?
樹莓派上rt-smart的應(yīng)用編程入門

如何在rt-smart簡化應(yīng)用程序開發(fā)
RT-Smart ELF應(yīng)用程序加載運(yùn)行過程分析
基于xmake的RT-Thread Smart用戶態(tài)開發(fā)教程

帶有RT-Thread的Arduino應(yīng)用程序

基于xmake的RT-Thread Smart用戶態(tài)開發(fā)教程

評論