systemtap没找到函数变量

Easter79
• 阅读 743

为啥systemtap没找到函数

hon@station6:~/codebox/stap/net$ sudo stap -L 'kernel.function("sock_recvmsg_nosec")'
kernel.function("sock_recvmsg_nosec@/build/linux-Ay7j_C/linux-4.4.0/net/socket.c:710")

710 static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
 711                      size_t size, int flags)
 712 {
 713     return sock->ops->recvmsg(sock, msg, size, flags);
 714 }

这是很好的一个例子,函数中明明是有sock msg size flags,但是stap显示不了,这说明函数被优化过了,

但是没有变量信息,说明这个参数直接被优化掉了

难道不是edi/esi中存放的就不是第一个参数了?

gcc如何优化函数入参:windows和linux是不同的:

https://www.cnblogs.com/shangdawei/p/3323252.html

那么函数参数什么时候会被优化呢?

我ubuntu机器上vmlinux的路径是/usr/lib/debug/boot目录下面,我们看一下这段反汇编代码的样子:

7 ffffffff816fb700 <sock_recvmsg_nosec>:
  8 ffffffff816fb700:   48 8b 47 28             mov    0x28(%rdi),%rax
  9 ffffffff816fb704:   55                      push   %rbp
 10 ffffffff816fb705:   48 89 e5                mov    %rsp,%rbp
 11 ffffffff816fb708:   ff 90 90 00 00 00       callq  *0x90(%rax)
 12 ffffffff816fb70e:   5d                      pop    %rbp
 13 ffffffff816fb70f:   c3                      retq

好好分析下这段汇编代码还真是有问题呢,首先我们通过gdb发现0x28(%rdi) 这个地方的值就是是:$sock->ops呢,也就是说rax寄存器中的值就是,

(gdb) p &((struct socket *)0)->ops
$2 = (const struct proto_ops **) 0x28 <irq_stack_union+40>
(gdb) p &((struct proto_ops *)0)->recvmsg
$3 = (int (**)(struct socket *, struct msghdr *, size_t,
    int)) 0x90 <irq_stack_union+144>
这段汇编代码中两个非常关键的常数:0x28,0x90我们就知道是啥了, 第一步是$sock->ops嘛,然后第二部就是($sock->ops)->recvmsg,然后取数值,就得到真正的recv_msg的地址咯,所以直到调用函数unix_stream_recvmsg,应该edi/esi都不变才对呢,为啥就变了呢,看下参数是怎么传递的:

来个普通的func(int a, int b)函数是怎么传递参数的

273 00000000004004d6 <func>:
274   4004d6:   55                      push   %rbp
275   4004d7:   48 89 e5                mov    %rsp,%rbp
276   4004da:   89 7d fc                mov    %edi,-0x4(%rbp)
277   4004dd:   89 75 f8                mov    %esi,-0x8(%rbp)...................
281   4004e7:   c3                      retq
282 
283 00000000004004e8 <main>:
..................287   4004f0:   be 02 00 00 00          mov    $0x2,%esi
288   4004f5:   bf 01 00 00 00          mov    $0x1,%edi
289   4004fa:   e8 d7 ff ff ff          callq  4004d6 <func>
290   4004ff:   89 45 fc                mov    %eax,-0x4(%rbp)
291   400502:   b8 01 00 00 00          mov    $0x1,%eax
292   400507:   c9                      leaveq
293   400508:   c3                      retq
294   400509:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)

 即便是优化了,参数也是放在了edi/esi中,那么我读取这个寄存器咋就不行呢?

程序为了优化,在sock_recvmsg_nosec上下文中根本就看不到edi/esi/edi,

710 static inline int sock_recvmsg_nosec(struct socket *sock, struct msghdr *msg,
 711                      size_t size, int flags)
 712 {
 713     return sock->ops->recvmsg(sock, msg, size, flags); //
 714 }
 但是这里我觉得edi/esi/参数仍然是存在的于寄存器edi中,只不过在这个上下文中不存在,所以在这里我们用ktap中两种方法中第一个参数的值;

1)ulong_arg(1)

2) 直接读取寄存器edi register("edi")

结果发现惊人地相似:

regis: 0xffffffff81d5d210
ulong: 0xffffffff81d5d210
regis: 0xffffffff81d5d210
ulong: 0xffffffff81d5d210
regis: 0xffffffff81d5d210
ulong: 0xffffffff81d5d210
regis: 0xffffffff81d5d210
ulong: 0xffffffff81d5d210
发现大家指向的都是一样的 1) ulong_arg(1) 2) pointer_arg(1); (3) register("edi")

为啥子,在函数中遇到的值不是一样的咧。

在函数调用关系中sock_recvmsg->sock_recvmsg_nosec->unix_stream_recvmsg

发现在函数sock_recvmsg和函数unix_stram_recvmsg中得到的函数的变量是一致的!!只有在sock_recvmsg_nosec中得到的变量与他们相差好大,这是因为sock_recvmsg_nosec是inline函数吗?但是inline函数怎么/proc/kallsyms中也能看到呀,并且

ffffffff816fb700 t sock_recvmsg_nosec
ffffffff816fdb30 T sock_recvmsg

hello inline:0xffffffff816fdb55 sock_recvmsg
hello inline:0xffffffff816fdb55 sock_recvmsg
hello inline:0xffffffff816fdb55 sock_recvmsg
hello inline:0xffffffff816fdb55 sock_recvmsg
hello inline:0xffffffff816fdb55 sock_recvmsg
hello inline:0xffffffff816fdb55 sock_recvmsg
hello inline:0xffffffff816fdb55 sock_recvmsg
hello inline:0xffffffff816fdb55 sock_recvmsg
hello inline:0xffffffff816fdb55 sock_recvmsg

发现根本就不是函数sock_recvmsg_nosec,而是函数probefunc()

  7 probe kernel.function("sock_recvmsg_nosec").inline {
  8     printf("hello inline:%p %s\n", addr(), probefunc())
  9 }

并且输出的地址也不是sock_recvmsg_nosec,直接就是函数sock_recvmsg了,根本就没有上下文信息,所以现在的问题是为啥inline函数有单独的程序块?

inline函数是有单独的程序块,但是真正程序执行时是不会跳到这个块里的,这个块就是为了将来直接嵌入到caller中去,看下caller的汇编码就可以了

反汇编函数的代码有:真正程序执行是调用的函数调用在0x816fdb55这个地方,

7 ffffffff816fdb30 <sock_recvmsg>:
  8 ffffffff816fdb30:   e8 7b 90 12 00          callq  ffffffff81826bb0 <__fentry__>
  9 ffffffff816fdb35:   55                      push   %rbp
 10 ffffffff816fdb36:   48 89 e5                mov    %rsp,%rbp
 11 ffffffff816fdb39:   41 56                   push   %r14
 12 ffffffff816fdb3b:   41 55                   push   %r13
 13 ffffffff816fdb3d:   41 54                   push   %r12
 14 ffffffff816fdb3f:   53                      push   %rbx
 15 ffffffff816fdb40:   49 89 f4                mov    %rsi,%r12
 16 ffffffff816fdb43:   48 89 fb                mov    %rdi,%rbx
 17 ffffffff816fdb46:   49 89 d5                mov    %rdx,%r13
 18 ffffffff816fdb49:   41 89 ce                mov    %ecx,%r14d
 19 ffffffff816fdb4c:   e8 3f 18 c4 ff          callq  ffffffff8133f390 <security_socket_recvmsg>
 20 ffffffff816fdb51:   85 c0                   test   %eax,%eax
 21 ffffffff816fdb53:   75 16                   jne    ffffffff816fdb6b <sock_recvmsg+0x3b>
 22 ffffffff816fdb55:   48 8b 43 28             mov    0x28(%rbx),%rax
 23 ffffffff816fdb59:   44 89 f1                mov    %r14d,%ecx
 24 ffffffff816fdb5c:   4c 89 ea                mov    %r13,%rdx
 25 ffffffff816fdb5f:   4c 89 e6                mov    %r12,%rsi
 26 ffffffff816fdb62:   48 89 df                mov    %rbx,%rdi
 27 ffffffff816fdb65:   ff 90 90 00 00 00       callq  *0x90(%rax)
 28 ffffffff816fdb6b:   5b                      pop    %rbx
 29 ffffffff816fdb6c:   41 5c                   pop    %r12
 30 ffffffff816fdb6e:   41 5d                   pop    %r13
 31 ffffffff816fdb70:   41 5e                   pop    %r14
 32 ffffffff816fdb72:   5d                      pop    %rbp
 33 ffffffff816fdb73:   c3                      retq
 34 ffffffff816fdb74:   66 90                   xchg   %ax,%ax
 35 ffffffff816fdb76:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
 36 ffffffff816fdb7d:   00 00 00

在红色插入点的位置,可见,其实rdi/rsi/rdx/rcx的值可能已经被函数给换掉了,所以不能够使用了已经。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k