《電子技術應用》
您所在的位置:首頁 > 嵌入式技術 > 設計應用 > kgdb調試Linux內核的剖析與改進
kgdb調試Linux內核的剖析與改進
李紅衛1 李翠萍1 韓紅宇2
1. 常州江蘇技術師范學院(213001) ; 2. 阜新遼寧工程技術大學(123000)
摘要: 在Linux內核中加入kgdb,通過開發機上的gdb對目標機上的內核進行源代碼級的調試技術。
Abstract:
Key words :

摘   要: 在Linux內核中加入kgdb,通過開發機上的gdb對目標機上的內核進行源代碼級的調試技術。
關鍵詞: 遠程調試  kgdb  串口通信協議  異常處理

  操作系統的內核調試器除完成一般的調試功能外,還必須工作在內核中。因此,內核調試器與用戶級的調試器有很大的區別。在Linux系統中,對內核的調試有很多種方法,例如:可在內核中插入printk( )函數,將調試信息輸出,然后針對輸出的信息進行分析;可以使用/proc文件系統對內核進行分析;可以利用strace命令對系統調用進行分析。但這些方法都不能直接對內核源代碼級進行調試。因此,本文介紹一種在內核源代碼中插入kgdb(Kernel GNU Debuger,GNU內核調試器),通過開發機上的gdb調試器對運行于目標機上的內核進行源代碼級調試的技術。
1  kgdb調試內核的實現原理
1.1 通信協議
  kgdb提供了一種使用gdb調試Linux內核的機制。使用kgdb調試內核需要二臺機器,一臺作為開發機,另一臺作為目標機,通過串口將它們連接起來。在將要調試的內核中插入kgdb,重新編譯內核,使其運行在目標機上。而gdb在開發機上運行,gdb通過串口與要調試的內核進行通信,對目標機上的內核進行控制,從而實現遠程調試內核的目的。
  要使gdb有效地控制調試目標機上的內核,必須與目標機上的kgdb約定相互的通信協議。而gdb本身帶有一個遠程串行通信協議,所以在kgdb中包含相同的協議即可實現開發機與目標機之間的通信。
  開發機上的gdb可以向目標機發送一些命令數據包,如果kgdb能夠實現g、G、m、M、c和s等主要命令,則在使用gdb對目標機上的內核進行調試時就像在本機上調試程序一樣。這六個命令的功能描述如下:
  g:查看CPU寄存器的值;
  G:設置CPU寄存器的值;
  maddr,count:從addr位置開始讀count個字節的數據;
  Maddr,count:從addr位置開始寫count個字節的數據;
  c/caddr:在當前位置上繼續執行程序或從地址addr處開始執行;
  s/saddr:單步執行當前的指令,或者執行到指定的addr位置。
1.2 kgdb遠程調試技術分析
  遠程調試常采用插樁(stub)的方法實現。在目標操作系統內和開發機上的調試器內分別加入某些功能模塊(如通信模塊和異常處理模塊等),二者互通信息來完成調試工作,這些功能模塊統稱為插樁。gdb本身帶有這些功能模塊,所以在調試內核時,只需要在內核中加入stub插樁模塊即可實現用gdb遠程調試內核的目的。gdb遠程調試器的結構如圖1所示。


  通過對kgdb源程序進行分析可知,kgdb主要有二大模塊:一個是初始化模塊,完成初始化過程,接管所有異常、設置串口通信等低層實現;另一個是控制模塊,實現通信,對接收到的信息包進行解析并執行,對應答包進行打包發送。
1.2.1 kgdb初始化模塊的實現
  在Linux啟動時要調用start_kernel( )函數。該函數調用一系列初始化函數,完成系統初始化工作。kgdb通過對該函數進行修改,使其在內核初始化工作完成后將控制權交給插樁程序kgdb,由插樁程序完成調試內核的任務。
  (1)設置異常中斷處理程序入口
  kgdb插樁模塊要對目標機上被調試的程序進行控制,必須對目標機上所發生的所有異常進行統一管理。在上述Linux啟動過程中,若要執行start_kernel( )函數,則應在該函數中調用trap_init( )函數設置各種入口地址,如異常事件處理程序入口、系統調用入口等。其中trap0~trap19為各種異常事件錯誤入口,如被0除、溢出、存儲器越界等。為了使gdb能夠捕獲這些發生在目標機上的異常,kgdb要對各個需要捕獲的異常處理函數進行修改。當發生異常時使異常處理事件進入異常處理函數handle_excepton( ),han-
dle_excepton( )就會將目標機上發生的異常以信號“Sxx”的方式通知主機上的gdb,主機上的gdb即可知道目標機上發生的異常。
  (2)串口初始化
  將所有異常入口地址進行修改后,應該對串口進行初始化,并設置linux_debug_traps指針變量的值,使其指向異常處理程序入口地址。此工作結束后,kgdb就接管所有發生在目標機上的異常事件。
1.2.2 kgdb控制模塊的實現
  kgdb控制模塊主要完成對協議的解析和執行,這些功能都在handle_exception( )函數中實現。通過該函數可實現在內核中設置斷點、單步執行代碼和監視變量的值。
  handle_exception( )函數首先判斷CPU是否處于虛擬86模式或用戶態,若是則返回。由此可見,kgdb只對內核態程序進行調試。其次判斷是否發生讀/寫內存異常,若是則為讀/寫內存操作設置一個有效內存地址,返回重試,否則向主機發送信息“Sxx”,其中xx是發生異常的信號量值,即通知開發機上的gdb在目標機上發生了什么樣的異常。接下來handle_exception( )接收來自主機的調試命令,對來自主機的命令進行解析并完成命令的執行,在kgdb中主要完成的調試命令有m、M、g、G、s、c。當這些命令執行完后還需要向開發機發送應答信息,報告完成命令的情況。此函數的流程如圖2所示。


  (1)g讀寄存器命令的實現。當系統發生異常時,系統首先將發生異常的進程的CPU狀態保存在核心堆棧中。用g命令讀寄存器時,實際上就是從核心棧中去取,但gdb所規定的寄存器的排列與Linux內核中對寄存器的排列順序不一致,需要進行寄存器的轉換。通過函數regs_to_gdb_regs(gdb_regs,&regs)實現轉換,轉換結束后將寄存器的值打包送回主機。
  (2)G寫寄存器命令的實現。對接收到的數據包進行解包,把結果放入gdb_regs結構中,再通過gdb_regs_to_regs(gdb_regs,&regs)函數將接收到的寄存器的值進行轉換,并放入核心棧中,通過對核心棧的修改得到修改寄存器的目標。
  (3)讀/寫內存命令的實現。對內存的讀寫有可能再次發生讀寫內存異常。例如對一個非法的地址進行讀寫的kgdb解決方法如下:
  kgdb通過函數int get_char(char?鄢char)讀內存,通過函數void set_char(char?鄢addr,int val)寫內存。kgdb在讀/寫不確定的內存時,通過二個變量來判斷是否讀/寫內存發生異常。一個變量是kgdb_memerr_expected,標志是否讀寫不確定的內存;另一個變量是kgdb_memerr,標志在讀寫內存時是否發生了異常。這樣,對不確定內存的讀/寫過程可分三步。
  第一步:對這二個變量賦值。將kgdb_memerr_expected賦值為1,表示對不確定內存進行讀/寫操作。對kgdb_me-merr賦值為0,表示在讀/寫內存時沒有發生異常。
  第二步:對內存進行讀寫操作。若讀寫地址是非法地址,則進入異常處理程序,轉第三步。若正確,則返回,并清變量kgdb_memerr_expected為0,表示讀寫內存結束。
  第三步:進入異常處理程序中。首先要判斷kgdb_me-merr_expected是否為1。若是1,則說明對內存讀/寫時發生了異常。這時先清kgdb_ memerr_expected為0,置kgdb_memerr為1,標志在讀/寫內存時發生了異常,并為讀/寫內存設置一個有效地址。這個有效地址是一個可讀/寫的內存地址,可以對其進行操作,操作的結果是無效的。
  (4)s單步命令的實現。基于x86 CPU的體系結構支持單步執行,但它只是指令級的單步,而不是源代碼級的單步。這里的s命令是實現指令級的單步,它的處理方法是:將產生異常的進程標志寄存器的陷阱標志位TF置1,異常中斷處理程序結束返回到異常點繼續執行。因TF標志位為1,所以程序執行一條指令后又進入異常處理程序。主機處的gdb利用此命令實現源代碼級的單步跟蹤。
  (5)c繼續運行命令的實現。異常處理程序結束,恢復異常處的CPU狀態,使程序繼續執行。
2  kgdb插樁技術的不足與改進
  現有的kgdb不具有使目標程序進行調試模式和正常運行模式的切換功能。目前的處理方法是:當程序調試好后,將kgdb卸下,重新編譯程序。當發生錯誤時再將kgdb插入目標程序中,編譯后再在目標機上調試。由此可見操作十分不便。本文提出一種新的設計思路,使目標機上運行的程序可隨時進行調試模式與正常運行模式的切換,這樣更便于調試。下面討論其實現方法。
   (1)在目標機方:通過對kgdb源代碼分析可知,在進入各異常函數中,首先判斷指向gdb_debug_hook類型的函數指針變量linux_debug_hook是否為空。若不為空則執行異常處理函數handle_exception( ),否則,執行原異常處理程序。這樣通過修改這個變量的值,即可實現調試模式與正常運行模式的轉換。當設置linux_debug_hook為(gdb_debug_hook?鄢)NULL時,目標機程序運行在正常運行狀態;當設置linux_debug_hook為指向異常函數handle_exception( )時,則目標機程序運行在調試狀態。
   (2)在主機方:調試狀態到正常運行狀態的轉換:在kgdb中設置一個變量int stop_gdb。當主機對該變量進行賦值時,目標機上的kgdb獲取信息后,使指向函數的指針變量linux_debug_hook指向(gdb_debug_hook?鄢)NULL,然后,kgdb構造c命令并執行,使目標機上的程序脫離調試運行模式進入正常運行模式。
  主機端發送命令:set stop_gdb=1
  這條命令經過主機端的gdb解析,實際上是執行協議命令M,即寫內存命令。這樣就需要在kgdb中對M命令進行修改。
  目標端kgdb 執行M命令的算法描述如下:
  (1)向主機返回應答信息“OK”;
  (2)如果所寫地址與變量stop_gdb的地址相同,則轉(4);
  (3)執行原M命令,轉(8);
  (4)設置變量initialized為0;
  (5)設置指針變量linux_debug_hook為(gdb_debug_hook*)NULL;
  (6)構造命令c;
   (7)執行命令c,目標機上被調試的程序轉為正常運行模式;
  (8)結束。
  正常運行狀態到調試狀態的轉換:目標程序從正常運行狀態切換到調試狀態,就不像從調試狀態到正常運行狀態切換那樣對一個變量進行設置而觸發狀態的切換。因為目標機已不在主機端gdb的控制下運行,主機端的gdb與目標機端的kgdb已失去了聯系。所以要激活目標機進入調試狀態,只能使用中斷技術,利用串口中斷來激活對目標機由正常運行狀態切換到調試狀態。
  在gdb與目標機建立連接時,gdb首先要向目標機發送一個數據包$Hc-1#09,它會觸發目標機上串口中斷處理程序的執行,并判斷接收的數據包是否為“Hc-1”。若是則設置linux_debug_hook指向異常中斷處理程序handle_exception( ),并執行breakpoint( )函數,使目標機進入調試狀態。
  通過上述方法即可實現目標機上程序運行狀態的切換,使程序調試更加靈活。
3  結束語
  通過對kgdb調試技術的分析與改進,增加了調試的方法和思路。此調試技術可以應用于嵌入式系統的設計和開發中,為嵌入式開發工具增加了一種廉價而強有力的調試工具。
參考文獻
1   李善平,劉文峰.Linux內核2.4版源代碼分析大全.北京: 機械工業出版社,2002
2   李紅衛,李翠萍.嵌入式軟件的調試技術.計算機時代,2002;(8)
 

此內容為AET網站原創,未經授權禁止轉載。
亚洲一区二区欧美_亚洲丝袜一区_99re亚洲国产精品_日韩亚洲一区二区
亚洲一区一卡| 美女视频黄免费的久久| 亚洲第一主播视频| 午夜精品亚洲一区二区三区嫩草| 99这里有精品| 亚洲电影天堂av| 国内精品视频在线观看| 国产一区二区三区四区hd| 国产精品在线看| 国产免费观看久久黄| 国产精品无人区| 国产九色精品成人porny| 国产精品捆绑调教| 国产精品实拍| 国产日韩欧美中文| 国产亚洲成人一区| 狠狠色综合网站久久久久久久| 国产日韩一区在线| 激情小说亚洲一区| 亚洲第一精品影视| 亚洲黄一区二区三区| 亚洲激情成人| 亚洲久久成人| 中文欧美字幕免费| 亚洲免费视频成人| 欧美中文字幕久久| 亚洲国产日韩欧美在线99| 日韩视频中文字幕| 一区二区三区日韩欧美精品| 亚洲网在线观看| 欧美一级夜夜爽| 久久蜜桃精品| 欧美大片网址| 欧美特黄一级| 国产视频一区二区在线观看 | 欧美午夜精品一区| 国产精品欧美日韩一区二区| 国产免费成人在线视频| aa成人免费视频| 日韩一级网站| 亚洲一区二区在| 欧美一区二区三区的| 久久久777| 欧美精品91| 国产精品一区二区a| 国产主播精品在线| 亚洲国产日韩欧美| 亚洲一二三区在线| 欧美与黑人午夜性猛交久久久| 亚洲国产欧美日韩精品| 99精品视频一区| 性做久久久久久久久| 免费成人黄色片| 欧美日韩综合精品| 国产一区二区三区电影在线观看| 亚洲电影免费在线| 亚洲一区二区影院| 亚洲第一在线综合网站| 在线一区二区三区四区五区| 欧美一级成年大片在线观看| 欧美va亚洲va香蕉在线| 国产精品卡一卡二卡三| 亚洲第一网站| 亚洲免费小视频| 亚洲日本成人| 欧美亚洲视频在线看网址| 男人的天堂亚洲| 国产精品一区二区你懂的| 亚洲成人影音| 亚洲欧美日韩国产中文| 亚洲伦理一区| 久久久久国产精品一区| 欧美日韩一区二区三区在线| 国产一级一区二区| 9色精品在线| 亚洲电影下载| 午夜亚洲性色视频| 欧美日韩成人| 在线视频观看日韩| 欧美一区三区三区高中清蜜桃| 一区二区三区导航| 久久综合九九| 国产视频不卡| 亚洲自拍偷拍色片视频| av成人手机在线| 理论片一区二区在线| 国产欧美日韩在线视频| 亚洲国产精品久久久久婷婷884| 亚洲综合国产| 一卡二卡3卡四卡高清精品视频| 久久久免费av| 国产人成精品一区二区三| 99国产精品自拍| 亚洲精品视频免费观看| 久久久水蜜桃| 国产免费成人| 亚洲综合另类| 亚洲一区综合| 欧美日韩久久不卡| 亚洲国产电影| 亚洲高清一区二| 久久国产精品久久国产精品| 国产精品久久激情| 亚洲久久视频| 日韩视频在线观看国产| 欧美jizz19hd性欧美| 狠狠综合久久av一区二区老牛| 性欧美长视频| 欧美主播一区二区三区| 国产精品蜜臀在线观看| 在线天堂一区av电影| 亚洲天堂视频在线观看| 欧美日韩国产精品 | 亚洲一区自拍| 亚洲女同精品视频| 欧美视频三区在线播放| 99国产精品久久| 亚洲视频一区在线| 欧美日韩小视频| 亚洲美女av黄| 中日韩高清电影网| 欧美日韩亚洲一区二区| 亚洲精品女人| 中文精品视频| 欧美日韩中文字幕日韩欧美| 99国产精品国产精品毛片| 亚洲一区二区三区四区五区午夜 | 亚洲午夜小视频| 国产精品国产一区二区| 一区二区久久| 亚洲男人影院| 国产女优一区| 久久大逼视频| 麻豆av福利av久久av| 亚洲二区精品| 亚洲欧洲日产国产网站| 欧美精品aa| 一本色道婷婷久久欧美| 亚洲在线观看免费视频| 国产精品一区=区| 欧美在线影院| 鲁大师影院一区二区三区| 亚洲国产经典视频| aa级大片欧美| 国产精品国内视频| 午夜精品一区二区三区在线| 久久精品在线观看| 亚洲黄色毛片| 亚洲免费在线视频| 国产一区二区精品久久| 亚洲国产成人在线| 欧美二区不卡| 在线视频亚洲欧美| 久久精品天堂| 亚洲人被黑人高潮完整版| 亚洲免费视频中文字幕| 国产日本欧美一区二区三区在线| 久久精品99| 欧美日韩国产美女| 亚洲主播在线| 美女视频黄免费的久久| 99国产精品视频免费观看一公开| 亚洲欧洲av一区二区三区久久| 国产日韩亚洲欧美综合| 亚洲精品小视频在线观看| 欧美特黄一区| 亚洲福利视频网| 欧美日韩在线精品| 欧美在线|欧美| 欧美久久久久久蜜桃| 亚洲综合精品| 欧美大尺度在线观看| 亚洲免费影院| 欧美风情在线观看| 亚洲一区二区三区四区五区黄| 久久精品日韩| 日韩一二三区视频| 久久久爽爽爽美女图片| 日韩午夜在线观看视频| 久久精品国产77777蜜臀| 亚洲肉体裸体xxxx137| 欧美一进一出视频| 亚洲国产美女精品久久久久∴| 亚洲摸下面视频| 亚洲第一精品影视| 午夜精品久久久久久久久久久久| 一区二区三区在线看| 亚洲欧美电影院| 亚洲二区视频在线| 欧美一区二区国产| 亚洲欧洲在线视频| 久久精品二区三区| 一区二区三区视频在线看| 免费高清在线视频一区·| 亚洲在线免费视频| 欧美精品一区二区高清在线观看| 午夜日韩激情| 欧美日韩在线视频一区| 亚洲激情欧美激情| 国产女人18毛片水18精品|