免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 992 | 回复: 0
打印 上一主题 下一主题

kgdb manual 2 (转) [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-22 08:51 |只看该作者 |倒序浏览
continue 

【 模块调试 】

『 内联函数 』
对于模块的步骤是有些不同的,因为模块目标文件中是不包含绝对地址的。

( 步骤的相关说明和实例将被添加  http://kgdb.linsyssoft.com/inlinemodules.htm )


『 卸载和装载模块 』
同第三节的相关内容


『 loadmodule.sh的工作 』
相关内容只针对kgdb1.8或早些的。

---目标文件段---
假设是 trfs 模块目标文件。文件中包含的段可以使用 objdump 来列出。

$ objdump -h trfs

trfs:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000162c  00000000  00000000  00000040  2**4
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .text.lock    0000010a  00000000  00000000  0000166c  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  2 .rodata       000002a4  00000000  00000000  00001780  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 __ksymtab     00000020  00000000  00000000  00001a24  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
  4 .kstrtab      0000006f  00000000  00000000  00001a60  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .modinfo      00000111  00000000  00000000  00001acf  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .data         00000178  00000000  00000000  00001be0  2**5
                  CONTENTS, ALLOC, LOAD, RELOC, DATA
  7 .bss          00000010  00000000  00000000  00001d58  2**2
                  ALLOC
  8 .stab         0003b8b0  00000000  00000000  00001d58  2**2
                  CONTENTS, RELOC, READONLY, DEBUGGING
  9 .stabstr      000e32bd  00000000  00000000  0003d608  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .comment      000001ab  00000000  00000000  001208c5  2**0
                  CONTENTS, READONLY
 11 .note         0000008c  00000010  00000010  00120a70  2**0
                  CONTENTS, READONLY



.text 是代码段, .data 包含初始化数据, .bss包含 未初始化数据。调试信息包含在 .stab 和 .stabstr段中。

VMA 是 段的虚拟地址。因为文件仍未重定位,所以 所有段的VMAs都为 0 。

内核目标文件--vmlinux ,被重定位。所以vmlinux中段的VMAs出现在进程虚拟地址空间的地方,拥有实际地址。

$ objdump -h vmlinux

vmlinux:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0014ed2b  c0100000  c0100000  00001000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .text.lock    00009579  c024ed30  c024ed30  0014fd30  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .rodata       00048061  c02582c0  c02582c0  001592c0  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .kstrtab      0000a200  c02a0340  c02a0340  001a1340  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 __ex_table    00001848  c02aa540  c02aa540  001ab540  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 __ksymtab     000023f0  c02abd88  c02abd88  001acd88  2**2
                  CONTENTS, ALLOC, LOAD

, READONLY, DATA
  6 .data         0001a200  c02ae180  c02ae180  001af180  2**5
                  CONTENTS, ALLOC, LOAD, DATA
  7 .data.init_task 00002000  c02ca000  c02ca000  001ca000  2**5
                  CONTENTS, ALLOC, LOAD, DATA
  8 .text.init    00018718  c02cc000  c02cc000  001cc000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  9 .data.init    0001ed18  c02e4720  c02e4720  001e4720  2**5
                  CONTENTS, ALLOC, LOAD, DATA
 10 .setup.init   00000170  c0303440  c0303440  00203440  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 11 .initcall.init 000000bc  c03035b0  c03035b0  002035b0  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 12 .data.page_aligned 00000800  c0304000  c0304000  00204000  2**5
                  CONTENTS, ALLOC, LOAD, DATA
 13 .data.cacheline_aligned 00004520  c0304800  c0304800  00204800  2**5
                  CONTENTS, ALLOC, LOAD, DATA
 14 .bss          00041f54  c0308d20  c0308d20  00208d20  2**5
                  ALLOC
 15 .stab         00615708  00000000  00000000  00208d20  2**2
                  CONTENTS, READONLY, DEBUGGING
 16 .stabstr      001b4ec1  00000000  00000000  0081e428  2**0
                  CONTENTS, READONLY, DEBUGGING
 17 .comment      00005bfa  00000000  00000000  009d32e9  2**0
                  CONTENTS, READONLY
 18 .note         00001e28  c034ac74  c034ac74  009d8ee3  2**0
                  CONTENTS, READONLY


如以上输出所见,代码段.text  ,开始于 地址 0xc0100000。


『  装载模块 』
当模块装载进内核,其首先被重定位。模块的重定位意思是将所有相对地址转化为绝对地址。
模块重定位后,insmod 命令打印模块map文件,如果命令行需要的话。
模块map文件包含 模块中的段和所有符号的地址。
模块trfs的部分模块map文件如下所示:

$ head -n 20 /tmp/trfs.map
Sections:       Size      Address   Align
.this           00000060  c1808000  2**2
.text           0000162c  c1808060  2**4
.text.lock      0000010a  c180968c  2**0
.rodata         000002a4  c18097a0  2**5
__ksymtab       00000048  c1809a44  2**2
.kstrtab        00000109  c1809aa0  2**5
.data           00000178  c1809bc0  2**5
.bss            00000010  c1809d38  2**2
__archdata      00000000  c1809d50  2**4


Symbols:
00000000 a translators.c
00000000 a linkinfo.c
00000000 a view.c
00000000 a super.c
00000000 a dirinfo.c
00000000 a link.c
00000000 a dir.c
c1808000 d __this_module

代码段.text在地址0xc1808060处装入。

『 gdb脚本的产生 』
loadmodule.sh产生一个gdb脚本,用于装载目标文件到gdb中。
脚本告诉gdb装载模块目标文件,给出不同段装载之处的地址。
以上模块map的gdb脚本如下:

$ cat /mnt/work/gdbscripts/loadtrfs
add-symbol-file /mnt/work/build/old-pc/trfs/modules/trfs/trfs 0xc1808060 -s .text.lock 0xc180968c -s .rodata 0xc18097a0 -s __ksymtab

0xc1809a44 -s .data 0xc1809bc0

loadmodule.sh 从模块map文件中获得段的地址。

--将目标文件载入gdb --
含有地址的模块目标文件载入后,gdb可以计算一个符号的地址,通过提供相对地址给包含此符号的段的绝对地址来实现。
例如 trfs模块中有一个函数 tr_initviewtree 。 包含他以及函数相对地址的段,可以通过 objdump 来找到。

$ objdump -t trfs | grep tr_initviewtree
000014f0 g     F .text  00000016 tr_initviewtree

.text 是包含此函数的段,字符 F 表示其是一个函数,0x14f0 是此函数在.text段中的相对地址。0x16是此函数的代码长度。
此函数载入的地址是0xc1808060 + 0x14f0 = 0xc1809550。
此地址在模块目标文件中也给出了。

$ grep tr_initviewtree /tmp/trfs.map
c1809550 T tr_initviewtree


$ gdbmod
GNU gdb 20000204
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu".
(gdb) source loadtrfs
add symbol table from file "/mnt/work/build/old-pc/trfs/modules/trfs/trfs" at
        .text_addr = 0xc1808060
        .text.lock_addr = 0xc180968c
        .rodata_addr = 0xc18097a0
        __ksymtab_addr = 0xc1809a44
        .data_addr = 0xc1809bc0
(gdb) p tr_initviewtree
$1 = {void ()} 0xc1809550


『 init_module()之调试 』

从一个模块中调试init_module()函数需要特殊的步骤。
当gdb被模块通报( 针对kgdb 1.9之后的 ),或者当loadmodule.sh结束 (针对kgdb 1.8之前的),模块调试信息才是可用的。
init_module()函数那时已经被执行过,因此init_module()不能通过原来的方式来调试。

方法是:在调用init_module()处之前的位置 设置断点于内核中。

对于kgdb 1.9/之后的版本:
modprobe 或者 insmod 载入模块,等到以上断点的产生。这时你可以在模块中任何地方设置断点了。

针对kgdb 1.8/之前的版本:
一旦内核侵入调试器,等到loadmodule.sh退出。 此时 init_module()未被调用,所有调试信息是可用的。现在载入模块目标文件。一旦载入,断点可设置于模

块中任何地方,如同init_module()的一条语句一般。

余下的显示实例参见 http://kgdb.linsyssoft.com/initmodule.htm

************************************************************************************************************************************************

【 体系依赖 】

『 x86_64 』

Kgdb patch已经在双opteron CPU上测试过。包括线程支持、控制台信息的所有功能测试可用。

x86_64 gdb对运行kgdb的CPU上d的o_IRQ函数不能正确显示堆栈跟踪。为了得到这个堆栈跟踪,一个隐蔽线程被执行。

Press Ctrl+C in gdb
Program received signal SIGTRAP, Trace/breakpoint trap.
breakpoint () at kernel/kgdbstub.c:1056
1056                    atomic_set(&kgdb_setting_breakpoint, 0);
(gdb) bt
#0  breakpoint () at kernel/kgdbstub.c:1056
#1  0xffffffff801e3f17 in kgdb8250_interrupt (irq=3, dev_id=0x0, regs=0x1)
    at drivers/serial/kgdb_8250.c:143
#2  0xffffffff80113341 in handle_IRQ_event (irq=3, regs=0x10001a1dc48,
    action=0x1001ff29840) at arch/x86_64/kernel/irq.c:219
#3  0xffffffff801134e1 in do_IRQ (regs=0x10001a1dc48)
    at arch/x86_64/kernel/irq.c:387
#4  0xffffffff80110eab in common_interrupt () at elfcore.h:92
Previous frame inner to this frame (corrupt stack?)

GDB不能正确跟踪这一点,检查一下线程列表中是否包含一个隐蔽线程。其可以通过在中断进入点处的tag stack标识。

(gdb) info thr
  10 Thread 32769 (Stack at interrupt entrypoint)  __delay (loops=1384000)
    at arch/x86_64/lib/delay.c:30
  9 Thread 32768 (Shadow task 0 for pid 0)  0xffffffff8010eb3e in cpu_idle ()
    at sched.h:914
  8 Thread 8 (aio/0)  0xffffffff8013f41c in worker_thread (
    __startup=0x1001ff28d60) at sched.h:914
  7 Thread 7 (kswapd0)  kswapd (p=0xffffffff803170e8) at mm/vmscan.c:1046
  6 Thread 6 (pdflush)  __pdflush (my_work=0x1001fd71f18) at current.h:11
  5 Thread 5 (pdflush)  __pdflush (my_work=0x1001fd73f18) at current.h:11
  4 Thread 4 (kblockd/0)  0xffffffff8013f41c in worker_thread (
    __startup=0x1001ff28ae0) at sched.h:914
  3 Thread 3 (events/0)  0xffffffff8013f41c in worker_thread (
    __startup=0x1001ff3cd60) at sched.h:914
  2 Thread 2 (ksoftirqd/0)  ksoftirqd (__bind_cpu=0xffffffff8030be20)
    at current.h:11
* 1 Thread 1 (swapper)  breakpoint () at kernel/kgdbstub.c:1056

如上面的列表,这个隐蔽线程是10,我们可以从线程10中得到丢失的回溯跟踪。

(gdb) bt
#0  __delay (loops=1384000) at arch/x86_64/lib/delay.c:30
#1  0xffffffff80212bfd in ide_delay_50ms () at drivers/ide/ide.c:1451
#2  0xffffffff8020b252 in actual_try_to_identify (drive=0xffffffff803c05e8,
    cmd=236 '' '') at drivers/ide/ide-probe.c:351
#3  0xffffffff8020b67a in try_to_identify (drive=0xffffffff803c05e8,
    cmd=236 '' '') at drivers/ide/ide-probe.c:405
#4  0xffffffff8020b7ef in do_probe (drive=0xffffffff803c05e8, cmd=236 ''?)
    at drivers/ide/ide-probe.c:497
#5  0xffffffff8020bcaa in probe_hwif (hwif=0xffffffff803c04a0)
    at drivers/ide/ide-probe.c:613
#6  0xffffffff8020bf46 in probe_hwif_init (hwif=0xffffffff803c04a0)
    at drivers/ide/ide-probe.c:868
#7  0xffffffff8021a10d in ide_setup_pci_device (dev=0x1f9e8, d=0x1f7)
    at drivers/ide/setup-pci.c:740
....


『 PowerPC 』
这个支持的提供还只是基于试验基础。仍然为进行测试,所以要小心使用。欢迎提交相关问题报告和bug修复。

---编译一个包括kgdb的内核---
启用 [ Standard / Generic serial ] 支持。如果kgdb选项中 通过gdb显示控制台信息的选项被选中,启用 串口控制台支持 。


『 Linux / s390 』

---运行于 VM 下的 Linux/s390 的 kgdb stub (ver 0.2.0 )---

这里试图提供有关 VM下,运行在s390平台上的Linux的内核源码级调试工具。其提供的功能组和x86 kgdb很相似。

如图:


x3270连接 s390 VM ,提供一个控制台接口给Linux客户机。 gdbstub.pl 通过x3270 告知VM , 并使用 VM的 调试命令 (如 cp trace 、cp dispay ......)

来实现gdb远程协议。
VM调试命令可用于 提取和修改 运行没有发生变化的内核的Linux客户机。

图中的 B和C通常是相同机器。


注意:其只能工作于32位的s390平台。64位的s390平台还不支持,这需要全部重写代码。

---必要条件---
目标机:   
运行在VM下的Linux/s390

主机   :   
* 运行Linux的x86或s390
* 打有下面附加补丁的gdb5.2 (x86上本地的 或 交叉平台的)。在下载页有一个预编译版本(x86 binary)。
* x3270。 使用基于文本的3270客户端-c3270来取代x3270是可能的。使用只基于脚本的客户机是不怎么可取的,因为有时需要手工干预。
* stub ---- 由三个perl文件组成,gdbstub.pl 、cpinter.pl 、 cpstrings.pl

最新的发布在这里 http://sourceforge.net/projects/kgdb


---基本使用---

(交叉)编译内核 时加上 -g -O2 。 拷贝到你的目标机并引导之。 主机则需要一份包含完整调试信息的vmlinux拷贝。

在目标机端,你不能从标准的kernel rpm中简单地使用 一个plain(平坦)的 -O2 内核,不能在主机端使用-g -O2的内核。当使用-g 选项时,地址将有轻微的不同。
一个遗憾,因为这对于调试 运行着标准发布内核的产品服务器而言 是非常有用的。

编辑 cpstrings.pl 文件,以使输出与你的VM配置相匹配。

在你解开stub的目录下,创建两个fifo: mkfifo  ip  op

运行命令:
$ sleep  1000000 > ip  < op &
这个可以让让x3270保持“陶”醉状态。

按照下面来启动x3270:

x3270  -script  -port  blah  hostname  op


注意控制台大小至少需要80x25 。 现在手动登录到你的虚拟机,启动编译时带有-g选项的内核。

按照下面来运行 stub :
perl  -w  ./gdbstub.pl  >ip <OP

如果所有一切进行的顺利,其将迫使目标机进入 CP ,并释放命令组。

在控制台你可以进行观察。一旦上面结束,启动gdb。

s390-ibm-linux-gdb  /path/to/vmlinux

set  remotetimeout 20   /* 如果通过网络来调试目标机,需要运行这条命令。你可以将此  加入到 .gdbinit 中。

set  trust-readonly-sections  1   /*这个可以避免一些不必要的麻烦。gdb will memory. target remote stubhost:5513


stubhost之处即是你运行gdbstub.pl之处(通常在本地主机)

你将得到下面信息:

$ s390-ibm-linux-gdb vmlinux
GNU gdb 5.2
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "--host=i386-pc-linux-gnu --target=s390-ibm-linux"...
(gdb) set remotetimeout 20
(gdb) ta re linux-3:5513
Remote debugging using linux-3:5513
cpu_idle (unused=0x0) at process.c:76
76      }
warning: shared library handler failed to enable breakpoint
(gdb)


这时你可以设置断点,检查内存、寄存器、查看回溯跟踪……


---线程调试---
你现在可以观察所有线程任务。可以切换到特殊线程做回溯跟踪。这对于调试死锁等状况是有用的。
这里有两种方法来做。
你可以根据自己的特殊环境,选择其中一个较简单的。

--方法1--

Helper  Module :
第一步需要编译一个调用gdbmod的helper module,然后在目标机上载入。
你可以在任何时间来做,甚至是stub 和 gdb启动之后。但是,这一步需要在运行第一个"info threads"命令之前来完成。

编辑Makefile样品,改变诸如内核源码路径、交叉编译等等之后,gdbmod.c 文件才可以被编译。

$ make
s390-ibm-linux-gcc -D__KERNEL__ -I/home/ganesh/work/usr/src/linux-2.4.9-37/include -Wall -Wstrict-prototypes -Wno-trigraphs -O2

-fno-omit-frame-pointer -fno-strict-aliasing -fno-common -Wno-unused -pipe -fno-strength-reduce -DMODULE -DEXPORT_SYMTAB -c

gdbmod.c
$

现在拷贝它至目标机:
$ scp -C gdbmod.o root@target:
gdbmod.o             100% |***************************************************|   106 KB    00:02

载入模块:
$ ssh root@target "/sbin/insmod /root/gdbmod.o;/sbin/lsmod"
Module                  Size  Used by
gdbmod                107616   0  (unused)
netiucv                18096   1  (autoclean)
af_packet              16560   0  (autoclean)
$

获得目标机的/proc/ksyms,在你的perl stub目录下dump一下ksyms:

[......gdbstub]$ ssh root@target cat /proc/ksyms >ksyms
[......gdbstub]$


现在你可以运行 info threads ,大约半分钟之后如果目标机连通网络,你应该获得一个运行在目标机上的线程列表。
使用 thread 和 bt  命令来切换 线程和回溯跟踪。

但是,无法设置线程上下文中的变量、寄存器。 只可观,不可触焉。

[............gdb]$ ~/work/gdb-build/gdb/gdb
GNU gdb 5.2
[.....]
(gdb) ta re localhost:5513
cpu_idle (unused=0x0) at process.c:76
76      }

warning: shared library handler failed to enable breakpoint
(gdb) info threads
  22 Thread 575 (mingetty)  schedule_timeout (timeout=2147483647) at sched.c:425
  21 Thread 568 (xfs)  schedule_timeout (timeout=282645) at sched.c:453
  20 Thread 516 (crond)  schedule_timeout (timeout=231187) at sched.c:453
  19 Thread 497 (xinetd)  schedule_timeout (timeout=2147483647) at sched.c:425
  18 Thread 464 (sshd)  schedule_timeout (timeout=2147483647) at sched.c:425
  17 Thread 427 (klogd)  0x0001f8d4 in do_syslog (type=0, buf=0x406b38 "", len=4095) at printk.c:178
  16 Thread 422 (syslogd)  schedule_timeout (timeout=2147483647) at sched.c:425
  15 Thread 110 (kjournald)  interruptible_sleep_on (q=0xc6d468) at sched.c:838
  14 Thread 109 (kjournald)  interruptible_sleep_on (q=0xc6d668) at sched.c:838
  13 Thread 108 (kjournald)  interruptible_sleep_on (q=0xc6d268) at sched.c:838
  12 Thread 107 (kjournald)  interruptible_sleep_on (q=0xc6d068) at sched.c:838
  11 Thread 106 (kjournald)  interruptible_sleep_on (q=0xf6a868) at sched.c:838
  10 Thread 10 (mdrecoveryd)  md_thread (arg=0x0) at md.c:3010
  9 Thread 9 (kupdated)  schedule_timeout (timeout=228645) at sched.c:453
  8 Thread 8 (bdflush)  interruptible_sleep_on (q=0x200c30) at sched.c:838
  7 Thread 7 (kreclaimd)  interruptible_sleep_on (q=0x1f9a0c) at sched.c:838
  6 Thread 6 (kswapd)  schedule_timeout (timeout=228682) at sched.c:453
  5 Thread 5 (ksoftirqd_CPU1)  ksoftirqd (__bind_cpu=0x0) at softirq.c:387
  4 Thread 4 (ksoftirqd_CPU0)  ksoftirqd (__bind_cpu=0x0) at softirq.c:387
  3 Thread 3 (keventd)  context_thread (dummy=0x0) at context.c:99
  2 Thread 2 (kmcheck)  __down_interruptible (sem=0x321020) at semaphore.c:128
  1 Thread 1 (init)  schedule_timeout (timeout=228644) at sched.c:453
(gdb) thread 17
[Switching to thread 17 (Thread 427)]#0  0x0001f8d4 in do_syslog (type=0, buf=0x406b38 "", len=4095)
    at printk.c:178
178                     error = wait_event_interruptible(log_wait, (log_start - log_end));
(gdb) bt 3
#0  0x0001f8d4 in do_syslog (type=0, buf=0x406b38 "", len=4095) at printk.c:178
#1  0x0007a6aa in kmsg_read (file=0x0, buf=0x0, count=0, ppos=0x0) at kmsg.c:35
#2  0x0004d5c8 in sys_read (fd=0, buf=0x406b38 "", count=4095) at read_write.c:162
(More stack frames follow...)
(gdb)


--方法2--

另一个办法耗费更长的时间,比需要做的更加痛苦, 但是,有一个优点: 不需要 helper  module 。
你需要在 .gdbinit 中加入用户定义的命令两条:

【code】
define addcontext
        maintenance packet Qa,$arg0,$arg1,,
end
define findthreads
        set $init_thread = init_tasks[0]
        set $athread = $init_thread->next_task
        while $athread != $init_thread
                set $frameptr = (unsigned long *)(((unsigned long *)$athread->thread.ksp)[0])
                printf "%s %x ", (char *)$athread->comm, $frameptr
                set $athread = $athread->next_task
        end
end
【/code】

(gdb) findthreads
init 7f5d80
kmcheck 7f1eb8
keventd df7f08
ksoftirqd_CPU0 df5f38
ksoftirqd_CPU1 df3f38
kswapd de5e48
kreclaimd de3ec0
bdflush de1eb8
kupdated ddfeb8
mdrecoveryd ddbf18
kjournald f00bea0
kjournald f003ea0
kjournald efffea0
kjournald eff9ea0
kjournald eff5ea0
syslogd e975d80
klogd eb11d80
sshd e7ffd80
xinetd e733d80
crond 1003e28


xfs e567d80
mingetty e4dfd08
(gdb) addcontext syslogd e975d80
sending: "Qa,syslogd,e975d80,,"
received: "OK"
(gdb) info threads
  1 Thread 65536 (syslogd)  schedule_timeout (timeout=2147483647) at sched.c:425
(gdb) thread 1
[Switching to thread 1 (Thread 65536)]#0  schedule_timeout (timeout=2147483647) at sched.c:425
425                     goto out;
(gdb) bt 3
#0  schedule_timeout (timeout=2147483647) at sched.c:425
#1  0x00063178 in do_select (n=1, fds=0xe975ed8, timeout=0xe975ef0) at select.c:223
#2  0x00063548 in sys_select (n=1, inp=0x7ffff800, outp=0x0, exp=0x0, tvp=0x0) at select.c:318
(More stack frames follow...)
(gdb) addcontext klogd eb11d80
sending: "Qa,klogd,eb11d80,,"
received: "OK"
(gdb) info threads
  2 Thread 65537 (klogd)  0x0001f8d4 in do_syslog (type=129048040, buf=0x406b38 "", len=4095)
    at printk.c:178
* 1 Thread 65536 (syslogd)  schedule_timeout (timeout=2147483647) at sched.c:425
(gdb) thread 2
[Switching to thread 2 (Thread 65537)]#0  0x0001f8d4 in do_syslog (type=129048040, buf=0x406b38 "",
    len=4095) at printk.c:178
178                     error = wait_event_interruptible(log_wait, (log_start - log_end));
(gdb) bt 3
#0  0x0001f8d4 in do_syslog (type=129048040, buf=0x406b38 "", len=4095) at printk.c:178
#1  0x0007a6aa in kmsg_read (file=0x7b11de8, buf=0x7b11de8 "", count=0, ppos=0x0) at kmsg.c:35
#2  0x0004d5c8 in sys_read (fd=129048040, buf=0x406b38 "", count=4095) at read_write.c:162
(More stack frames follow...)
(gdb) The program is running.  Exit anyway? (y or n) y
 

如果gdb的伪语言(pseudo-language)在传递参数之前可以实际求出它们,这个方法就更容易一些。
然后我们可以简单地从 findthreads loop 中运行 addcontext ,而不是手动做这一切。
addcontext 命令也可北用于 backtrack任意帧指针,比如 一个 panic 之后在控制台上打印出的。


『 提示 』

*  不要做不受限制的backtrace ,esp 。 如果你调试的是一个非常远的系统,Do a bt 5 or something 。
*  避免使用 n 命令 和 单步进single stepping 。(这也许在将来会得到修复)。
    在必要的地方设置断点。
*  在gdb上击打 ^C 来强迫机器进入调试器。作为选择, 在控制台键入 PA1  或者  #cp 将起到同样的效果。
*  有时会发生这种情况: 机器已进入CP ,但是 在控制台上没有讯息--VM Read/Running 的状态遗留着,没有断点地址。
    或者CP讯息出现在屏幕上。如果你怀疑机器在CP中,击打 Enter 。This is usually sufficient to get the ball rolling.
*  当机器进入CP之中,你可以在控制台运行任何命令 而不影响调试器。 只是不要改变状态 (如 寄存器、内存)。
*  不要在stub运行时从控制台手动恢复VM。
*  你可以在任何时候杀死stub 和 gdb , do a #cpu  all  cp   tr  ,移除断点,重启stub 和 gdb 。
*  你可以调试模块,但是复杂的。我不能在这里解释的更多。在 kgdb.sourceforge.net 上查看调试模块说明。


---gdb patch---

stub使用 硬件断点 , 所以不必要去消耗PC资源。我确信这样做更好一些。

【patch code】
--- ./gdb/s390-tdep.c.ORG Wed Jun  5 01:59:18 2002
+++ ./gdb/s390-tdep.c Wed Jun  5 01:59:39 2002
@@ -1787,7 +1787,7 @@
   /* Amount PC must be decremented by after a breakpoint.
      This is often the number of bytes in BREAKPOINT
      but not always.  */
-  set_gdbarch_decr_pc_after_break (gdbarch, 2);
+  set_gdbarch_decr_pc_after_break (gdbarch, 0);
   set_gdbarch_pop_frame (gdbarch, s390_pop_frame);
   /* Stack grows downward.  */
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP