kgdb抓虫日记 – gdb 7.1 不能正常退出KGDB

/ 1评 / 0

A: BUG重现步骤

1: 使用gdb7.1版本连接kgdb,
2: 在连接成功后,敲入detach与kgdb断开连接。

gdb不能成功退出并提示 "Bogus trace status reply from target: E22"信息。

1
2
3
(gdb) detach 
Bogus trace status reply from target: E22
(gdb)

B: BUG现场分析

要搞清楚为什么不能退出,我们得先看看detach究竟是干了些什么.

先设置下远程调试模式,看看它给kgdb发送了什么命令.

1
2
3
4
5
6
7
(gdb)set debug remote 1 (设置gdb远程调试模式查看与kgdb之间的通信内容)
 
(gdb) detach 
Sending packet: $qTStatus#49...Ack
Packet received: E22
Bogus trace status reply from target: E22
(gdb)

第一眼望去,很明显发现一个不同。
以前老版本的gdb的detach是直接发送“D" 命令给kgdb的,而现在确是先发送一个“qTStatus”.
然后kgdb由于不支持“qTStatus”命令而返回一个“E22”的错误信息。
但是gdb那边确不认这个错误信息. 于是问题就出现了...

C: BUG触发原因

1: 为什么发有“qTStatus”这个查询.
这个是gdb 7.1新增加的Tracepoints(追踪点)特性,有关Tracepoints特性可以点击这里:
在gdb退出的时候,它会去查询下是否有Tracepoints,如果有,则把Tracepoint积累的数据给下载回来,没有就算了. :-)

2: 远程串行协议规范
目前关于gdb远程串行协议文档,主要有两个记录的地方,一个是gdb的官方站点,一个是redhat的站点.

那两个协议内容基本是一致的,只有一些细微的差别。
在redhat上远程串行协议文档的有关协议包package简介上,明显的定义对于不支持的general query应该返回ENN格式的错误值

1
2
3
4
5
6
7
8
9
10
11
12
13
qquery -- general query
    Request info about query. In general gdb queries have a leading upper
case letter. Custom vendor queries should use a company prefix
 (in lower case) ex: qfsf.var. query may optionally be followed by
 a , or ; separated list. Stubs must ensure that they match the full
query name.
 
Reply:
    XX…
        Hex encoded data from query. The reply can not be empty. 
ENN
        error reply 
        Indicating an unrecognized query.

但在gdb的官方站点的协议文档里并没有general query必须返回错误值这样定义。

很显然现在是因为kgdb由于不支持“qTStatus”命令而返回一个“E22”的错误信息,但gdb 7.1并不认帐..

翻看了下gdb对包的处理,对于大部分包来说,返回“E22”的错误信息是可以被接受的.
但是“qTStatus”由于其特殊性,它接受的是EENN的错误格式..

kgdb如果不返回E22的错误值,那应该返回什么呢?
由于kgdb和gdbserver的性质一样,所以我就去看gdbserver的代码实现了,

process_serial_event() gdb-7.1/gdb/gdbserver/server.c : 2585
handle_query() gdb-7.1/gdb/gdbserver/server.c : 884

阅读上面两个函数后,发现gdbserver对于不识别或者不支持的命令,都是返回""空包给gdb的,
所以kgdb也应当返回""空包给gdb,这样问题就解决了.

D: BUG解决方法

采用与gdbserver的处理方法,对于不支持的命令,返回一个空包""。

1: linux-2.6.35以后版本的patch: (已集成进内核代码)
2: linux-2.6.35之前版本patch:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
From a7702831d879dfd1bdbe3a994d8787a28cd50e4b Mon Sep 17 00:00:00 2001
From: Dongdong Deng <dongdong.deng@windriver.com>
Date: Fri, 9 Jul 2010 15:48:36 +0800
Subject: [PATCH] kgdb: return empty packet for unsupported query command
 
Respond with an empty packet so that gdb knows that we don't
support that command.
 
Signed-off-by: Jason Wessel <[email protected]>
Signed-off-by: Dongdong Deng <[email protected]>
---
 kernel/kgdb.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)
 
diff --git a/kernel/kgdb.c b/kernel/kgdb.c
index 1cbfa7b..a97fae1 100644
--- a/kernel/kgdb.c
+++ b/kernel/kgdb.c
@@ -1009,10 +1009,8 @@ static void gdb_cmd_query(struct kgdb_state *ks)
 	switch (remcom_in_buffer[1]) {
 	case 's':
 	case 'f':
-		if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10)) {
-			error_packet(remcom_out_buffer, -EINVAL);
+		if (memcmp(remcom_in_buffer + 2, "ThreadInfo", 10))
 			break;
-		}
 
 		i = 0;
 		remcom_out_buffer[0] = 'm';
@@ -1053,10 +1051,9 @@ static void gdb_cmd_query(struct kgdb_state *ks)
 		pack_threadid(remcom_out_buffer + 2, thref);
 		break;
 	case 'T':
-		if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16)) {
-			error_packet(remcom_out_buffer, -EINVAL);
+		if (memcmp(remcom_in_buffer + 1, "ThreadExtraInfo,", 16))
 			break;
-		}
+
 		ks->threadid = 0;
 		ptr = remcom_in_buffer + 17;
 		kgdb_hex2long(&ptr, &ks->threadid);
-- 
1.6.0.4

一条回应:“kgdb抓虫日记 – gdb 7.1 不能正常退出KGDB”

  1. Kgdb说道:

    Kgdb…

    […] something about kgdb[…]…

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据