Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1240945
  • 博文数量: 122
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4004
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-20 08:27
文章分类
文章存档

2016年(1)

2015年(21)

2014年(100)

分类: LINUX

2014-08-22 00:33:44

Crash工具用于解析kdump抓取的vmcore信息,如之前分析,vmcore实际为系统运行当时的内存镜像,其中包括了所有的内存中可以看到的信息,通过Crash工具可以解析vmcore中的详细数据,本文主要以sk_buff数据结构为例简单说明Crash中间中对结构体的解析。

1、基本用法
Crash中使用struct命令解析结构体,具体用法为:
[struct] <结构体名称> <结构体虚拟地址>
其中,[struct]可以不用。

2、示例
1)启动crash
crash vmlinux vmcore

2)找到sk_buff结构体地址
a、bt命令查看当前上下文的寄存器和堆栈信息。

点击(此处)折叠或打开

  1. crash> bt
  2. PID: 27528 TASK: ffff88108e1d00c0 CPU: 6 COMMAND: "ZMSSMediaProces"
  3.  #0 [ffff88106f035740] machine_kexec at ffffffff8103237b
  4.  #1 [ffff88106f0357a0] crash_kexec at ffffffff810ba552
  5.  #2 [ffff88106f035870] oops_end at ffffffff814fc6c0
  6.  #3 [ffff88106f0358a0] die at ffffffff8100f31f
  7.  #4 [ffff88106f0358d0] do_general_protection at ffffffff814fc242
  8.  #5 [ffff88106f035900] general_protection at ffffffff814fba15
  9.     [exception RIP: put_page+9]
  10.     RIP: ffffffff8112d3a9 RSP: ffff88106f0359b8 RFLAGS: 00010206
  11.     RAX: 0000000000000030 RBX: 0000000000000001 RCX: ffff881161aa4800
  12.     RDX: ffff881161aa4e00 RSI: ffff88114b4f0c08 RDI: 4002030400585a00
  13.     RBP: ffff88106f0359b8 R8: ffff88106f0358b4 R9: 00000000fffffff2
  14.     R10: 0000000000000000 R11: 0000000000000000 R12: ffff8810dd32f280
  15.     R13: 00000000000005dc R14: ffff88106f035f18 R15: ffffffff81470720
  16.     ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
  17.  #6 [ffff88106f0359c0] skb_release_data at ffffffff8142c77f
  18.  #7 [ffff88106f0359e0] __kfree_skb at ffffffff8142c2fe
  19.  #8 [ffff88106f035a00] kfree_skb at ffffffff8142c442
  20.  #9 [ffff88106f035a30] __ip_flush_pending_frames at ffffffff814706e3
  21. #10 [ffff88106f035a50] ip_flush_pending_frames at ffffffff8147071c
  22. #11 [ffff88106f035a60] udp_flush_pending_frames at ffffffff81495be0
  23. #12 [ffff88106f035a70] udp_sendmsg at ffffffff814960f6
  24. #13 [ffff88106f035b70] inet_sendmsg at ffffffff8149e34a
  25. #14 [ffff88106f035bb0] sock_sendmsg at ffffffff81424b0a
  26. #15 [ffff88106f035d60] __sys_sendmsg at ffffffff81424fbf
  27. #16 [ffff88106f035f10] sys_sendmsg at ffffffff81425c79
  28. #17 [ffff88106f035f80] system_call_fastpath at ffffffff8100b0f2
  29.     RIP: 000000385ea0eadd RSP: 00007fa8e25cebd0 RFLAGS: 00010202
  30.     RAX: 000000000000002e RBX: ffffffff8100b0f2 RCX: 00007fa8e25cfa0f
  31.     RDX: 0000000000008000 RSI: 00007fa8e25ce6d0 RDI: 0000000000000538
  32.     RBP: 00007fa66c18c500 R8: 000000000000001c R9: 00007fa8e25cf700
  33.     R10: 00007fa8e25ce6d0 R11: 0000000000000293 R12: 0000000000000000
  34.     R13: 00007fa8e25ce9c0 R14: 00007fa8e25ced40 R15: 00007fa8e25ce9c0
  35.     ORIG_RAX: 000000000000002e CS: 0033 SS: 002b
b、反汇编,确认skb数据结构的地址:

点击(此处)折叠或打开

  1. crash> dis -l skb_release_data
  2. /usr/src/debug/kernel-2.6.32-220.el6/linux-2.6.32-220.el6.x86_64/net/core/skbuff.c: 340
  3. 0xffffffff8142c700 <skb_release_data>: push %rbp
  4. 0xffffffff8142c701 <skb_release_data+1>: mov %rsp,%rbp
  5. 0xffffffff8142c704 <skb_release_data+4>: push %r12
  6. 0xffffffff8142c706 <skb_release_data+6>: push %rbx
  7. 0xffffffff8142c707 <skb_release_data+7>: nopl 0x0(%rax,%rax,1)
  8. /usr/src/debug/kernel-2.6.32-220.el6/linux-2.6.32-220.el6.x86_64/net/core/skbuff.c: 341
  9. 0xffffffff8142c70c <skb_release_data+12>: movzbl 0x7c(%rdi),%eax
  10. /usr/src/debug/kernel-2.6.32-220.el6/linux-2.6.32-220.el6.x86_64/net/core/skbuff.c: 340
  11. 0xffffffff8142c710 <skb_release_data+16>: mov %rdi,%r12
  12. /usr/src/debug/kernel-2.6.32-220.el6/linux-2.6.32-220.el6.x86_64/net/core/skbuff.c: 341
  13. 0xffffffff8142c713 <skb_release_data+19>: test $0x2,%al
  14. 0xffffffff8142c715 <skb_release_data+21>: je 0xffffffff8142c742 <skb_release_data+66>
  15. /usr/src/debug/kernel-2.6.32-220.el6/linux-2.6.32-220.el6.x86_64/net/core/skbuff.c: 342
  16. ...
结合代码,可以确认skb变量地址通过r12寄存器寄存器,则r12寄存器中保存的即为skb变量的地址,地址为:ffff8810dd32f280

c、通过变量地址打印,结构体内容

点击(此处)折叠或打开

  1. crash> sk_buff ffff8810dd32f280
  2. struct sk_buff {
  3.   next = 0x0,
  4.   prev = 0x0,
  5.   sk = 0xffff88114b4f0b40,
  6.   tstamp = {
  7.     tv64 = 0
  8.   },
  9.   dev = 0x0,
  10.   _skb_dst = 0,
  11.   sp = 0x0,
  12.   cb = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
  13. struct sk_buff {
  14.   next = 0x0,
  15.   prev = 0x0,
  16.   sk = 0xffff88114b4f0b40,
  17.   tstamp = {
  18.     tv64 = 0
  19.   },
  20.   dev = 0x0,
  21.   _skb_dst = 0,
  22.   sp = 0x0,
  23.   cb = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\00
  24. 0\000",
  25.   len = 1500,
  26.   data_len = 0,
  27.   mac_len = 0,
  28.   hdr_len = 0,
  29.   {
  30.     csum = 1527250250,
  31.     {
  32.       csum_start = 64842,
  33.       csum_offset = 23303
  34.     }
  35.   },
  36.   priority = 0,
  37.   flags1_begin = 0xffff8810dd32f2fc,
  38.   local_df = 0 '\000',
  39.   cloned = 0 '\000',
  40.   ip_summed = 0 '\000',
  41.   nohdr = 0 '\000',
  42.   nfctinfo = 0 '\000',
  43.   pkt_type = 0 '\000',
  44.   fclone = 0 '\000',
  45.   ipvs_property = 0 '\000',
  46.   peeked = 0 '\000',
  47.   nf_trace = 0 '\000',
  48.   protocol = 0,
  49. ...
  50.   transport_header = 76,
      network_header = 16,
      mac_header = 4294967295,
      tail = 1516,
      end = 1536,
      head = 0xffff881161aa4800 "",
      data = 0xffff881161aa4810 "",
      truesize = 1768,
      users = {
        counter = 1
      }
3)通过sk_buff结构体内容,确认head和data指针,通过x命令查看地址内容,其中16xg表示查看0x16(十六进制)长度的数据

点击(此处)折叠或打开

  1. crash> x/16xg 0xffff881161aa4800
  2. 0xffff881161aa4800: 0x0000000000000000 0x0008000000000000
  3. 0xffff881161aa4810: 0x0000000000000000 0x884509ff00000000
  4. 0xffff881161aa4820: 0x113d000001006005 0x007fe200f20a27ed
  5. 0xffff881161aa4830: 0x4c0508a930310900 0xb1d2745121900000
  6. 0xffff881161aa4840: 0x585a547439439fff 0x0000004b02e30400
  7. 0xffff881161aa4850: 0x4002030400585a00 0x017306e8a8ed53c9
  8. 0xffff881161aa4860: 0xca21900000a40559 0x0000004b5f2b1275
  9. 0xffff881161aa4870: 0x4002830400585a00 0x017306e8a8ed53c9
4)通过sk_buff的head和end成员,确认skb_shared_info结构的内容(该机构存放于end之后),即其地址为0xffff881161aa4800+1536(end)=0xffff881161aa4E00

点击(此处)折叠或打开

  1. crash> skb_shared_info 0xffff881161aa4E00
  2. struct skb_shared_info {
  3.   dataref = {
  4.     counter = 10749386
  5.   },
  6.   nr_frags = 36864,
  7.   gso_size = 51745,
  8.   gso_segs = 4753,
  9.   gso_type = 33323,
  10.   ip6_frag_id = 203,
  11.   tx_flags = {
  12.     {
  13.       hardware = 0 '\000',
  14.       software = 0 '\000',
  15.       in_progress = 0 '\000',
  16.       reserved = 0 '\000',
  17.       dev_zerocopy = 0 '\000'
  18.     },
  19.     flags = 0 '\000'
  20.   },
  21.   frag_list = 0x17306e8a8ed53c9,
  22.   hwtstamps = {
  23.     hwtstamp = {
  24.       tv64 = -3881663074131507766
  25.     },
  26.     syststamp = {
  27.       tv64 = 650841363090
  28.     }
  29.   },
  30. ...
其实可以明显看出,上述示例中的skb_shared_info结构的数据不对,因为这个数据区被踩坏了,本示例就是在分析内存被踩的问题。

5)通过sk_buff查看sock结构内容,可以直接通过sk_buff->sk指针,从上面的sk_buff结构内容看,其值为0xffff88114b4f0b40

点击(此处)折叠或打开

  1. struct sock {
  2.   __sk_common = {
  3.     {
  4.       skc_node = {
  5.         next = 0xffff8810debddb80,
  6.         pprev = 0xffff881204a84ec0
  7.       },
  8.       skc_nulls_node = {
  9.         next = 0xffff8810debddb80,
  10.         pprev = 0xffff881204a84ec0
  11.       }
  12.     },
  13.     skc_refcnt = {
  14.       counter = 2
  15.     },
  16.     skc_hash = 33728,
  17.     skc_family = 2,
  18.     skc_state = 1 '\001',
  19.     skc_reuse = 1 '\001',
  20.     skc_bound_dev_if = 0,
  21.     skc_bind_node = {
  22.       next = 0x0,
  23.       pprev = 0x0
  24.     },
  25. 。。。
  26.   sk_write_queue = {
        next = 0xffff8810d3f26780,
        prev = 0xffff8810d3f26780,
        qlen = 1,
        lock = {
          raw_lock = {
            slock = 0
          }
        }
      },
    。。。

6)通过sock结构,查看sock发送队列中的所有sk_buff,可以通过sock->sk_write_queue->next和sock->sk_write_queue->prev查看:

点击(此处)折叠或打开

  1. crash> sk_buff 0xffff8810d3f26780
  2. struct sk_buff {
  3.   next = 0xffff88114b4f0c08,
  4.   prev = 0xffff88114b4f0c08,
  5.   sk = 0xffff88114b4f0b40,
  6.   tstamp = {
  7.     tv64 = 0
  8.   },
  9.   dev = 0x0,
  10.   _skb_dst = 0,
  11.   sp = 0x0,
  12.   cb = "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
  13.   len = 1500,
  14.   data_len = 1432,
  15.   mac_len = 0,
  16.   hdr_len = 0,

阅读(9475) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~