ubuntu: qemu+gdb 調試linux kernel 學習筆記

 

聲明:html

  本筆記內容並不是本人原創,90%來自網絡資料的整合。同時,因爲本身是剛剛接觸qemu & gdbserver remote debug,本文也就算不得教程,僅供有緣人蔘考而已。linux

------------------------------------------------------------------------------------------------分割線---------------------------------------------------------------------------redis

step 1:  kernel 編譯環境安裝shell

  

apt-cache search build-essential
sudo apt-get install build-essential -y

apt-cache search libncurses-dev
sudo apt-get install libncurses-dev -y

固然,可能還須要其餘一些工具,若是gcc  g++ make 之類的工具,畢竟build-essential是一個工具箱子,如有潔癖,可能就有點衝突。而ncurses-dev,這個是必需要有的,我記得在fedora上是直接yum install ncurses-dev便可,.deb系列的彷佛是加了個前綴。ubuntu

 

step 2:   gdb的安裝vim

  須要告訴的是,build-essential 裏應該是包含了一個gdb & gdbsever工具了,可是很抱歉的是沒法使用,會出現這個錯誤:bash

    

Remote 'g' packet reply is too long: 000000000000000020000000000000004000000000000000001006000000000000f009000000000028aece81ffffffff981fc081ffffffff901fc081ffffffff0030c1010000000000000000000000000000000000000000f0b926020000000020f1d281ffffffffb01fc081ffffffff00e0e681ffffffff0010e781ffffffff02fbd281ffffffff9600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000

  因而,咱們須要去下載一個比較新的gdb source下來(我使用的是7.8),網址是: http://ftp.gnu.org/gnu/gdb/網絡

  

http://ftp.gnu.org/gnu/gdb/

  而後按照網絡前人們共享出來的資料,修改gdb的源碼:  在 gdb-7.8/gdb/remote.c 文件的 static void process_g_packet (struct regcache *regcache)函數裏面修改部份內容,以下:eclipse

 1 static void
 2 process_g_packet (struct regcache *regcache)
 3 {
 4   struct gdbarch *gdbarch = get_regcache_arch (regcache);
 5   struct remote_state *rs = get_remote_state ();
 6   struct remote_arch_state *rsa = get_remote_arch_state ();
 7   int i, buf_len;
 8   char *p;
 9   char *regs;
10 
11   buf_len = strlen (rs->buf);
12 
13   /* Further sanity checks, with knowledge of the architecture.  */
14 /*  if (buf_len > 2 * rsa->sizeof_g_packet)
15     error (_("Remote 'g' packet reply is too long: %s"), rs->buf);
16 */
17   /*modify by xx*/
18   if (buf_len > 2 * rsa->sizeof_g_packet) {
19     rsa->sizeof_g_packet = buf_len;
20     for (i = 0; i < gdbarch_num_regs(gdbarch); i++) {
21         if (rsa->regs[i].pnum == -1)    
22             continue;
23         if (rsa->regs[i].offset >= rsa->sizeof_g_packet)
24             rsa->regs[i].in_g_packet = 0;
25         else
26             rsa->regs[i].in_g_packet = 1;
27     }
28   }
29   //.......
30     }
31     }
32 }

  上面的14-15行是原來文件的,而18-27行是從新添加上的 <爲了節約版面,我沒有貼後面的,因此,注意 " { } "  可能致使的語法錯誤>,這樣修改的具體原理,本人並不清楚,但確實解決了問題。tcp

  修改完整後,就開始編譯gdb吧。在 gdb-7.8/  下執行下面的命令:

1 ./configure --prefix=../../tools/
2 make 
3 make install

  須要注意的是在gdb-7.8/  目錄下並無Makefile文件,須要使用 ./configure來生產。在配置的時候,若是要指定gdb安裝的路徑(目錄),那麼就須要跟上  --prefix=$PATH的相關參數,通常這種狀況可能會針對系統已經有一個gdb了但沒法使用,同時也未刪除,那麼新編譯的gdb可能須要安裝在另外的目錄了。固然我本身的是安裝在 ../../tools/ 目錄下。

 

step 3: 編譯linux kernel

  去 www.kernel.org下載本身須要的版本,待完畢後,對kernel編譯生成bzImage  &  vmlinux 文件。若是是和我同樣剛入門的,能夠參考如下命令&步驟:

  

cd  linux-3.12.35/
cp /boot/config-3.13.0-43-generic .config
make menuconfig
<save>
make bzImage

  須要說明的是,具體要看哪些調試信息,應該在make menuconfig的時候去配置,去選擇,而後保存好後,就編譯。編譯後,bzImage這個是被壓縮了的,供qemu虛擬機使用,vmlinux裏面帶了某些信息,沒有壓縮,供gdb使用。

  當編譯結束後,能夠將vmlinux bzImage文件copy到一個乾淨的目錄下吧---這個隨本身的習慣了,不copy也無所謂了。

  上面忘記了準備最重要的東西了: qemu

step 4: qemu的使用

  簡單說下: qemu 是一款虛擬機,能夠模擬x86 & arm 等等硬件平臺<彷佛可模擬的硬件平臺不少...>,而qemu 也內嵌了一個 gdbserver。這個gdbserver因而就能夠和gdb構成一個遠程合做夥伴,經過ip:port 網絡方式或者是經過串口/dev/ttyS*來進行工做,一個在這頭,一個在那頭。

  至於安裝qemu虛擬機,能夠經過源碼編譯,make & make install ,在這裏能夠下載:http://wiki.qemu.org/Download。也能夠直接在ubuntu 軟件包裏apt-get install  qemu-kvm便可。這裏不詳細記載了。當安裝後,可能的文件是這些:

1 qemu-system-i386
2 
3 qemu-system-x86_64
4 
5 qemu-img
6 
7 qemu-io
8 ....

  這個是什麼意思呢? 第一行的表示是 i386機器上使用的qemu虛擬機,第二行表示是 x86_64上使用的虛擬機。另外的就沒使用過了。具體的請參考官網文檔:http://wiki.qemu.org/Main_Page。固然,我本身的系統是 x86_64的,使用的是第二個。

 

step 4: 讓kernel爲你稍帶片刻~

  

1 qemu-system-x86_64 -kernel ./bzImage -initrd ./initrd.img -smp 2 -gdb tcp::1234  -S

  先使用命令啓動qemu。

  qemu-system-x86_64的參數比較多,這裏簡單說下:

  -kernel 是指定一個大內核文件,當仁不讓的是bzImage。

  -initrd 是指定一個 initrd.img文件,這個文件能夠從   /boot/initrd.img-3.13.0-43-generic  拷貝而來,關於它是什麼東西呢? 能夠參考這個: http://www.linuxfly.org/post/94/ ,或者是這個 http://blog.csdn.net/chrisniu1984/article/details/3907874  。

  -smp 能夠從名字猜測,它是給qemu指定幾個處理器,或者是幾個線程<嗯,大概意思就thread吧>。

  -gdb則是啓動qemu的內嵌gdbserver,監聽的是本地tcp端口1234---若是這樣寫:   -gdb tcp:192.168.1.100:1234 ,彷佛也是沒問題的。

  -S 就是掛起gdbserver,讓gdb remote connect it。還有一個-s,那是另一種狀況要使用了。

  若是本身嫌敲命令麻煩<雖然那很酷>,可使用如下的方式,將該命令保存到某個文件中,好比 qemu.start:

  

1 #!/bin/bash
2 qemu-system-x86_64 -kernel ./bzImage -initrd ./initrd.img -smp 2 -gdb tcp::1234  -S
3 <save>
4 chmod  +x qemu.start
5 
6 ./qemu.start

  這樣就能夠啓動qemu了 <注意本身的 bzImage & initrd.img 文件的路徑>

  提示:  man qemu-system-x86_64,你會得到一些幫助。

 

step 5: 使用gdb去鏈接已將啓動了的qemu:

  

 1 ../tools/gdb/bin/gdb vmlinux 
 2 
 3 -----
 4 GNU gdb (GDB) 7.8
 5 Copyright (C) 2014 Free Software Foundation, Inc.
 6 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 7 This is free software: you are free to change and redistribute it.
 8 There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
 9 and "show warranty" for details.
10 This GDB was configured as "x86_64-unknown-linux-gnu".
11 Type "show configuration" for configuration details.
12 For bug reporting instructions, please see:
13 <http://www.gnu.org/software/gdb/bugs/>.
14 Find the GDB manual and other documentation resources online at:
15 <http://www.gnu.org/software/gdb/documentation/>.
16 For help, type "help".
17 Type "apropos word" to search for commands related to "word"...
18 Reading symbols from vmlinux...done.
19 -----
20 
21 (gdb) target remote : 1234
22 Remote debugging using : 1234
23 0x0000000000000000 in irq_stack_union ()
24 
25 (gdb) b start_kernel
26 Breakpoint 1 at 0xffffffff81d2fb02: file init/main.c, line 476.
27 
28 (gdb) c
29 Continuing.
30 
31 Breakpoint 1, start_kernel () at init/main.c:476
32 476    {
33 
34 
35 (gdb) n
36 485        smp_setup_processor_id();
37 (gdb) n
38 491        boot_init_stack_canary();
39 (gdb) n
40 493        cgroup_init_early();

  第一行代表啓動我本身編譯的gdb,這有兩個方式  :  gdb    fileName 啓動,或者 gdb啓動後,再使用 file   fileName 啓動

  第21行代表鏈接遠程gdbserver,因爲這是在同一檯筆記本上,就沒有指定ip地址,僅僅指定了port號碼。----固然,若是是鏈接uart口,也行。

  第25行,是break一個斷點,在某個函數的入口處  。

  第28行,應該是發一個命令,讓qemu那邊繼續運行的意思,這個時候,qemu那邊的屏幕上會閃現出:"Booting from ROM..."

  後面啊,就是下一步下一步的意思咯: next ...  next ...   固然,也能夠選擇step   step   s....  直到哪裏纔會在qemu那邊打印消息呢? 要在 console_init();這行代碼後纔會的。

 

  作一個稍微重要的說明: 我這裏並無啓用文件系統,若是有須要,能夠試着用busybox作一個,而後參考qemu kernel調試手冊,或者網絡資源進行加入調試便可。

--------------------------------------------------------------------------------------扯淡分割線--------------------------------------------------------------------------------------------

後記:

  至於gdb 的命令,還有不少不少,若是是new to kernel的話,請點擊這裏:    http://www.sourceware.org/gdb/   最好的是慢慢啃官網文檔,而後再看看別人的理解,應該就差很少了。或者看看這個: http://www.yolinux.com/TUTORIALS/GDB-Commands.html

  這幾天也一直在搜索kernel debug的方法,qemu+gdb 是一種,固然也還有其餘的方法。不過總結下來,代價以qemu+gdb最小。若是你是大屏幕pc,能夠試試將qemu+gdb+eclipse這樣,歸入IDE環境。而本身是筆記本,就不湊合IDE了,在vim  shell 下足以。

  稍微夾雜一點想法: 前面也是看了一些操做系統的書+linux kernel的入門讀物,可是一直沒機會去試着單步運行如下kernel,看看它是怎麼走的<書中搭建方式花銷比較大:要麼就是兩臺電腦,要麼就是搞一半就會放棄的那種>。長此以往,也就懈怠了,更別說再去詳細的看代碼了。linux kernel是真的很偉大,但不必神話它。若是對操做系統原理和程序設計的理解達到必定水平,本身也能夠整一個OS---儘管那可能會很粗糙。因而,知行合一也就有必要了。

  最後就是,若是真對kernel有興趣,那起碼得把英語搞一搞,而後儘早關注kernel MailList----雖然是萬變不離其宗,但世界也是發展變化的。書上多少是有時限的。

 

 

關鍵字: qemu kernel gdb gdbserver 調試

相關文章
相關標籤/搜索