systemtap监测分析代码

  • Post author:
  • Post category:其他


原理

systemtap原理类似与Runtime Hook技术,先找到函数的入口地址,然后保存函数的入口代码,再动态修改这部分代码,当内核调用函数时,systemtap就会执行检测点的修改代码,从而打印出我们需要的信息。

X86环境

Linux CentOS 3.10.0-514.2.2.el7.x86_64

安装:sudo yum install systemtap (安装时间较长)

版本信息:

Systemtap translator/driver (version 3.3/0.172, rpm 3.3-3.el7)
Copyright (C) 2005-2018 Red Hat, Inc. and others
This is free software; see the source for copying conditions.
tested kernel versions: 2.6.18 ... 4.18-rc0

实现

stap可以使用2种方式实现:

1、stap + 文本,文本中实现函数

2、./stap.sh,脚本中注明脚本解释器

分析

下面脚本实现功能是打印出内核调用do_timer函数的信息。

#!/usr/bin/stap -v

probe kernel.function("do_timer").return {
	printf("call do_timer from 0x%x\n", caller_addr());
}

超级用户运行此脚本,打印如下:

[systemtap]$ sudo ./stap.sh
语法检查
Pass 1: parsed user script and 470 library scripts using 239544virt/41312res/3408shr/37952data kb, in 240usr/170sys/671real ms.
分析统计
Pass 2: analyzed script: 1 probe, 7 functions, 5 embeds, 0 globals using 365180virt/168216res/4760shr/163588data kb, in 1900usr/1930sys/6704real ms.
转换为C代码
Pass 3: translated to C into "/tmp/stapeLJkFD/stap_16b421a9b64012d46f93109e9c4710e2_4427_src.c" using 365180virt/168496res/5040shr/163588data kb, in 180usr/70sys/345real ms.
编译为内核ko模块
Pass 4: compiled C into "stap_16b421a9b64012d46f93109e9c4710e2_4427.ko" in 3200usr/1160sys/5194real ms.
加载运行
Pass 5: starting run.
WARNING: Missing unwind data for a module, rerun with 'stap -d kernel'
打印调用信息
call do_timer from 0xffff88003c603f80
call do_timer from 0xffff88003c683ea8

地址信息需要使用addr2line工具进行转换才能看出函数名称。

修改脚本实现dump_stack函数功能。

#!/usr/bin/stap -v

probe kernel.function("do_timer").return {
	print_backtrace();
	printf("\n");
}
 0xffffffff810eb9a0 : do_timer+0x0/0x20 [kernel]
 0xffffffff810f2d00 : tick_do_update_jiffies64+0x70/0xd0 [kernel]
 0xffffffff819afed0 : __end_rodata+0x3ed0/0x4000 [kernel]
 0xffffffff810f3c77 : tick_nohz_idle_exit+0x67/0x150 [kernel] (inexact)
 0xffffffff810e7cf1 : cpu_startup_entry+0x171/0x290 [kernel] (inexact)
 0xffffffff81674627 : rest_init+0x77/0x80 [kernel] (inexact)
 0xffffffff81b0a05a : start_kernel+0x42c/0x44d [kernel] (inexact)
 0xffffffff81b09a37 : unknown_bootoption+0x0/0x186 [kernel] (inexact)
 0xffffffff81b09120 : early_idt_handler+0x0/0xb7 [kernel] (inexact)
 0xffffffff81b095ee : x86_64_start_reservations+0x2a/0x2c [kernel] (inexact)
 0xffffffff81b09742 : x86_64_start_kernel+0x152/0x175 [kernel] (inexact)

好处是不用重新编译和重新烧写或者启动内核,方便调试。

实现捕获进行切换的动作信息脚本如下:

#!/usr/bin/stap -v

probe kernel.function("__switch_to") {
	if (tast_execname($next_p) == "vim") {
		printf("switch from [%s] \t to \t [%s]\n",
		task_execname($prev_p),
		task_execname($next_p));
	}
}

probe end {
	printf("\nDONE\n");
}

运行打印错误如下:

Pass 1: parsed user script and 470 library scripts using 239548virt/41316res/3408shr/37956data kb, in 220usr/70sys/287real ms.
WARNING: function __switch_to is blacklisted: keyword at ./stap.sh:3:1
 source: probe kernel.function("__switch_to") {
         ^
semantic error: while resolving probe point: identifier 'kernel' at :3:7
        source: probe kernel.function("__switch_to") {
                      ^

semantic error: no match (similar functions: __switch_to, switch_mm, switch_idt, __stop_tx, __switch_to_xtra)

Pass 2: analyzed script: 1 probe, 0 functions, 0 embeds, 0 globals using 276036virt/78768res/4332shr/74444data kb, in 650usr/120sys/778real ms.
Pass 2: analysis failed.  [man error::pass2]

难道是我内核版本太低导致没有这个函数吗?没道理啊

ARM环境

版本4.0

Systemtap

下载地址

,下载后解压编译:

cd systemtap-4.0;mkdir build;cd build
../configure --host=arm-linux --prefix=$PWD CC=/home/wangyubo/ifoton/logread-build-tools/OS2000-70/openwrt/staging_dir/toolchain-arm_gcc-imx6ul/bin/arm-linux-gnueabihf-gcc

问题1

configure: error: missing elfutils development headers/libraries (install elfutils-devel, libebl-dev, libdw-dev and/or libebl-devel)

sudo yum install libdw-dev提示没有可用软件包 libdw-dev,手动网上

下载libdw-dev

,下载i386平台包,但格式是deb,安装alien工具转换为rpm:

sudo yum install alien

alien -r libdw-dev_0.175-2_i386.deb 进行转换

安装rmp包:

[yubo.wang@localhost systemtap]$ sudo rpm -ivh libdw-dev-0.175-3.i386.rpm 
准备中...                          ################################# [100%]
	file / from install of libdw-dev-0.175-3.i386 conflicts with file from package filesystem-3.2-21.el7.x86_64
	file /usr/lib from install of libdw-dev-0.175-3.i386 conflicts with file from package filesystem-3.2-21.el7.x86_64
	file /usr/include/elfutils/libdw.h from install of libdw-dev-0.175-3.i386 conflicts with file from package elfutils-devel-0.172-2.el7.x86_64
	file /usr/include/elfutils/libdwelf.h from install of libdw-dev-0.175-3.i386 conflicts with file from package elfutils-devel-0.172-2.el7.x86_64

安装成功后还是提示错误:

configure: error: missing elfutils development headers/libraries (install elfutils-devel, libebl-dev, libdw-dev and/or libebl-devel)

为何? 难道要用Ubuntu才行吗?

直接使用命令在x86平台配置也失败:./configure【这里可以make编译试下?在ubuntu 14.04 x86环境安装了libdw-dev后配置后也是下面的打印,make编译通过】

configure: For a private or temporary build of systemtap, we recommend
configure: configuring with a prefix.  For example, try
configure: ./configure  python='/usr/bin/python2' pyexecdir='${exec_prefix}/lib64/python2.7/site-packages' --prefix=/home/yubo.wang/systemtap-4.0-104354
configure: Running systemtap uninstalled, entirely out of the build tree,
configure: is not supported.

编译出版本信息如下,arm平台待验证。。。

切换版本

还是提示一样的问题,无改善,后续使用ubuntu测试一下,再不行的话就只有手写C代码,自己编译ko文件进行插入监测测试,需要使用到的函数:kprobe, jprobe, jretprobe



版权声明:本文为TSZ0000原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。