在Ubuntu上使用QEMU學習RISC-V程序(2)gdb調試

文章目錄

      • 一、準備工作
      • 二、基本調試流程
        • 1. 設置斷點
        • 2. 執行程序
        • 3. 查看源代碼/匯編
      • 三、查看寄存器
        • 1. 查看通用寄存器
        • 2. 查看特殊寄存器
      • 四、查看內存
        • 1. 內存查看命令
        • 2. 內存修改命令
      • 五、調試實戰示例
      • 六、高級調試技巧
        • 1. 條件斷點
        • 2. 自動顯示
        • 3. 內存斷點(觀察點)
        • 4. 回溯調用棧
      • 七、退出調試
    • 八、退出QEMU
      • 總結

在嵌入式開發中,GDB是調試RISC-V程序的核心工具。以下是使用 gdb-multiarch調試 add.elf程序的詳細步驟,包括斷點設置、寄存器查看、內存分析等關鍵操作:

一、準備工作

  1. 給elf文件增加調試信息
# 編譯匯編代碼(添加-g選項)
riscv64-unknown-elf-as -g -march=rv64g -mabi=lp64 add.s -o add.o# 鏈接(保持-g選項)
riscv64-unknown-elf-ld -g -T link.ld add.o -o add.elf# 檢查文件是否包含調試信息
riscv64-unknown-elf-readelf -S add.elf | grep debug# 輸出示例(應包含多個debug_*節)
.debug_info     PROGBITS        0000000000000000  000002e0
.debug_abbrev   PROGBITS        0000000000000000  000006e8
.debug_line     PROGBITS        0000000000000000  000007e0
  1. 啟動QEMU并暫停執行
qemu-system-riscv64 \-machine virt \-cpu rv64 \-m 128M \-nographic \-bios none \-kernel add.elf \-s -S  # -s開啟GDB服務器,-S暫停執行直到GDB連接
  1. 啟動GDB并連接到QEMU
    如果沒有安裝gdb-multiarch,先用sudo apt install gdb-multiarch進行安裝。
gdb-multiarch add.elf  # 加載帶有調試信息的ELF文件# 在GDB交互式界面中執行以下命令
(gdb) set architecture riscv:rv64  # 指定目標架構
(gdb) target remote :1234         # 連接到QEMU的GDB服務器

二、基本調試流程

1. 設置斷點
(gdb) break _start        # 在_start標簽處設置斷點
(gdb) break add.s:20      # 在add.s文件第20行設置斷點
(gdb) break print_string  # 在print_string函數入口設置斷點
(gdb) info breakpoints    # 查看已設置的斷點
2. 執行程序
(gdb) continue            # 繼續執行到下一個斷點
(gdb) next                # 單步執行(不進入函數)
(gdb) step                # 單步執行(進入函數)
(gdb) finish              # 執行完當前函數并返回
(gdb) until 25            # 執行到當前文件第25行
3. 查看源代碼/匯編
(gdb) list                # 顯示當前位置附近的源代碼
(gdb) list 10,20          # 顯示第10-20行代碼
(gdb) disassemble         # 反匯編當前函數
(gdb) x/i $pc             # 顯示當前執行的指令
(gdb) layout asm          # 切換到匯編視圖
(gdb) layout regs         # 顯示寄存器窗口

三、查看寄存器

1. 查看通用寄存器
(gdb) info registers      # 顯示所有寄存器
(gdb) print $a0           # 查看a0寄存器的值
(gdb) p/x $sp             # 以十六進制形式查看sp寄存器
(gdb) p/a $ra             # 以地址形式查看ra寄存器
(gdb) display $t0         # 每次停止時自動顯示t0寄存器
2. 查看特殊寄存器
(gdb) p $mstatus          # 查看機器狀態寄存器
(gdb) p $mcause           # 查看異常原因寄存器
(gdb) p $mtvec            # 查看異常向量表基址
(gdb) set $pc = 0x80000010  # 修改程序計數器

四、查看內存

1. 內存查看命令
(gdb) x/10xw 0x80000000   # 從0x80000000開始,以16進制顯示10個32位字
(gdb) x/20b $sp            # 從sp開始,以字節形式顯示20個值
(gdb) x/10i 0x80000000    # 從0x80000000開始,顯示10條指令
(gdb) examine/i $pc        # 查看當前執行的指令
2. 內存修改命令
(gdb) set {int}0x80000010 = 42  # 將0x80000010處的32位整數設置為42
(gdb) set *0x80000014 = 0x1234  # 將0x80000014處的16位值設置為0x1234

五、調試實戰示例

假設我們要調試add.s程序中的加法操作:

  1. 設置斷點并開始執行
(gdb) break _start
(gdb) continue
  1. 單步執行到加法操作
(gdb) step  # 執行初始化棧指針
(gdb) step  # 加載a0 = 10
(gdb) step  # 加載a1 = 20
(gdb) step  # 執行add a2, a0, a1
  1. 驗證加法結果
(gdb) p/x $a0    # 應該顯示0xa (10)
(gdb) p/x $a1    # 應該顯示0x14 (20)
(gdb) p/x $a2    # 應該顯示0x1e (30)
  1. 查看內存中的變量
(gdb) x/i $pc    # 顯示當前指令
(gdb) x/10xw 0x80000000  # 查看.text段內容
(gdb) x/10xw $sp         # 查看棧內容
  1. 調試UART輸出
(gdb) break print_string
(gdb) continue
(gdb) step  # 進入print_string函數
(gdb) p $a0  # 查看要打印的字符串地址
(gdb) x/s $a0  # 以字符串形式顯示內存內容

六、高級調試技巧

1. 條件斷點
(gdb) break add.s:25 if $a0 > 10  # 當a0>10時觸發斷點
2. 自動顯示
(gdb) display/i $pc        # 每次停止時顯示當前指令
(gdb) display/x $a0        # 每次停止時顯示a0寄存器
3. 內存斷點(觀察點)
(gdb) watch *0x80000020    # 當地址0x80000020被修改時觸發
4. 回溯調用棧
(gdb) backtrace           # 顯示調用棧
(gdb) frame 1             # 切換到第1層棧幀

七、退出調試

(gdb) disconnect          # 斷開與QEMU的連接
(gdb) quit                # 退出GDB

八、退出QEMU

退出qemu-system-riscv64通常可以使用快捷鍵或通過監視器界面來操作,具體方法如下:

  • 使用快捷鍵:按下Ctrl + a,然后松開這兩個鍵,再按下x,即可直接終止QEMU進程,回到shell界面。
  • 通過監視器界面:首先按下Ctrl + a,然后松開,再按下c,這將退出當前操作系統的shell界面,進入QEMU的監視器界面。接著在監視器界面中,輸入q并按回車鍵,即可完全退出QEMU。

總結

通過上述命令,你可以全面掌控程序的執行流程,監控寄存器和內存的變化,從而快速定位問題。GDB的強大功能不僅適用于調試簡單程序,也是開發復雜嵌入式系統的必備工具。建議結合具體程序多練習,熟練掌握這些命令將顯著提高開發效率。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93058.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93058.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93058.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

不止于“亮”:一盞智慧路燈的技術進化史——塔能科技用“落地性”定義行業標準

在凌晨3點的園區道路之上,路燈會隨著車輛的靠近而自動亮起,待車輛逐漸遠去之后,又會緩緩地調暗下來;當電纜意外被觸碰的時候,系統能夠在短短3秒之內自動發出報警信息,并且推送出維修工單;而當一…

Redis的String數據類型底層實現

redis就是用c語言寫,但redis的string并沒有直接用c語言的string,而是自己搞了一個 SDS 結構體來表示字符串。SDS 的全稱是 Simple Dynamic String,中文叫做“簡單動態字符串”。想知道為什么這么做,我們先看看c語言的string是什么…

【音視頻學習】四、深入解析視頻技術中的YUV數據存儲方式:從原理到實踐

文章目錄 引言 1. YUV 基礎:為什么它比 RGB 更適合視頻? 1.1 YUV 與 RGB 的核心區別 1.2 YUV色度下采樣簡介 2. YUV 的三大存儲方式 方式一:平面格式(Planar) 方式二:半平面格式(Semi-Planar ) 方式三:打包格式(Packed YUV) 三種存儲方式對比: 3. 如何選擇合適的 Y…

前端項目組成

一、前端項目常見模塊及功能(以 Vue/React 通用結構為例) 前端項目的模塊本質是「按功能拆分的代碼文件/文件夾」,就像蓋房子的「磚、梁、窗」各司其職:模塊類型功能說明(大白話)舉個例子pages(…

聚觀早報 | 猿編程推動中美青少年AI實踐;華為Pura 80數字版售價公布;iPhone 17 Air電池曝光

聚觀早報每日整理最值得關注的行業重點事件,幫助大家及時了解最新行業動態,每日讀報,就讀聚觀365資訊簡報。整理丨肖羽7月24日消息猿編程推動中美青少年AI實踐華為Pura 80數字版售價公布iPhone 17 Air電池曝光亞馬遜收購AI初創公司Bee蜂巢半固…

unittest 案例執行順序詳解

unittest 案例執行順序詳解在 unittest 框架中,測試用例的執行順序有默認規則,也可通過自定義方式調整。以下是具體說明:一、默認執行順序規則unittest 對測試用例的執行順序遵循 “按測試方法名的 ASCII 碼排序” 原則,具體邏輯如…

【web大前端】001_前端開發入門:創建你的第一個網頁

前端開發入門:創建你的第一個網頁 在當今數字化時代,網頁已經成為人們獲取信息和交流的重要平臺。對于想要學習編程的人來說,前端開發往往是一個不錯的起點。本文將帶你通過簡單的兩步,創建屬于你的第一個網頁程序。 點擊這里去…

HTTP性能優化終極指南:從協議原理到企業級實踐

前言:為什么性能優化是Web開發的生命線?根據Google研究數據,當頁面加載時間從1秒增加到3秒時,跳出率提升32%;當達到5秒時,轉化率下降90%。本文將通過七層優化體系,帶您掌握HTTP性能優化的核心技…

Python 數據分析(二):Matplotlib 繪圖

目錄 1. 簡介2. 繪圖 2.1 折線圖 2.1.1 單線2.1.2 多線2.1.3 子圖 2.2 散點圖2.3 直方圖2.4 條形圖 2.4.1 縱置2.4.2 橫置2.4.3 多條 2.5 餅圖 1. 簡介 Matplotlib 是 Python 提供的一個繪圖庫,通過該庫我們可以很容易的繪制出折線圖、直方圖、散點圖、餅圖等豐…

Scrapy分布式爬蟲數據統計全棧方案:構建企業級監控分析系統

引言:數據統計在分布式爬蟲中的戰略價值在分布式爬蟲系統中,??數據統計與分析??是系統優化的核心驅動力。根據2023年爬蟲工程調查報告:實施專業統計方案的爬蟲系統性能提升??40%以上??數據驅動的優化策略可減少??70%??的資源浪費…

計劃任務(at和cron命令介紹及操作)

簡介計劃任務主要做一些周期性的任務,目前最主要的是定期備份數據分類at:一次性調度執行cron:循環調度執行at簡介at 是一個用于安排一次性任務的命令行工具,適合在指定時間點執行單次任務語法at 時間 選項若要提交,通過…

[2025CVPR:圖象合成、生成方向]WF-VAE:通過小波驅動的能量流增強視頻 VAE 的潛在視頻擴散模型

論文概述? 這篇論文提出了一種名為WF-VAE(Wavelet Flow VAE)?的新型視頻變分自編碼器(Video VAE),旨在解決潛在視頻擴散模型(LVDM)中的關鍵瓶頸問題,包括高計算成本和潛在空間不連續性。WF-VAE利用小波變換(Wavelet Transform)來分解視頻信號,并通過能量流路徑優…

Map接口-實現類HashMap

目錄 一、什么是Map? 二、實現類HashMap 1.關鍵特點 無序、key唯一、value允許重復、key和value允許為null。 2.數據結構 2.1 JDK 1.7 2.2 JDK 1.8 2.3 關鍵參數 2.4 關鍵計算 3.擴容方式 3.1 初始化 3.2 擴容 4.常見方法 4.1 根據key存入value 4.2 …

深入解析Hadoop如何實現數據可靠性:三副本策略、校驗和驗證與Pipeline復制

Hadoop數據可靠性的重要性在大數據時代,數據可靠性已成為企業數字化轉型的生命線。根據IDC預測,到2025年全球數據總量將增長至175ZB,其中企業數據占比超過60%。面對如此龐大的數據規模,任何數據丟失或損壞都可能造成數百萬美元的經…

15.6 DeepSpeed+Transformers實戰:LLaMA-7B訓練效率提升210%,顯存直降73%

DeepSpeedTransformers實戰:LLaMA-7B訓練效率提升210%的底層邏輯與實操指南 當LLaMA-7B的訓練顯存需求達到78GB時,單卡A100(80GB)幾乎瀕臨溢出,更不用說普通GPU集群。而DeepSpeed與Hugging Face Transformers的深度集成,通過"ZeRO三階段優化+混合精度+梯度檢查點&q…

Nginx + PM2 實現Express API + React 前端 本地測試服務器搭建

一、工具準備 openSSL:需要針對https請求頭 生成對應的 自簽名證書。 Nginx:服務器搭建工具 nodeJS: Express API運行環境 PM2: node進程管理器。用于替代npm命令管理 啟動命令。 二、openSSL 本地自簽名證書生成。 創建服務器空文件夾&#xff08…

OTG原理講解

文章目錄一、什么是 OTG(USB On-The-Go)?? OTG 的定義:二、傳統 USB 與 OTG 的區別三、OTG 的核心機制:**通過 ID 引腳判斷角色**1. 對于 Micro-USB OTG:2. 電路如何感知 ID 引腳?四、OTG 電路…

數據結構系列之紅黑樹

前言 紅黑樹是比較重要的一顆樹了,map和set的底層就是紅黑樹,一定要牢牢記住。 一、什么是紅黑樹 首先:紅黑樹仍然是一顆搜索二叉樹,但他引入了顏色這一概念,每個結點多一個存儲位來存儲顏色,它通過維護下…

在OpenMP中,#pragma omp的使用

在OpenMP中,#pragma omp for 和 #pragma omp parallel for(或 #pragma omp parallel num_threads(N))有本質區別,主要體現在 并行區域的創建 和 工作分配方式 上。以下是詳細對比:1. #pragma omp for 作用 僅分配循環迭…

停止“玩具式”試探:深入拆解ChatGPT Agent的技術棧與實戰避坑指南

摘要: 當許多人還在用ChatGPT寫周報、生成樣板代碼時,其底層的Agent化能力已經預示著一場深刻的開發范式變革。這不再是簡單的“AI輔助”,而是“人機協同”的雛形。本文旨在穿透表面的功能宣傳,從技術棧層面拆解Agent模式的實現基…