kprobe 在某个函数offset处插桩

如果想要查看内核函数地址,查一查内核符号表就行了,可是想要知道某个函数内语句相对于函数起始地址的偏移还是需要一定方法。

需求:想要在以下函数struct sk_buff *next = skb->next;处插桩,如何获取到对应的offset。

3253 struct sk_buff *dev_hard_start_xmit(struct sk_buff *first, struct net_device *dev,
3254                                     struct netdev_queue *txq, int *ret)
3255 {
3256         struct sk_buff *skb = first;
3257         int rc = NETDEV_TX_OK;
3258
3259         while (skb) {
3260                 struct sk_buff *next = skb->next;
3261
3262                 skb->next = NULL;
3263                 rc = xmit_one(skb, dev, txq, next != NULL);
3264                 if (unlikely(!dev_xmit_complete(rc))) {
3265                         skb->next = next;
3266                         goto out;
3267                 }
3268
3269                 skb = next;
3270                 if (netif_xmit_stopped(txq) && skb) {
3271                         rc = NETDEV_TX_BUSY;
3272                         break;
3273                 }
3274         }
3275
3276 out:
3277         *ret = rc;
3278         return skb;
3279 }
[root@gitclient kernel-4.18.0-80.el8]# crash /usr/lib/debug/usr/lib/modules/4.18.0-80.el8.x86_64/vmlinux /proc/kcore

crash 7.2.9-2.el8
Copyright (C) 2002-2020  Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
Copyright (C) 1999-2006  Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011  NEC Corporation
Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions.  Enter "help copying" to see the conditions.
This program has absolutely no warranty.  Enter "help warranty" for details.

GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu"...

WARNING: kernel relocated [706MB]: patching 91326 gdb minimal_symbol values

      KERNEL: /usr/lib/debug/usr/lib/modules/4.18.0-80.el8.x86_64/vmlinux
    DUMPFILE: /proc/kcore
        CPUS: 8
        DATE: Mon Mar 20 23:11:11 EDT 2023
      UPTIME: 1 days, 00:32:21
LOAD AVERAGE: 0.38, 0.14, 0.10
       TASKS: 585
    NODENAME: gitclient
     RELEASE: 4.18.0-80.el8.x86_64
     VERSION: #1 SMP Tue Jun 4 09:19:46 UTC 2019
     MACHINE: x86_64  (2200 Mhz)
      MEMORY: 16 GB
         PID: 464226
     COMMAND: "crash"
        TASK: ffff99691c43ad00  [THREAD_INFO: ffff99691c43ad00]
         CPU: 3
       STATE: TASK_RUNNING (ACTIVE)

crash> dis -s dev_hard_start_xmit

crash> help dis

NAME
  dis - disassemble

SYNOPSIS
  dis [-rfludxs][-b [num]] [address | symbol | (expression)] [count]

DESCRIPTION
  This command disassembles source code instructions starting (or ending) at
  a text address that may be expressed by value, symbol or expression:

            -r  (reverse) displays all instructions from the start of the
                routine up to and including the designated address.
            -f  (forward) displays all instructions from the given address
                to the end of the routine.
            -l  displays source code line number data in addition to the
                disassembly output.
            -u  address is a user virtual address in the current context;
                otherwise the address is assumed to be a kernel virtual address.
                If this option is used, then -r and -l are ignored.
            -x  override default output format with hexadecimal format.
            -d  override default output format with decimal format.
            -s  displays the filename and line number of the source code that
                is associated with the specified text location, followed by a
                source code listing if it is available on the host machine.
                The line associated with the text location will be marked with
                an asterisk; depending upon gdb's internal "listsize" variable,
                several lines will precede the marked location. If a "count"
                argument is entered, it specifies the number of source code
                lines to be displayed after the marked location; otherwise
                the remaining source code of the containing function will be
                displayed.
      -b [num]  modify the pre-calculated number of encoded bytes to skip after
                a kernel BUG ("ud2a") instruction; with no argument, displays
                the current number of bytes being skipped. (x86 and x86_64 only)
       address  starting hexadecimal text address.
        symbol  symbol of starting text address.  On ppc64, the symbol
                preceded by '.' is used.
  (expression)  expression evaluating to a starting text address.
         count  the number of instructions to be disassembled (default is 1).
                If no count argument is entered, and the starting address
                is entered as a text symbol, then the whole routine will be
                disassembled.  The count argument is supported when used with
                the -r and -f options.

EXAMPLES
  Disassemble the sys_signal() routine without, and then with, line numbers:

    crash> dis sys_signal
    0xc0112c88 <sys_signal>:        push   %ebp
    0xc0112c89 <sys_signal+1>:      mov    %esp,%ebp
crash> dis -s dev_hard_start_xmit
FILE: net/core/dev.c
LINE: 3255

  3250          return rc;
  3251  }
  3252
  3253  struct sk_buff *dev_hard_start_xmit(struct sk_buff *first, struct net_device *dev,
  3254                                      struct netdev_queue *txq, int *ret)
* 3255  {
  3256          struct sk_buff *skb = first;
  3257          int rc = NETDEV_TX_OK;
  3258
  3259          while (skb) {
  3260                  struct sk_buff *next = skb->next;
  3261
  3262                  skb->next = NULL;
  3263                  rc = xmit_one(skb, dev, txq, next != NULL);
  3264                  if (unlikely(!dev_xmit_complete(rc))) {
  3265                          skb->next = next;
  3266                          goto out;
  3267                  }
  3268
  3269                  skb = next;
  3270                  if (netif_xmit_stopped(txq) && skb) {
  3271                          rc = NETDEV_TX_BUSY;
  3272                          break;
  3273                  }
  3274          }
  3275
  3276  out:
  3277          *ret = rc;
  3278          return skb;
  3279  }
  crash> dis -l dev_hard_start_xmit
/usr/src/debug/kernel-4.18.0-80.el8/linux-4.18.0-80.el8.x86_64/net/core/dev.c: 3255
0xffffffffad8ca510 <dev_hard_start_xmit>:       data32 data32 data32 xchg %ax,%ax [FTRACE NOP]
/usr/src/debug/kernel-4.18.0-80.el8/linux-4.18.0-80.el8.x86_64/net/core/dev.c: 3259
0xffffffffad8ca515 <dev_hard_start_xmit+5>:     push   %r15
0xffffffffad8ca517 <dev_hard_start_xmit+7>:     push   %r14
0xffffffffad8ca519 <dev_hard_start_xmit+9>:     push   %r13
0xffffffffad8ca51b <dev_hard_start_xmit+11>:    push   %r12
0xffffffffad8ca51d <dev_hard_start_xmit+13>:    push   %rbp
0xffffffffad8ca51e <dev_hard_start_xmit+14>:    push   %rbx
0xffffffffad8ca51f <dev_hard_start_xmit+15>:    sub    $0x20,%rsp
0xffffffffad8ca523 <dev_hard_start_xmit+19>:    mov    %rcx,0x18(%rsp)
0xffffffffad8ca528 <dev_hard_start_xmit+24>:    test   %rdi,%rdi
0xffffffffad8ca52b <dev_hard_start_xmit+27>:    je     0xffffffffad8ca706 <dev_hard_start_xmit+502>
0xffffffffad8ca531 <dev_hard_start_xmit+33>:    lea    0x90(%rsi),%rax
0xffffffffad8ca538 <dev_hard_start_xmit+40>:    mov    %rsi,%rbx
0xffffffffad8ca53b <dev_hard_start_xmit+43>:    mov    %rdi,%r15
0xffffffffad8ca53e <dev_hard_start_xmit+46>:    mov    %rdx,%r13
0xffffffffad8ca541 <dev_hard_start_xmit+49>:    mov    %rax,0x8(%rsp)
/usr/src/debug/kernel-4.18.0-80.el8/linux-4.18.0-80.el8.x86_64/net/core/dev.c: 3260
0xffffffffad8ca546 <dev_hard_start_xmit+54>:    mov    (%r15),%r12
/usr/src/debug/kernel-4.18.0-80.el8/linux-4.18.0-80.el8.x86_64/net/core/dev.c: 3262
0xffffffffad8ca549 <dev_hard_start_xmit+57>:    mov    $0xffffffffae609090,%rax
0xffffffffad8ca550 <dev_hard_start_xmit+64>:    movq   $0x0,(%r15)
/usr/src/debug/kernel-4.18.0-80.el8/linux-4.18.0-80.el8.x86_64/net/core/dev.c: 3263
0xffffffffad8ca557 <dev_hard_start_xmit+71>:    mov    (%rax),%rax
0xffffffffad8ca55a <dev_hard_start_xmit+74>:    test   %r12,%r12
0xffffffffad8ca55d <dev_hard_start_xmit+77>:    setne  %bpl
/usr/src/debug/kernel-4.18.0-80.el8/linux-4.18.0-80.el8.x86_64/./include/linux/list.h: 203
0xffffffffad8ca561 <dev_hard_start_xmit+81>:    cmp    $0xffffffffae609090,%rax
0xffffffffad8ca567 <dev_hard_start_xmit+87>:    je     0xffffffffad8ca6db <dev_hard_start_xmit+459>
/usr/src/debug/kernel-4.18.0-80.el8/linux-4.18.0-80.el8.x86_64/net/core/dev.c: 3243
0xffffffffad8ca56d <dev_hard_start_xmit+93>:    mov    %rbx,%rsi
0xffffffffad8ca570 <dev_hard_start_xmit+96>:    mov    %r15,%rdi
0xffffffffad8ca573 <dev_hard_start_xmit+99>:    callq  0xffffffffad8c7fe0 <dev_queue_xmit_nit>
......

使用dis -s可以查看内核函数源码,dis -l 可以获取汇编代码对应源码的行号,如下所示便是 struct sk_buff *next = skb->next;对应的偏移0x54

0xffffffffad8ca546 <dev_hard_start_xmit+54>:    mov    (%r15),%r12
/usr/src/debug/kernel-4.18.0-80.el8/linux-4.18.0-80.el8.x86_64/net/core/dev.c: 3262
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值