利用qemu進行核心源碼級調試

來源:互聯網
上載者:User

=================================
本文系本站原創,歡迎轉載!

轉載請註明出處:http://blog.csdn.net/gdt_a20

=================================

概要:看kernel代碼的時候,變數多了,就記不清楚了,尤其是讀記憶體部分代碼的時候,傳來傳去,常常不知道

改成什麼樣子了,記憶體布局到底變成什麼了,也許是我記憶力太不行了,利用qemu可以線上調試核心,
如同你用gdb調試app一樣,斷點,列印變數值等等,qemu算是個模擬器吧,說虛擬機器也可以,雖然bug很多,但是還不失為一個好工具,如果對qemu陌生,那android的模擬器相信大家都很熟悉了吧,那個也是基於開源的qemu修改的,好了讓我們趕快開始調試的旅程吧.

一、環境
 #$cat /etc/issue
  Ubuntu 11.10 \n \l
二、gdb準備
  #$$ gdb --version
  GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08
  Copyright (C) 2011 Free Software Foundation, Inc.
  License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  This is free software: you are free to change and redistribute it.
  There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
  and "show warranty" for details.
  This GDB was configured as "x86_64-linux-gnu".
  For bug reporting instructions, please see:

  <http://bugs.launchpad.net/gdb-linaro/>.

  我的gdb預設會有問題,當調試開啟後gdb vmlinux會出現:

  Remote 'g' packet reply is too long: 00000000000000000020e30100000000000000000000
  000060eecf81ffffffff000000010000000048eecf81fffff

  ...

  為瞭解決這個問題,我們需要重新編譯一個gdb,
 #$wget ftp://sourceware.org/pub/gdb/releases/gdb-7.4.tar.gz
  #$tar xzvf gdb-7.4.tar.gz
  #$cd gdb-7.4
  我們需要針對上面的問題做如下修改:
  在gdb/remote.c中
  注釋掉:
       

if (buf_len > 2 * rsa->sizeof_g_packet)           error (_(“Remote ‘g’ packet reply is too long: %s”), rs->buf); 

  並在後面添加:
 

if (buf_len > 2 * rsa->sizeof_g_packet) {      rsa->sizeof_g_packet = buf_len ;      for (i = 0; i < gdbarch_num_regs (gdbarch); i++)      {         if (rsa->regs[i].pnum == -1)         continue;         if (rsa->regs[i].offset >= rsa->sizeof_g_packet)         rsa->regs[i].in_g_packet = 0;         else         rsa->regs[i].in_g_packet = 1;      }   }

  configure前我們還要一個庫,texinfo,否則gdb編譯過程中會出現
  makeinfo錯誤:missing makeinfo --split-size=5000000  ...
  #$sudo apt-get install texinfo
  好了現在可以configure了,
  #$configure --prefix=/opt/gdb_7_4       //臨時裝在這裡吧
  #$mkdir /opt/gdb_7_4
  #$make && make install
三、kernel準備
  我們還需要一個bzImage,也就是個胖核心,qemu只鐘愛肥的,由於我們目的只在調試核心,所以別的
  可以不準備,有興趣的可以裝個整套的,做個虛擬機器看看,
  #$wget ftp://ftp.kernel.org/pub/linux/kernel/v3.x/linux-3.2.tar.gz
  #$tar xzvf linux-3.2.tar.gz
  #$cd linux-3.2/
  #$make defconfig  
  暫且用個x86做實驗,我們要用gdb串連,需要把調試資訊加入核心,
  否則gdb時候會出現:no debugging symbols found
  這裡就別去修改Makefile添加-g了,直接在核心配置選項裡開啟就可以.
   #$make menuconfig
   在kernel hacking中選中compile the kernel with debug info,
   這樣編譯出來的kernel才是真正的肥
   #$make bzImage
 
四、準備qemu.
  好了萬事具備可以開始qemu了,
  我們首先添加一個庫,不然qemu運行會卡在:
  VNC server running on `127.0.0.1:5900'
  #$sudo apt-get install libsdl1.2-dev
 
  #$wget http://wiki.qemu.org/download/qemu-1.0.tar.gz
  #$tar xzvf qemu-1.0.tar.gz
  #$sudo mkdir /opt/qemu_bin
  #$cd qemu-1.0
  #$./configure --prefix=/opt/qemu_bin --target-list=x86_64-softmmu
  我的系統是64的,這裡有i386-softmmu,arm平台等等,可以有選擇
  #$make && make install
  這樣就可以了,1.0的版本我這樣安裝使用後沒有遇到單步無法啟動並執行問題,
  但這個問題在以前版本確實存在,當初單步會直接跳到中斷裡面,
  如果有遇到這個問題的版本可以參考下面的修改(http://blog.chinaunix.net/space.php?uid=10285909&do=blog&id=2964933):

以qemu-0.9.0為例:  1 target-i386\cpu.h CPUX86State 結構加入:       int intr_cnt;  //當前的中斷深度       int intr_scnt; //儲存的中斷深度  2 vl.c main函數中加入初始化:       first_cpu->intr_cnt = 0;  3 target-i386\Helper.c 加入中斷深度的計算       do_interrupt_protected 函數中加入       env->intr_cnt++;       helper_iret_protected 函數中加入       env->intr_cnt--;  4 Exec.c cpu_single_step執行單步時儲存當前的中斷深度       env->intr_scnt = env->intr_cnt;  5 target-i386\Translate.c DisasContext結構加入:       CPUState *env;  6 target-i386\Translate.c gen_eob函數加入插入debug時的判斷       if (s->singlestep_enabled) {       if (s->env->intr_scnt==s->env->intr_cnt){//加了這個if判斷            gen_op_debug();            s->is_jmp = 3;            return;       }     }     在函數gen_intermediate_code_internal中加入:     dc->env = env;

五、運行調試
    
    #$/opt/qemu_bin/bin/qemu-system-i386 -S -kernel arch/x86/boot/bzImage -m 1024
    ctrl+alt+1 與 ctrl+alt+2可以切換,前者是螢幕輸出,後者是qemu控制台
   運行起來後是黑屏,我們要切換到控制台,用滑鼠點擊視窗,然後ctrl+alt+2,

   如所示輸入,然後斷行符號,ctrl+alt+1切換回來,ctrl+alt切出滑鼠.

 

   在另一個終端中,
    #$cd linux-3.2/
   #$/opt/gdb_7.4/bin/gdb vmlinux

   (gdb) target remote localhost:1234

 

  好了可以正式開始你的調試之旅了,可以先
   #b start_kernel

  #continue

  #list
  #n
  等等.
  注意:不要把vmlinux從源碼目錄考出來運行,因為gdb list是需要當前上下文列出代碼執行到哪裡的.
  另外-m 參數用於設定記憶體大小,這個在調試記憶體時候尤其有用,你可以清晰的列印除normal記憶體
  高端記憶體布局等等^.^!

  好了差不多就這麼多吧,最後附上幾幅:

===================================

================================

===================================

=================================

=================================

Thanks

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.