1.GDB調試--以彙編語言爲例

#rpm -qa |grep  gdb

下載:

安裝

#tar -zxvf

#./configure

#make

使用GDB

以彙編語言調試爲例

彙編語言實現CPUID指令

CPUID

cpuid是Intel  Pentinum以上級CPU內置的一個指令(486級以下的CPU不支持),他用於識別某一類型的CPU,

它能返回CPU級別,型號,CPU步進以及CPU字串信息,從此命令也可以得到CPU的緩存和TLB信息

CPUID返回數據類型是在EAX寄存器裏定義的,而指令返回的數值則存儲在EAX,EBX,ECX和EDX寄存器中。

返回的信息分兩部分:基本信息與擴展信息。

在EAX輸入0-3參數時,它返回CPU基本信息;

而在EAX輸入0x8000000至ox800000x,他返回的是CPU擴展信息。擴展信息只包括在Pentinum4及以後的CPU上。

 

CPU級別         基本信息   擴展信息
486及以前的CPU      不可用    不可用
Pentium        0x1    不可用
Pentium Pro,Pentium 2    0x2    不可用
Pentium 3      0x3    不可用
Pentium 4      0x2    0x80000004
Xeon(至強)      0x2    0x80000004

 

代碼

cpuid.s

#cpuid.s Sample program to extract the processor Vendor ID                
.section .data                
output:                   
    .ascii "The processor Vendor ID is 'xxxxxxxxxxxx'\n"
.section .text                
.globl _start                
_start:                   
    movl $0, %eax                   
    cpuid                   
    movl $output, %edi                   
    movl %ebx, 28(%edi)                   
    movl %edx, 32(%edi)                   
    movl %ecx, 36(%edi)                   
    movl $4, %eax                   
    movl $1, %ebx                   
    movl $output, %ecx                   
    movl $42, %edx                   
    int $0x80                   
    movl $1, %eax                   
    movl $0, %ebx                   
    int $0x80<strong></strong>

 
彙編


使用GNU彙編器

#as -o cpuid.o cpuid.s

使用GNU鏈接器

#ld -o cpuid cpuid.o

運行程序

#./cpuid

輸出

調試

爲了調試彙編語言程序,必須使用-gstabs參數重新彙編代碼

#as -gstabs -o cpuid.o cpuid.s

#ld -o cpuid cpuid.o

使用-gstabs參數在可執行文件中添加了附加信息,所以新產生的文件會大些

如果沒有必要不要使用調試信息

運行

在gdb內運行

#gdb cupid

GNU調試器啓動,把程序加載到內存,使用run命令(簡化r也可以)從gdb內運行程序

可見調試器內的運行和從命令行直接運行一樣

斷點

彙編語言中指定斷點時,必須指定對於最近的標籤的相對位置,上述代碼中只有一個標籤,所以每個斷點必須依據_start指定。

break(簡化的b)命令格式 break * label+offset

break 函數名

break 行號

break 文件名:行號

break 文件名:函數名

break +偏移量

break -偏移量

break *地址

label是被引用的源代碼中的標籤

offset是應該停止的地方距離標籤的行數

break * _start

*_start參數指定了斷點,該參數指定_start標籤後的第一條指令碼。

run或者(簡化的r)啓動程序,暫停在第一條指令碼處。

單步

使用next(簡化的n)或者step(簡化的s)命令單步調試

注意:s會步入調用的函數,類似於VS中的F11,而n類似於VS中的F10

每個next或者step命令執行下一行代碼

繼續運行

使用continue(或者c)按正常方式繼續運行,類似於VS中的F5

查看數據

info  registers   查看所有寄存器的值

print (或者p)   顯示特定寄存器或者來自程序的變量值

p $eax            顯示寄存器的內容

p/格式  變量

格式

p/t    顯示爲2進制數

p/o   顯示爲8進制數

p/d   顯示爲10進制數

p/u   顯示爲無符號10進制數

p/x   顯示爲16進制數

p/a   地址

p/c   顯示爲字符

p/s   顯示爲字符串

p/f    浮點小數

p/i    顯示爲機器語言(僅在顯示內存的x命令中可用)

程序指針可以寫爲$pc或者$eip,因爲Intel IA-32架構中的程序指針名爲eip

p $pc

p $eip

x         顯示特定的內存位置內容

x/格式 地址

x命令顯示特定內存位置的值。

x命令的格式 x/nyz

n是要顯示的字段數;

y是輸出格式同之前的p

z是要顯示的字段長度:

b        字節

h        半字(2字節)

w       字(4字節)默認值

g        雙字(8字節)

例如:

x $pc

x/i $pc

此處x/i意爲顯示彙編指令

也有反彙編命令disassemble(或者disas)

格式:

disas                                    

disas       程序計數器

disas       開始地址  結束地址

由此可見,在cpuid指令執行之前,EBX,ECX,EDX寄存器都是0,之後他們包含從廠商ID字符串來的值。

使用x命令顯示位於output變量前42個字節的內存位置的值(&符號表明是一個內存位置):

GDB的數據顯示格式:

x 按十六進制格式顯示變量。
d 按十進制格式顯示變量。
u 按十六進制格式顯示無符號整型。
o 按八進制格式顯示變量。
t 按二進制格式顯示變量。
a 按十六進制格式顯示變量。
c 按字符格式顯示變量。
f 按浮點數格式顯示變量。

查看寄存器和內存

1) info args
打印出當前函數的參數名及其值。
2)info locals
打印出當前函數中所有局部變量及其值。
3)info catch
打印出當前的函數中的異常處理信息。
4)源代碼的內存
你可以使用info line命令來查看源代碼在內存中的地址。info line後面可以跟“行號”,“函數名”,“文件名:行號”,“文件名:函
數名”,這個命令會打印出所指定的源碼在運行時的內存地址,如:
(gdb) info line tst.c:func
Line 5 of "tst.c" starts at address 0x8048456 <func+6> and ends at 0x804845d <func+13>.
5)info break
查看斷點信息。
6)info threads
看正在運行程序中的線程信息
7)info registers
查看寄存器的情況。(除了浮點寄存器)
8)info all-registers
查看所有寄存器的情況。(包括浮點寄存器)
9)info registers <regname >
查看所指定的寄存器的情況。

例如:info registers ebp

10)info frame或者i f
這個命令會打印出更爲詳細的當前棧層的信息,只不過,大多數都是運行時的內內
地址。比如:函數地址,調用函數的地址,被調用函數的地址,目前的函數是由什麼
樣的程序語言寫成的、函數參數地址及值、局部變量的地址等等

11)(gdb) disassemble func

disassemble可以查看源程序的當前執行時的機器碼,這個命令
會把目前內存中的指令dump出來

12)list

用list命令來打印程序的源代碼

13)x

可以使用examine命令(簡寫是x)來查看內存地址中的值.

x/3uh 0x54320表示,從內存地址0x54320讀取內容,h表示以雙字節爲一個單位,3表示三個單位,u表示按十六進制顯示。

x/48xw  $ebp   也可以一樣顯示改寄存器或者用上述方法按寄存器的地址

參考:GDB查看棧信息

查看進程

info proc

查看棧幀

bt

backtrace

info stack

where

都是一樣的只是別名而已

bt  顯示所有棧幀

bt N  顯示開頭N個棧幀

bt -N 顯示最後N個棧幀

bt full 顯示棧幀+局部變量

bt full N  N同前

監視

eatch <表達式>

<表達式>發生變化時暫停運行,此處<表達式>是常量或變量等

awatch <表達式>

<表達式>被訪問,改變時暫停運行

nwatch <表達式>

<表達式>被訪問時暫停運行

delete<編號>

刪除監視點

改變變量的值

set variable <變量><表達式>

例如:

(gdb) p  options

$7=1

(gdb)set variable options=0

(gdb)print options

$8=0

GDB命令

1)單步調試:

n (next),

ni(nexti) 執行下一行(以彙編代碼爲單位)

s(step 跟n的區別,s進入到函數內)

si(stepi) 執行下一行(以彙編代碼爲單位)

u(until)執行到指定行

2)恢復操作:c(continue或者cont) 直到遇到下個斷點

3)臨時斷點: tbreak 有效期,第一次遇到

4)檢查變量:p (printf)  顯示錶達式

x   顯示內存內容

5)監視點:watch 當監視點的值發生變化時停止

6)查看棧:bt(backtrace,where) 顯示整個棧的內容。

f(frame)選擇要顯示的棧幀

do(down) 在當前調用的棧幀中選擇要顯示的棧幀

7)看已經設的斷點: ib(info break)

8)設置斷點:break(b)

break function, break line_number, break filename:line_number, break filename:function

info break 查看斷點信息。

9)刪除斷點: d(delete),delete+數值標識符(從第7點可得到) (不加參數,刪除所有斷點), clear使用跟第8點對應

10)禁用斷點:disable+數值標識符 (重新啓用 enable)

11)在單步時跳出函數:finish

12)在單步時跳出循環:until

13)條件斷點:break break-arg if (condition),例: break main if argc > 1

14)斷點命令列表(到斷點自動執行):

commands breakpoint-number 例子:commands 1

... >printf "i = %d", i

commands >end

...

end

a) 在commands 中加入silent,過濾到其他無用的輸出。

b) 最後一個commands是continue的話,自動continue。

例:comands 1

> silent

> printf "i = %d", i

> continue

> end

15)查看局部變量:info locals 得到當前棧中所有局部變量的值列表

16)設置變量:set x=12

17)GDB線程命令:

a) info threads(給出當前所有的線程信息)

b) thread 3(切換查看線程)

c) break 88 thread 3(當線程3到達源代碼行88時停止執行)

d) break 88 thread 3 if x == y

e) thread apply all bt,查看所有的線程的棧信息。

18) 您可以以進程ID作爲第二個參數,以調式一個正在運行的進程

gdb 程序名 1234

19)finish運行到函數結束

20)forward-search(或者fo)  向前搜索

21)generate-core-file(或者gcore)  生成內核轉儲

22edit 編輯文件或函數

23)directory(或者dir)插入目錄

24)list(或者l)顯示函數或者行

25)info (或者i)顯示信息

26)help (或者h)顯示幫助

注意:

1)重新編譯文件時不要退出gdb,斷點可以保存着。

2)在調試時不要開啓優化代碼的選項,不然經過了優化,設置的斷點的位置跟編譯後的位置相差可能很大。

《深入理解計算機系統(原書第2版)》

更高級的GDB調試:

GDB attach到進程
————————————————
版權聲明:本文爲CSDN博主「unix21」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/unix21/article/details/8450016

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章