Linux Kernel -- Debug VirtualBox

本文介绍如何利用kgdb-light调试器在VirtualBox环境下调试Linux内核。首先需配置虚拟机串口,并确保内核支持kgdb。然后安装socat和gdb,通过特定命令设置调试参数,实现内核模块的符号加载及变量修改。

references:

http://fotis.loukos.me/blog/?p=25



Kgdb is a source level debugger for the linux kernel. It requires two machines, one running a kernel compiled with kgdb enabled and the second one running gdb. It can be found atsourceforge and a light version has been merged into the 2.6.26 kernel. There is anarticle at kerneltrap which contains all the appropriate information about this light version and it’s differences from the full one. I am going to describe how you can debug a linux kernel running under VirtualBox using the kgdb-light debugger.

First of all you must define a serial port. Go to the settings of your virtual machine, then at the “Serial Ports” and enable “Port 1″. Use port number COM1, port mode ‘Host Pipe’, check ‘Create Pipe’ and enter a path, e.g. /home/fenggxin/myvm/serila1. You can use another port number, e.g. COM2, but then you’ll have to change the device below to ttyS1, ttyS2 for COM3 etc. Furthermore, you can create the pipe yourself and not automatically using:

$mkfifo/home/fenggxin/myvm/serial1
This will create a fifo file in your host machine.

At your virtual machine you must have a kernel compiled with the option CONFIG_KGDB. You can find this under the “Kernel debugging” menu. I also advise you to enable the CONFIG_DEBUG_INFO to insert debug symbols.

"It seems that when CONFIG_DEBUG_RODATA is 'y', kgdb is unable toaccess its datastructures required to set a breakpoint.Disabling the config option fixes the problem."

.config like this,

  CONFIG_DYNAMIC_PRINTK_DEBUG=y
  # CONFIG_SAMPLES is not set
  CONFIG_HAVE_ARCH_KGDB=y
  CONFIG_KGDB=y
  CONFIG_KGDB_SERIAL_CONSOLE=y


At the host machine you only need to install socat and of course gdb. Socat is a multipurpose relay which can be foundhere. You should also transfer theuncompressed image of the kernel running at the vm. It can be found at the directory where you compiled the kernel and it’s name will be vmlinux.

You are now ready to start. At the host machine run:

$socat-d-d/home/fotisl/virtualbox/myvm/serial1pty:
2009/01/0100:00:00socat[12345]NopeningconnectiontoAF=1"/home/fotisl/virtualbox/myvm/serial1"
2009/01/0100:00:00socat[12345]NsuccessfullyconnectedfromlocaladdressAF=1"\x04\b\xAB"
2009/01/0100:00:00socat[12345]Nsuccessfullyconnectedvia\xD0\xA7\x10
2009/01/0100:00:00socat[12345]NPTYis/dev/pts/4
2009/01/0100:00:00socat[12345]NstartingdatatransferloopwithFDs[3,3]and[4,4]

You must note the PTY, in this case /dev/pts/4. Now fire gdb and load vmlinux. Then set the remote baud to 115200 and attach to the serial port.
$gdb~/vmlinux
GNU gdb(GDB)6.8.50.20090628-cvs-debian
Copyright(C)2009FreeSoftwareFoundation,Inc.
License GPLv3+:GNUGPLversion3orlater<http://gnu.org/licenses/gpl.html>
Thisisfreesoftware:youarefreetochangeandredistributeit.
There isNOWARRANTY,totheextentpermittedbylaw.  Type"show copying"
and"show warranty"fordetails.
ThisGDBwasconfiguredas"i486-linux-gnu".
Forbugreportinginstructions,pleasesee:
<http://www.gnu.org/software/gdb/bugs/>...
(gdb)setremotebaud115200
(gdb)targetremote/dev/pts/4
Remotedebuggingusing/dev/pts/4
Now switch to the virtual machine. You must first set the serial port that kgdb will use.
# echo ttyS0,115200 > /sys/module/kgdboc/parameters/kgdboc

You’re ready to start debugging! When you want to break use the Alt-SysRq-G key combination or use
# echo g > /proc/sysrq-trigger
This let target kernel waiting for gdb to start.

now, start gdb to,
$gdb~/vmlinux
(gdb)setremotebaud115200
(gdb)targetremote/dev/pts/4
(gdb)target remote put         #this can kill gdb process, let it quit

push your module chardev.ko to virtualbox,
in virtual machine,
#insmod chardev.ko
#lsmod


chardev 3040 0 - Live 0xd07fd000

In host machine, you need to find out the offset of the text section within the module,
http://freebsd.unixtech.be/doc/en/books/developers-handbook/kerneldebug-kld.html

#objdump --section-headers  ./chardev.ko | grep text

  1 .text         00000324  00000000  00000000  00000058  2**2

The 2nd method for it is, in virtual machine,
#/sys/module/chardev/sections
#ll -a
#cat .bss           #this is address of global begin address
#cat .text          #this is address of symbol, when add-symbol-file, can use this address


The fourth hexadecimal field (sixth field overall) is the offset of thetext section within the file. Add this offset to the load address of the module to obtainthe relocation address for the module's code. In our example, we get0xd07fd000 +00000000=0xd07fd000. Use the add-symbol-file command in GDB to tell the debugger about the module:

(kgdb) add-symbol-file /sys/modules/linux/linux.ko 0xd07fd000
add symbol table from file "/sys/modules/linux/linux.ko" at text_addr = 0xc0ae22d0?
(y or n) y
Reading symbols from /sys/modules/linux/linux.ko...done.
(kgdb)


If you want to use kgdbwait to start the debugging when the kernel starts loading, there is a patch for grub,
From 42536359a093dbe104336d4552903d 411cdae17b Mon Sep 17 00:00:00 2001
From: Tomasz Hliwiak <tomasz.hliwiak@tieto.com>
Date: Thu, 12 Jul 2012 13:27:09 +0200
Subject: [PATCH] Enable KGDB on kernel start
 
Change-Id: I85ccd59b56df430c83eb09ab738bd 7a406d1a054
---
stage2/preset_menu.c |    4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
 
diff --git a/stage2/preset_menu.c b/stage2/preset_menu.c
index e968049..a08613d 100644
--- a/stage2/preset_menu.c
+++ b/stage2/preset_menu.c
@@ -12,4 +12,8 @@ const char *preset_menu =
     "title Android Startup from /dev/sda\n"
     "       cmdline (hd0,2)/cmdline\n"
     "       kernel --use-cmd-line (hd0,2)/kernel\n"
+    "       initrd (hd0,2)/ramdisk\n"
+    "\n"
+    "title Android KGDB Startup from /dev/sda v0.4\n"
+    "       kernel (hd0,2)/kernel qemu=1 console=ttyS0 console=tty0 vga=788 verbose androidboot.hardware=vbox_x86 androidboot.console=ttyS0 android.qemud=ttyS1 kgdboc=ttyS0,115200 kgdbwait\n"
     "       initrd (hd0,2)/ramdisk\n";
--
1.7.8.3

$ cd $ANDROID/external/grub
$patch -p1 < patchname

compile goldfish kernel, there will be an option  in grub menu.


QA:
 


1.  How to modify global variables in gdb


I have global int *buf123 in my code, but when I try to read the value I got message:

(gdb) p buf123Cannot access memory at address 0x480(gdb) p &buf123$46 = (int **) 0x480

Steps:

  1.       1. Check module section addresses on target, so You can give those in add-symbol-file cmd:

     cd /sys/module/ai_char_dev/sections

     cat .data

     cat .bss

     cat .txt

    2. 

            Load symbols in gdb host:

            (gdb) add-symbol-file /home/xtomhli/aosp/02_07_11/kernel-goldfish/drivers/android_incubator/ai_char_dev.ko 0xf8470000 -s .bss 0xf8470a94 -s .data 0xf8470908

add symbol table from file "/home/xtomhli/aosp/02_07_11/kernel-goldfish/drivers/android_incubator/ai_char_dev.ko" at
  .text_addr = 0xf8470000
  .bss_addr = 0xf8470a94
  .data_addr = 0xf8470908


  3.  
Now You can print data:

(gdb) p buf123
$3 = (int ) 0xf306aa00
(gdb) p
buf123
$4 = 269488144


If for some reason You still cant access those by name, You can always use addresses.

objdump --section-headers ai_char_dev.ko   # prints section headers offsets

objdump -t ai_char_dev.ko         #prints data location in section (+offset in section)

If You want to access one of variables, for example globalint major do:-

objdump -t ai_char_dev.ko | grep myvarialname  # find major variable in output (in my case it's"00000070 l O .bss 00000004 major", so it's located in bss with 0x70 offset)- knowing the address of bss section from "cat /sys/module/ai_char_dev/sections/.bss",

You can access variable by it's address:

(gdb) p *(0xf8470a94 + 0x70)

$37 = 248


modify it,
(gdb) set {int}(0xf8470a94 + 0x70) = 99

modify char buffer,
(gdb) set Message[o]='a'
(gdb) set Message[1]='b'




2. 

like this,

(gdb)print  i

$1 = < value optimized out >


Add    EXTRA_CFLAGS += -g -O0  in your module Makefile, do not optimize your module.

This solution can also resolve the problem that  the break point can not stop at the accurate code line.


3.

How to enble Dynamic Debug for goldfish(kernel 2.6.29)

Please refer to

http://cateee.net/lkddb/web-lkddb/DYNAMIC_PRINTK_DEBUG.html

http://lxr.linux.no/#linux+v3.4.4/Documentation/dynamic-debug-howto.txt



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值