systemtap没找到函数变量
为啥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的值可能已经被函数给换掉了,所以不能够使用了已经。
systemtap没找到函数变量的更多相关文章
- python note 10 函数变量
1.命名空间 #内置命名空间 —— python解释器 # 就是python解释器一启动就可以使用的名字存储在内置命名空间中 # 内置的名字在启动解释器的时候被加载进内存里#全局命名空间 —— 我们写 ...
- Python基础3 函数 变量 递归 -DAY3
本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...
- 探究javascript对象和数组的异同,及函数变量缓存技巧
javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...
- C++中函数变量布局小结
把布局作为一种信仰(Layout as Religion). ...
- 没找到Wkhtmltopdf,报表会被显示为html
windows10 odoo 打印报表时提示 没找到Wkhtmltopdf,报表会被显示为html 现象 原因 没有安装Wkhtmltopdf,没有配置环境变量,odoo在电脑系统中找不到Wkhtml ...
- 函数变量作用域(python)
收集参数:该参数个数不确定 >>> def test(*params): print('参数的长度是:', len(params)); print('第二个参数是:', params ...
- 创建 userSettings/Microsoft.SqlServer.Configuration.LandingPage.Properties.Settings 的配置节处理程序时出错: 未能加载文件或程序集“System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”或它的某一个依赖项。系统没找到指定的文件
创建 userSettings/Microsoft.SqlServer.Configuration.LandingPage.Properties.Settings 的配置节处理程序时出错: 未能加载文 ...
- 解决SecureCRT中文版"数据库里没找到防火墙'无'"的错误提示
问题描述: 最近从同事那拷贝到一个中文版的SecureCRT,但是每次打开都会有个防火墙的错误提示,“数据库里没找到防火墙“无”.此会话将尝试不通过防火墙进行连接. 出现这个错误的原因是在Secure ...
- day11.1函数进阶 列表集合 字典中的函数变量,函数作为形参
函数进阶 1.函数作为变量 a=123 name="gao" nums=[1,2,3] data=nums#指向同一个内存地址 #查看内存地址篇章 def func(): prin ...
随机推荐
- 解方程(hash,秦九韶算法)
题目描述 已知多项式方程: a0+a1x+a2x2+⋯+anxn=0 求这个方程在 [1,m]内的整数解(n 和 m 均为正整数). 输入输出格式 输入格式: 共 n+2 行. 第一行包含 2个整数 ...
- ABAP术语-Database Rollback
Database Rollback 原文:http://www.cnblogs.com/qiangsheng/archive/2008/01/24/1051238.html Operation tha ...
- (转载)jsp的内部方法jspInit(),_jspService(),jspDestroy()
jspInit(){}:jsp Page被初始化的时候调用该方法,并且该方法仅在初始化时执行一次,所以可以在这里进行一些初始化的参数配置等一次性工作,由作者创建jspDestroy(){}:jsp P ...
- Hash学习笔记
啊啊啊啊,这篇博客估计是我最早的边写边学的博客了,先忌一忌. 本文章借鉴与一本通提高篇,但因为是个人的学习笔记,因此写上原创. 目录 谁TM边写边学还写这玩意? 后面又加了 Hash Hash表 更多 ...
- HBase配置和使用
参考官方文档 整体实现框架 图1 以下几个为组成部件 21892 HMaster 22028 HRegionServer 21553 QuorumPeerMain 2366 NameNode 2539 ...
- Python: 列表的两种遍历方法
方法一:以列表中元素的下标进行访问 def traverse1(list1): for i in range(len(list1)): print(list1[i], end=' ') print() ...
- Error: Error while compiling statement: FAILED: SemanticException Unable to determine if hdfs://hadoopNode2:8020/user/hive/warehouse/test is encrypted...
1.发现问题: 在hive客户端或者beeline查询hive表时候报错: 根据报错信息查看,是在集群namenode做了HA之后,产生的hdfs路径不对的问题: 2.解决问题,修改hive元数据my ...
- idea离线安装lombock插件
技术交流群:233513714 安装过程 1.首先找到插件包 插件包可以在两个地方下载,分别是IDEA的官方插件仓库和GitHub里lombok-intellij-plugin仓库中的release包 ...
- CC3200模块的内存地址划分和bootloader(一)
1. CC3200的内存地址划分非常特殊,如果没测试的话,很容易懵逼.我们先看芯片手册里面的内存地址.芯片的RAM是256KB,下图的0x2000 0000-0x2003 FFFF,正好是256KB. ...
- SQL On Streaming
此文已由作者岳猛授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 实时计算的一个方向 实时计算未来会成为一个趋势,基本上所有的离线计算任务都能通过实时计算来完成,对于实时计算来 ...