Skip to content
lainme edited this page May 14, 2014 · 24 revisions

调试主要需要的数据分为2类情况,1种是verbose,也就是通常的日志信息。这个无需重新编译,设置简单,可以查看很多http通信的细节。 另外一种是backtrack,这个只是用来当程序崩溃时使用的手段

提交verbose信息

(在0.1版本以后)需要在pidgin的帐号面板的高级中设置Verbose或者输出等级

(在0.1版本之前)需要编译时指定参数cmake .. -DVERBOSE=3

VERBOSE的输出等级分为下面5类:

0---无输出
1---常规信息输出(一些错误提示)
2---poll信息输出
3---所有的请求输出(url,post,response)
4---图片上传下载和离线文件上传的详细HTTP信息.
5---extra输出(输出当前活跃的url),timeout输出(不是超时,可以认为是curl的时间片)

一般是选择3,在调试图片和离线文件传输问题的时候需要打开到4.

之后重启pidgin,在终端下直接输入pidgin运行,可以在控制台中看到verbose信息,如下所示,是登录的时候的输出

xiehuc:~$ pidgin -f
[login stage 1:get webqq version]

https://ssl.ptlogin2.qq.com/check?uin=××××××××&appid=1003903
[Jul 12 07:44:36] ERROR[8245]: type.c:507 lwqq_set_cookie: 
	No this cookie:confirmuin
Get response verify code: ptui_checkVC('0','!YLU','\x00\x00\x00\x00\x14\xe4\x63\x95');
Verify code: !YLU
Get verify code OK
https://ssl.ptlogin2.qq.com/login?u=×××××××××&p=1592182301FA3BE2FA18012E8A9625FF&verifycode=!YLU&webqq_type=10&remember_uin=1&aid=1003903&login2qq=1&u1=http%3A%2F%2Fweb.qq.com%2Floginproxy.html%3Flogin2qq%3D1%26webqq_type%3D10&h=1&ptredirect=0&ptlang=2052&from_ui=1&pttype=1&dumy=&fp=loginerroralert&action=2-11-7438&mibao_css=m_webqq&t=1&g=1
[Jul 12 07:44:36] ERROR[8245]: type.c:507 lwqq_set_cookie: 
	No this cookie:superuin
[Jul 12 07:44:36] ERROR[8245]: type.c:507 lwqq_set_cookie: 
	No this cookie:superkey
[Jul 12 07:44:36] ERROR[8245]: type.c:507 lwqq_set_cookie: 
	No this cookie:ETK
[Jul 12 07:44:36] ERROR[8245]: type.c:507 lwqq_set_cookie: 
	No this cookie:airkey
ptuiCB('0','0','http:https://web.qq.com/loginproxy.html?login2qq=1&webqq_type=10','0','登录成功!', '××××××××');

r=%7B%22status%22%3A%22online%22%2C%22ptwebqq%22%3A%2273bf869ffeb6e7d74b21c496fa8028ba1548cca541d44d514c6b263c6dcb872e%22%2C%22passwd_sig%22%3A%22%22%2C%22clientid%22%3A%2230422779%22%2C%20%22psessionid%22%3Anull%7D
{"retcode":0,"result":{"uin":××××××××,"cip":1858037536,"index":1075,"port":47943,"status":"online","vfwebqq":"4be2a95c0b69dd8a41abc296a324ec6ac0361a28badf825f02e02229aaff895c9f781c079845f81f","psessionid":"8368046764001d636f6e6e7365727665725f77656271714031302e3133392e372e3136300000482600001f7e026e04009563e4146d0000000a407279477673573143326d000000284be2a95c0b69dd8a41abc296a324ec6ac0361a28badf825f02e02229aaff895c9f781c079845f81f","user_state":0,"f":0}}

r={"h":"hello","hash":"0406525309040954575657065006560706530104530108045653090307085750030506095056510005035406055700010152045200070056065152500805035645514642455F4055135042475E40","vfwebqq":"4be2a95c0b69dd8a41abc296a324ec6ac0361a28badf825f02e02229aaff895c9f781c079845f81f"}
http:https://s.web2.qq.com/api/get_user_friends2
https://d.web2.qq.com/channel/get_online_buddies2?clientid=30422779&psessionid=8368046764001d636f6e6e7365727665725f77656271714031302e3133392e372e3136300000482600001f7e026e04009563e4146d0000000a407279477673573143326d000000284be2a95c0b69dd8a41abc296a324ec6ac0361a28badf825f02e02229aaff895c9f781c079845f81f

事实上,也完全可以通过把日志写入文件,然后让在贴issue的时候附带文件,但是这样是以增加程序的额外开销为代价的,并且,自己手工复制的时候,可以隐去一些隐私信息。所以最后还是决定不通过这种方式。

提交backtrace

###1. 开启编译参数###

backtrace信息必须要求使用编译时带-g参数编译的,所以有两种方式:

  1. 使用Ubuntu的PPA的

pidgin-lwqq 和 lwqq 的调试信息分别在 pidgin-lwqq-dbg 和 liblwqq-dbg 两个包中,可以一起安装方便调试。

sudo apt-get install pidgin-lwqq-dbg liblwqq-dbg 
  1. 手工编译方式 因为一般从源中安装的版本都不含有调试信息.所以首先我们需要下载源代码编译.

    git clone git:https://github.com/xiehuc/pidgin-lwqq.git

然后需要满足编译的时候带有-g标识.VERBOSE可以打开大部分控制台输出

mkdir build;cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug
make
sudo make install

安装debug版本。

2.带gdb运行

主要是为了获取backtrace,事实上,可以通过生成core dump,并且直接发给我文件来完成。但是coredump有些很大,200MB左右,并不适合网络传输.所以最后还是直接贴出来的方式比较好.

backtrace和具体的程序的版本相关,需要提交时附带git的commit号 (通过PPA安装的,包版本中gitxxx.yyy中yyy部分即是commit号)

然后请运行源代码包里面的debug.sh,它设定了一些gdb的flags. 主要是不要拦截开启了SSL之后的SIGPIPE信号.

会有如图的消息:

GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http:https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.<br>
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"<br>
and "show warranty" for details.<br>
This GDB was configured as "x86_64-linux-gnu".<br>
For bug reporting instructions, please see:<br>
<http:https://bugs.launchpad.net/gdb-linaro/>...<br>
Reading symbols from /usr/bin/pidgin...Reading symbols from /usr/lib/debug/usr/bin/pidgin...done.<br>
done.<br>
(gdb)

此时输入run (r)回车

(gdb) r

就会开始运行pidgin了.

其中控制台会出现许多信息.不用管它.

[Sep  9 09:18:48] DEBUG[18627]: /home/xiehuc/PROJECT/pidgin-lwqq/src/liblwqq/info.c:1210     lwqq_info_get_friend_detail_info: in function.hi
r={"to":2505299203,"face":0,"content":"[\"hi\",[\"font\",{\"name\":\"宋体\",\"size\":\"13\",\"style\": [0,0,0],\"color\":\"000000\"}]]","msg_id":3310000,"clientid":"84684545","psessionid":"8368046764001f636f6e6e7365727665725f7765627171403137322e32332e3133342e323136000055cb00000ce1016e04009563e4146d0000000a40744f4462614167355a6d00000028f74c3012cadb51c60b55ab412e8d1dd7070b0ce4bb78d5f2acf877a6afa94b3ee508bc7e56de8383"}&clientid=84684545&psessionid=8368046764001f636f6e6e7365727665725f7765627171403137322e32332e3133342e323136000055cb00000ce1016e04009563e4146d0000000a40744f4462614167355a6d00000028f74c3012cadb51c60b55ab412e8d1dd7070b0ce4bb78d5f2acf877a6afa94b3ee508bc7e56de8383
{"retcode":0,"result":"ok"}

你有兴趣的话可以看一下.大部分是POST消息.

3.理解gdb的工作原理

gdb运行会在后台运行调试程序。我们暂且称被调试程序运行时为工作模式,使用gdb输入控制指令的时候为控制模式。这两种模式不能同时存在,也就是说被调试的程序运行时是无法输入gdb的命令的。要输入gdb的命令时需要先暂停被调试程序。从工作模式切换到控制模式有集中途径。 1 在gdb所在的终端按 ctrl+c 。(需要gdb的m控制台处于聚焦(focus),例如被调试程序是pidgin时,直接按ctrl+c是向pidgin发送而不是gdb,所以需要先点击一下gdb的控制台,再按ctrl+c。 2 程序崩溃时,会自动切换到控制模式,方便了解程序退出的前一刻的状态。 3 触发堵啊断点时。 从控制模式切换到工作模式,只需要输入c回车即可。(continue)

4.gdb的命令

  • i 可以查看一些信息(info) 例如经常用i threads 来查看所有的线程。
  • t 可以切换线程(thread)
  • bt 查看调用栈(backtrace)。就是查看哪些函数调用了哪些函数,非常的有用。可以通过它确定是哪里出现的问题。

5.一个崩溃的示例

然后运行操作让它崩溃.

Program received signal SIGINT, Interrupt.
0x00007ffff46afb03 in __GI___poll (fds=<optimized out>, nfds=<optimized out>, 
    timeout=<optimized out>) at ../sysdeps/unix/sysv/linux/poll.c:87
87	../sysdeps/unix/sysv/linux/poll.c: 没有那个文件或目录.
(gdb) 

现在已经在gdb里面了.当然这些信息还根本没有什么作用.
运行(gdb) bt可以查看系统调用栈,如下:

(gdb) bt
#0  qq_send_im (gc=0x5555565f20c0, who=0x555555e15e00 "2505299203", 
    what=0x555555dcff60 "hi", UNUSED_flags=PURPLE_MESSAGE_SEND)
    at /home/xiehuc/PROJECT/pidgin-lwqq/src/webqq.c:771
#1  0x00007ffff4d0fb94 in serv_send_im (gc=0x5555565f20c0, 
    name=0x555555e15e00 "2505299203", message=0x555555dcff60 "hi", 
    flags=PURPLE_MESSAGE_SEND)
    at /build/buildd/pidgin-2.10.3/./libpurple/server.c:145
#2  0x00007ffff4cdeb9f in common_send (conv=0x555556655440, 
    message=<optimized out>, msgflags=PURPLE_MESSAGE_SEND)
    at /build/buildd/pidgin-2.10.3/./libpurple/conversation.c:182
#3  0x00005555555b5065 in send_cb (widget=<optimized out>, 
    gtkconv=0x5555566efe00)
    at /build/buildd/pidgin-2.10.3/./pidgin/gtkconv.c:612
#4  0x00007ffff52b6ca2 in g_closure_invoke ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#5  0x00007ffff52c7fdd in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#6  0x00007ffff52cf289 in g_signal_emitv ()
   from /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#7  0x00007ffff617380a in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#8  0x00007ffff6173d68 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0

可以看到第#0号就是pidgin-lwqq的代码了.有另外一些情况是在#i,i>0是pidgin-lwqq的代码,而#0是其他地方的比如libc.so的.
这里我们能改的只能是pidgin-lwqq的代码.所以需要用(gdb)f i来跳到第几层,f是frame的意思.
其中可以看到是在qq_send_im这个函数挂调的(我这里是设置的断点,其实没有问题)
而且提示是在771行,因为不同的版本行肯定会改变的.
(你用的是19日编译版本,我用的是29日编译版本,中间添加了这么多代码,肯定会造成行移位)
所以使用(gdb) l可以查看代码.中间一行就是出错的位置.

(gdb) l
766	
767	
768	//send a message to a friend.
769	//called by purple
770	static int qq_send_im(PurpleConnection *gc, const gchar *who, const gchar *what, PurpleMessageFlags UNUSED(flags))
771	{
772	    qq_account* ac = (qq_account*)purple_connection_get_protocol_data(gc);
773	    LwqqClient* lc = ac->qq;
774	    char nick[32],gname[32];
775	    const char* pos;

(我这里是加的断点,所以是函数一开始).
有了具体的位置了.调试起来就容易了.
最后.把这些消息都贴在github上.或者发给我.帮助调试.

最后运行(gdb) c继续运行.如果中间操作时间太长了,就会掉线.需要重新登录.