利用dmesg和addr2line来对(动态库里的)段错误进行调试

问题:

工作中,我们在varnish的基础上,利用vmod机制,实现了一个可以定制策略,且策略可自动加载而不需重新启动引擎的cache(平时,大家对varnish的利用,cache策略都定义在一个vcl配置文件中,每次对策略进行修改,都需要重新启动varnish,从而使得策略生效,且当部署在varnish后面的站点很多时,不方便对每站点的cache策略进行个性化的定制),这里各种策略的控制以及加载都实现在一个vmod模块里(libvmod_ngcache.so),很开心,产品上线了。那么问题来,(挖掘机技术那家强?)当程序上到线上的时候,有时会出现各种bug,尤其是当程序崩溃了,而又没有对相应的core dump信息进行保存的时候,怎么定位问题出在程序的哪个位置就成为了一个难题,这篇文章就以我们的cache为实例,来示例定位问题。

 

解决方法:

程序发生段错误时,提示信息很少,在没有保存相应的core dump信息的情况下,要对这类错误进行调试尤为显得捉襟见肘,幸运的是我们可以利用linux系统自带的一些小工具来查看段错误发生的各种信息:

 

dmesg 可以在应用程序崩溃的时候,显示内核中保存的相关信息:

root@****:/home/l7# dmesg-T | grep varnishd

[Thu Dec  421:25:58 2014] varnishd[16470] general protection ip:7feb693443bbsp:7feb669ea1e0 error:0 in libvmod_ngcache.so.1.0.0[7feb69331000+52000]

 

有时候,通过查看相应的内核日志,也可以查看到同样的信息:

root@****:/home/l7# cat/var/log/kern.log

Dec  5 07:49:34 ****kernel: [17376990.017811] varnishd[16470] general protection ip:7feb693443bbsp:7feb669ea1e0 error:0 in libvmod_ngcache.so.1.0.0[7feb69331000+52000]

 


root@****:/home/l7# dmesg| grep varnishd

[17376990.017811] varnishd[16470] general protectionip:7feb693443bb sp:7feb669ea1e0 error:0 inlibvmod_ngcache.so.1.0.0[7feb69331000+52000]

输出信息内容:段错误发生的时间([17376990.017811])、发生段错误的程序名称[进程号](varnishd[16470])、引起段错误发生的指令指针地址(general protection ip:7feb693443bb)、引起段错误发生的堆栈指针地址(sp:7feb669ea1e0)、错误代码(error:0)、libvmod_ngcache.so.1.0.0[7feb69331000+52000](In the libfoo.so[NNNNNN+YYYY] part, the NNNNNN is where the librarywas loaded. Subtract this from theinstruction pointer (ip) and you'll getthe offset into the .so of the offendinginstruction. Then you can use objdump -DCgl libfoo.so andsearch for the instruction at that offset. You should easily be able to figureout which function it is from the asm labels.If the .so doesn't haveoptimizations you can also try using addr2line-e libfoo.so , 52000 = 0xcb20)。



因此,有动作:

(一):

ip:0x7feb693443bb -libvmod_ngcache.so.1.0.0[0x7feb69331000+YYYY] = 0x133bb

root@****:/home/l7# objdump-DCgl /usr/local/lib/varnish/vmods/libvmod_ngcache.so | grep -C 10 133bb

   1339c: 0f b6 c2               movzbl%dl,%eax

   1339f: 48 8b 5c c1 08         mov    0x8(%rcx,%rax,8),%rbx

/var/lib/jenkins/workspace/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/varnish_vmod/libvmod-ngcache/src/sfksearch.c:864

   133a4: 48 85 db               test   %rbx,%rbx

   133a7: 74 1f                  je     133c8

   133a9: 44 8b 6c 24 2c         mov    0x2c(%rsp),%r13d

   133ae: 4c 89 fd               mov    %r15,%rbp

   133b1: 0f 1f 80 00 00 00 00   nopl   0x0(%rax)

/var/lib/jenkins/workspace/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/varnish_vmod/libvmod-ngcache/src/sfksearch.c:868

   133b8: 0f b6 c2               movzbl%dl,%eax

   133bb: 39 03                  cmp    %eax,(%rbx)

   133bd: 74 71                  je     13430 <KTrieSearch+0x220>

/var/lib/jenkins/workspace/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/varnish_vmod/libvmod-ngcache/src/sfksearch.c:895

   133bf: 48 8b 5b 08            mov    0x8(%rbx),%rbx

   133c3: 48 85 db               test   %rbx,%rbx

   133c6: 75 f0                  jne    133b8

KTrieSearchNoBC():

/var/lib/jenkins/workspace/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/varnish_vmod/libvmod-ngcache/src/sfksearch.c:979

   133c8: 44 01 74 24 30         add    %r14d,0x30(%rsp)

/var/lib/jenkins/workspace/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/varnish_vmod/libvmod-ngcache/src/sfksearch.c:977

   133cd: 49 83 c7 01            add    $0x1,%r15

这里基本上可以定位到出问题的函数了。

 

(二):

ip:0x7feb693443bb -libvmod_ngcache.so.1.0.0[0x7feb69331000+YYYY] = 0x133bb

root@****:/home/l7# addr2line-e /usr/local/lib/varnish/vmods/libvmod_ngcache.so 0x133bb -f

KTriePrefixMatch

/var/lib/jenkins/workspace/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/l7cache_ngcache_vmod_for_varnish3.0.5_First_Edition/varnish_vmod/libvmod-ngcache/src/sfksearch.c:868

 

(三):

ip:0x7feb693443bb -libvmod_ngcache.so.1.0.0[0x7feb69331000+YYYY] = 0x133bb

root@****:/home/l7# gdb/usr/local/lib/varnish/vmods/libvmod_ngcache.so

......

(gdb) disass0x133bb

  ......

  0x0000000000013399 <+393>:    xor    %r14d,%r14d

  0x000000000001339c <+396>:    movzbl%dl,%eax

  0x000000000001339f <+399>:    mov    0x8(%rcx,%rax,8),%rbx

  0x00000000000133a4 <+404>:    test   %rbx,%rbx

  0x00000000000133a7 <+407>:    je     0x133c8

  0x00000000000133a9 <+409>:    mov    0x2c(%rsp),%r13d

  0x00000000000133ae <+414>:    mov    %r15,%rbp

  0x00000000000133b1 <+417>:    nopl   0x0(%rax)

  0x00000000000133b8 <+424>:    movzbl%dl,%eax

   0x00000000000133bb <+427>:   cmp   %eax,(%rbx)

  0x00000000000133bd <+429>:    je     0x13430 <KTrieSearch+544>

  0x00000000000133bf <+431>:    mov    0x8(%rbx),%rbx

  0x00000000000133c3 <+435>:    test   %rbx,%rbx

  0x00000000000133c6 <+438>:    jne    0x133b8

 

另:推荐一些工具,供大家学习使用:

gdb、ldd、eu-readelf、readelf、objdump、dmesg、addr2line、nm、catchsegv;

另外建议,像这种线上的程序,尽量配置当程序crash的时候有coredump文件产生或者记录stack backtrace。

 

问题的查找,参考了网络上很多的文章和Q&A,在这里表示感谢并列出原文引用,谢谢!

Refer:

1、"Linux环境下段错误的产生原因及调试方法小结"

http://www.cnblogs.com/panfeng412/archive/2011/11/06/segmentation-fault-in-linux.html

 

2、"How doyou read a segfault kernel log message"

http://stackoverflow.com/questions/2179403/how-do-you-read-a-segfault-kernel-log-message

 

3、"DebuggingC++ (Part 3): dmesg"

http://enki-tech.blogspot.com/2012/08/debugging-c-part-3-dmesg.html

 

4、"Introductionto segmentation fault handling"

http://www.slideshare.net/noobyahoo/introduction-to-segmentation-fault-handling-5563036

 

5、"Pythoncrashed; how to decode segfault in dmesg log?"

http://stackoverflow.com/questions/21269999/python-crashed-how-to-decode-segfault-in-dmesg-log

你可能感兴趣的:(debugging,varnish)