【電腦系統基礎1】gdb、gcc簡易使用指南

1. 基本實驗工具的使用

1.1GCC

在IA-32+LINUX平台

在IA-32+LINUX平台上,編譯,調試和運行C語言

  • 為了把C語言源程式編譯成IA-32機器指令,X86-64位電腦系統需要先運行下列命令:

    sudo apt-get install build-essential module-assistant
    sudo apt-get install gcc-multilib g++-multilib
    

基本的GCC 命令

  • -E:翻譯帶 # 的文件,將頭文件內容生成到源文件中。

  • -S:生成彙編文件。

  • -C:生成鏈接文件,就是組裝的模組。

image-20220527103628467

  • gcc -E hello.c -o hello.i
    gcc -S hello.i -o hello.s
    gcc -C hello.s -o hello.o
    gcc hello.o -o hello
    

一些其他選項

gcc -O0 -m32 -g hello.c -o hello
  • -O0: 不用編譯優化
  • -m32:編譯成 x86-32 位的指令
  • -g:帶調試資訊

1.2objdump

  • 作用:反彙編二進位的目標文件
objdump -S gdbtest.o > gdbtesto.txt
objdump -S gdbtest > gdbtest.txt
  • -s:在反彙編後的內容中添加源程式碼

image-20220527154011432

image-20220527154159949

1.3gdb

啟動gdb 調試工具

啟動gdb 調試工具,載入要被調試的可執行文件

# 啟動方式1:gdb [可執行文件名]
gdb gdbtest
# 啟動方式2:1.gdb 2.file [可執行文件名]
gdb
file gdbtest
# 查看源程式碼
l

設置斷點

# 在 main 函數的入口處設置斷點
break main # 或者 b main
# 在源程式 gdbtest.c 的第 3 行處設置斷點
break gdbtest.c:3

啟動程式運行

# 啟動程式運行,程式會在斷點處停下
run # 或者 r 

查看程式運行時的當前狀態

  • 程式的當前斷點位置

    eip 暫存器:保存一下條要執行的指令的地址

    # i r:顯示所有暫存器的內容
    # i r eip: 只顯示暫存器 eip 的內容,64位是rip
    i r eip
    
  • 通用暫存器內容

    i r eax ebx ecx edx #(或i r) 顯示通用暫存器內容
    
  • 查看變數的地址

    p &a # 查看a的地址
    
  • 存儲器單元內容

    x/8xb 0xffffd2bc 
    x/2xw 0xffffd2bc
    

    各部分含義解釋:

    • image-20220527172650195

    • image-20220527172712212

    • image-20220527172732913

    • image-20220527172802817

    • image-20220527172814461

    語句含義:

    • image-20220527172854572
    • image-20220527173027977
  • 棧幀資訊

    說明: IA-32用棧來支援過程的嵌套調用,過程的入口參數、返回地址,被保存暫存器的值、被調用過程中的非靜態局部變數等都會被保存在棧中。
    棧幀:系統為每個執行的過程分配一個棧空間。

    類似於游泳池儲物櫃的申請和返還

    image-20220527173449423

    當前棧幀範圍:

    i r esp ebp # esp棧頂指針、ebp 棧底指針
    

    當前棧幀位元組數:

    y = R[ebp] - R[esp] + 4

    舉例:

    image-20220527173839206

    顯示當前棧幀內容:

    x/yxb $esp # y: R[ebp]-R[esp]+4的值, 棧幀起始地址是esp指向的單元地址;
    
    x/zxw $esp # z=y/4, 顯示從esp指向的地址開始。
    

繼續執行下一條指令或語句

si # 執行一條機器指令
s  # 執行一條C語句

退出

quit

————恢復內容結束————