聲明: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 調試