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…
[…] something about kgdb[…]…