Systemtap : stap PROCESSING 5 steps introduce
背景
stap处理stp时, 分5步进行, 以下取自man stap :
第一步 :
The translator begins pass 1 by parsing the given input script, and all scripts (files named *.stp) found in a tapset directory.
The directories listed with -I are processed in sequence, each processed in "guru mode".
"guru mode" : Enable parsing of unsafe expert-level constructs like embedded C.
For each directory, a number of subdirectories are also searched.
These subdirectories are derived from the selected kernel version (the -R option), in order to allow more kernel-version-specific scripts to override less specific ones.
For example, for a kernel version 2.6.12-23.FC3 the following patterns would be searched, in sequence:
2.6.12-23.FC3/*.stp,
2.6.12/*.stp,
2.6/*.stp,
and finally *.stp Stopping the translator after pass 1 causes it to print the parse trees.
第一步做的事情是 :
解析stap输入脚本, 或者-e中指定的内容, 以及tapset库, -I检索路径中的*.stp文件.
如下 :
parsed user script and 95 library script.
[root@db-172-16-3-150 ~]# stap --vp 50000 -I /tmp -e 'probe syscall.read {printf("hello i am digoal.\n"); exit()}'
Parsed kernel "/lib/modules/2.6.32-358.el6.x86_64/build/.config", containing 3166 tuples
Parsed kernel /lib/modules/2.6.32-358.el6.x86_64/build/Module.symvers, which contained 5541 vmlinux exports
Searched: " /usr/share/systemtap/tapset/x86_64/*.stp ", found: 10, processed: 10
Searched: " /usr/share/systemtap/tapset/*.stp ", found: 82, processed: 82
Searched: " /tmp/2.6.32-358.el6.x86_64/*.stp ", found: 1, processed: 1
Searched: " /tmp/2.6.32/*.stp ", found: 1, processed: 1
Searched: " /tmp/2.6/*.stp ", found: 1, processed: 1
Pass 1: parsed user script and 95 library script(s) using 203480virt/31780res/3104shr/29416data kb, in 290usr/20sys/307real ms.
hello i am digoal.
第一步中, -R在测试时发现一个BUG, 参见 :
http://blog.163.com/digoal@126/blog/static/16387704020139142437763/
第二步 :
分析 stap"执行脚本或者-e中指定内容" 包含的符号(指变量,函数,探针, 条件预编译, 宏 ,符号(probe,function, global..等语法型字符)等) 以及变量类型(猜或指定类型如函数返回值和参数).
未能直接分析出来的符号, 将通过第一步得到的tapset库进行匹配, 只要匹配到了, 就会把对应的stp(探针库), stpm(宏库)文件选择进来.
直到所有的符号都分析匹配完.
In pass 2, the translator analyzes the input script to resolve symbols and types.
References to variables, functions, and probe aliases that are unresolved internally are satisfied by searching through the parsed tapset script files.
If any tapset script file is selected because it defines an unresolved symbol, then the entirety of that file is added to the translator's resolution queue.
This process iterates until all symbols are resolved and a subset of tapset script files is selected.
接下来校验stap脚本(或-e内容)中用到的所有的探针, 以及探针handler中的target端变量.
Next, all probe point descriptions are validated against the wide variety supported by the translator.
Probe points that refer to code locations ("synchronous probe points") require the appropriate kernel debugging information to be installed.
In the associated probe handlers, target-side variables (whose names begin with "$") are found and have their run-time locations decoded.
如果未使用stap -u选项, 那么接下来要做的是优化脚本. 移除未使用的变量, 表达式, 函数等.
具体的优化规则参见 :
http://blog.163.com/digoal@126/blog/static/16387704020138109459201/
Next, all probes and functions are analyzed for optimization opportunities, in order to remove variables, expressions, and functions that have no useful value and no side-effect.
Embedded-C functions are assumed to have side-effects unless they include the magic string /* pure */.
Since this optimization can hide latent code errors such as type mismatches or invalid $target variables, it sometimes may be useful to disable the optimizations with the -u option.
pass2最后要做的是, 根据上下文(例如语境或操作符)推测所有变量的类型, 函数的返回值类型和参数类型, 数组中存储的类型, 数组的索引类型.
Finally, all variable, function, parameter, array, and index types are inferred from context (literals and operators).
Stopping the translator after pass 2 causes it to list all the probes, functions, and variables, along with all inferred types.
Any inconsistent or unresolved types cause an error.
第二步示例输出如下 :
[root@db-172-16-3-150 ~]# stap --vp 05000 -I /tmp -e 'probe syscall.read {printf("hello i am digoal.\n"); exit()}'
Attempting to extract kernel debuginfo build ID from /lib/modules/2.6.32-358.el6.x86_64/build/vmlinux.id
Attempting to extract kernel debuginfo build ID from /sys/kernel/notes
blacklist regexps:
blfn: ^(atomic_notifier_call_chain|default_do_nmi|__die|die_nmi|do_debug|do_general_protection|do_int3|do_IRQ|do_page_fault|do_sparc64_fault|do_trap|dummy_nmi_callback|flush_icache_range|ia64_bad_break|ia64_do_page_fault|ia64_fault|io_check_error|mem_parity_error|nmi_watchdog_tick|notifier_call_chain|oops_begin|oops_end|program_check_exception|single_step_exception|sync_regs|unhandled_fault|unknown_nmi_error|xen_[gs]et_debugreg|xen_irq_.*|xen_.*_fl_direct.*|check_events|xen_adjust_exception_frame|xen_iret.*|xen_sysret64.*|test_ti_thread_flag.*|inat_get_opcode_attribute|system_call_after_swapgs|.*raw_.*_lock.*|.*raw_.*_unlock.*|.*raw_.*_trylock.*|.*read_lock.*|.*read_unlock.*|.*read_trylock.*|.*write_lock.*|.*write_unlock.*|.*write_trylock.*|.*write_seqlock.*|.*write_sequnlock.*|.*spin_lock.*|.*spin_unlock.*|.*spin_trylock.*|.*spin_is_locked.*|rwsem_.*lock.*|.*mutex_.*lock.*|raw_.*|atomic_.*|atomic64_.*|get_bh|put_bh|.*apic.*|.*APIC.*|.*softirq.*|.*IRQ.*|.*_intr.*|__delay|.*kernel_text.*|get_current|current_.*|.*exception_tables.*|.*setup_rt_frame.*|.*preempt_count.*|preempt_schedule|__switch_to|special_mapping_.*|.*_pte_.*)$
blfn_ret: ^(do_exit|sys_exit|sys_exit_group)$
blfile: ^(kernel/kprobes\.c|arch/.*/kernel/kprobes\.c|.*/include/asm/io\.h|.*/include/asm/io_64\.h|.*/include/asm/bitops\.h|drivers/ide/ide-iops\.c|arch/.*/kernel/paravirt\.c|.*/include/asm/paravirt\.h|fs/seq_file\.c)$
blsection: ^(\.init\.|\.exit\.|\.devinit\.|\.devexit\.|\.cpuinit\.|\.cpuexit\.|\.meminit\.|\.memexit\.)
dwarf_builder::build for
parse 'sys_read', func 'sys_read'
pattern 'kernel' matches module 'kernel'
focused on module 'kernel' = [0xffffffff81000000-0xffffffff8203c000, bias 0 file /usr/lib/debug/lib/modules/2.6.32-358.el6.x86_64/vmlinux ELF machine |x86_64 (code 62)
focused on module 'kernel'
module function cache kernel size 60247
module function cache kernel hit sys_read
selected function sys_read
function cache kernel:fs/read_write.c size 114
function cache kernel:fs/read_write.c hit sys_read
selected function sys_read
probe sys_read@fs/read_write.c:389 kernel reloc=.dynamic pc=0xffffffff811817b0
die parent cache kernel:fs/read_write.c size 611
finding location for local 'fd' near address 0xffffffff811817b0, module bias 0
get_cfa_ops @0xffffffff811817b0, module_start @0xffffffff81000000
got dwarf cfi bias: 0x0
found cfa, info: 16 [start: 0xffffffff811817b0, end: 0xffffffff811817b1, nops: 1
finding location for local 'buf' near address 0xffffffff811817b0, module bias 0
get_cfa_ops @0xffffffff811817b0, module_start @0xffffffff81000000
got dwarf cfi bias: 0x0
found cfa, info: 16 [start: 0xffffffff811817b0, end: 0xffffffff811817b1, nops: 1
finding location for local 'count' near address 0xffffffff811817b0, module bias 0
get_cfa_ops @0xffffffff811817b0, module_start @0xffffffff81000000
got dwarf cfi bias: 0x0
found cfa, info: 16 [start: 0xffffffff811817b0, end: 0xffffffff811817b1, nops: 1
finding location for local 'fd' near address 0xffffffff811817b0, module bias 0
get_cfa_ops @0xffffffff811817b0, module_start @0xffffffff81000000
got dwarf cfi bias: 0x0
found cfa, info: 16 [start: 0xffffffff811817b0, end: 0xffffffff811817b1, nops: 1
finding location for local 'buf' near address 0xffffffff811817b0, module bias 0
get_cfa_ops @0xffffffff811817b0, module_start @0xffffffff81000000
got dwarf cfi bias: 0x0
found cfa, info: 16 [start: 0xffffffff811817b0, end: 0xffffffff811817b1, nops: 1
finding location for local 'count' near address 0xffffffff811817b0, module bias 0
get_cfa_ops @0xffffffff811817b0, module_start @0xffffffff81000000
got dwarf cfi bias: 0x0
found cfa, info: 16 [start: 0xffffffff811817b0, end: 0xffffffff811817b1, nops: 1
deleting module_cache
Eliding side-effect-free empty block operator '{' at /usr/share/systemtap/tapset/syscalls2.stp:676:1
Flattening nested block operator '{' at <input>:1:20
Pass 2: analyzed script: 1 probe(s), 1 function(s), 0 embed(s), 0 global(s) using 358144virt/132372res/79236shr/53812data kb, in 620usr/40sys/655real ms.
hello i am digoal.
第三步 :
将以上解析好的stap脚本转换成c代码.
In pass 3, the translator writes C code that represents the actions of all selected script files, and creates a Makefile to build that into a kernel object.
These files are placed into a temporary directory.
Stopping the translator at this point causes it to print the contents of the C file.
第三步示例输出如下 :
[root@db-172-16-3-150 ~]# stap --vp 00500 -I /tmp -e 'probe syscall.read {printf("hello i am digoal.\n"); exit()}'
Pass 3: using cached /root/.systemtap/cache/e8/stap_e878009262b7836eb07f0b5a0bf0705e_970.c
hello i am digoal.
第四步 :
使用第三步生成的c文件创建linux内核对象文件(.ko).
In pass 4, the translator invokes the Linux kernel build system to create the actual kernel object file.
This involves running make in the temporary directory, and requires a kernel module build system (headers, config and Makefiles) to be installed in the usual spot /lib/modules/VERSION/build.
Stopping the translator after pass 4 is the last chance before running the kernel object.
This may be useful if you want to archive the file.
第四步示例输出如下 :
[root@db-172-16-3-150 ~]# stap --vp 00050 -I /tmp -e 'probe syscall.read {printf("hello i am digoal.\n"); exit()}'
Pass 4: using cached /root/.systemtap/cache/e8/stap_e878009262b7836eb07f0b5a0bf0705e_970.ko
hello i am digoal.
第五步 :
调用staprun, 将ko文件加载到内核中, 并与之通讯, 拷贝这个内核对象跟踪到的数据到临时文件中. 直到stap运行结束或受到中断请求信号.
最后staprun 从内核中卸载这个ko模块, 并且清除整个stap过程产生的临时文件.
In pass 5, the translator invokes the systemtap auxiliary program staprun program for the given kernel object.
This program arranges to load the module then communicates with it, copying trace data from the kernel into temporary files, until the user sends an interrupt signal.
Any run-time error encountered by the probe handlers, such as running out of memory, division by zero, exceeding nesting or runtime limits, results in a soft error indication.
Soft errors in excess of MAXERRORS block of all subsequent probes (except error-handling probes), and terminate the session.
Finally, staprun unloads the module, and cleans up.
第五步示例输出如下 :
[root@db-172-16-3-150 ~]# stap --vp 00005 -I /tmp -e 'probe syscall.read {printf("hello i am digoal.\n"); exit()}'
Pass 5: starting run.
Running /usr/bin/staprun -v -v -R /tmp/stapNmEOL6/stap_e878009262b7836eb07f0b5a0bf0705e_970.ko
staprun:main:387 modpath="/tmp/stapNmEOL6/stap_e878009262b7836eb07f0b5a0bf0705e_970.ko", modname="stap_e878009262b7836eb07f0b5a0bf0705e_970"
staprun:init_staprun:305 init_staprun
staprun:insert_module:73 inserting module /tmp/stapNmEOL6/stap_e878009262b7836eb07f0b5a0bf0705e_970.ko
staprun:insert_module:99 module options: _stp_bufsize=0
staprun:insert_module:107 module path canonicalized to '/tmp/stapNmEOL6/stap_e878009262b7836eb07f0b5a0bf0705e_970.ko'
staprun:check_signature:441 checking signature for /tmp/stapNmEOL6/stap_e878009262b7836eb07f0b5a0bf0705e_970.ko
Signature file /tmp/stapNmEOL6/stap_e878009262b7836eb07f0b5a0bf0705e_970.ko.sgn not found
staprun:check_signature:454 verify_module returns 0
staprun:insert_module:170 Renaming module 'stap_e878009262b7836eb07f0b5a0bf0705e_970'
staprun:insert_module:178 Renamed module to 'stap_e878009262b7836eb07f0b5a0bf070_14544'
staprun:init_ctl_channel:31 Opened /sys/kernel/debug/systemtap/stap_e878009262b7836eb07f0b5a0bf070_14544/.cmd (4)
staprun:close_ctl_channel:66 Closed ctl fd 4
execing: /usr/libexec/systemtap/stapio -v -v -R stap_e878009262b7836eb07f0b5a0bf070_14544
stapio:parse_modpath:408 modpath="/lib/modules/2.6.32-358.el6.x86_64/systemtap/stap_e878009262b7836eb07f0b5a0bf070_14544.ko"
stapio:main:41 modpath="/lib/modules/2.6.32-358.el6.x86_64/systemtap/stap_e878009262b7836eb07f0b5a0bf070_14544.ko", modname="stap_e878009262b7836eb07f0b5a0bf070_14544"
stapio:init_stapio:367 init_stapio
stapio:init_ctl_channel:31 Opened /sys/kernel/debug/systemtap/stap_e878009262b7836eb07f0b5a0bf070_14544/.cmd (4)
stapio:stp_main_loop:565 in main loop
stapio:stp_main_loop:584 select_supported: 1
stapio:init_relayfs:244 initializing relayfs
stapio:init_relayfs:268 attempting to open /sys/kernel/debug/systemtap/stap_e878009262b7836eb07f0b5a0bf070_14544/trace0
stapio:init_relayfs:268 attempting to open /sys/kernel/debug/systemtap/stap_e878009262b7836eb07f0b5a0bf070_14544/trace1
stapio:init_relayfs:274 ncpus=1, bulkmode = 0
stapio:init_relayfs:357 starting threads
stapio:stp_main_loop:736 systemtap_module_init() returned 0
stapio:stp_main_loop:727 got STP_REQUEST_EXIT
hello i am digoal.
stapio:stp_main_loop:720 got STP_EXIT
stapio:cleanup_and_exit:452 detach=0
stapio:close_relayfs:373 closing
stapio:close_relayfs:392 done
stapio:cleanup_and_exit:469 closing control channel
stapio:close_ctl_channel:66 Closed ctl fd 4
stapio:cleanup_and_exit:477
Renamed module to: stap_e878009262b7836eb07f0b5a0bf070_14544
stapio:cleanup_and_exit:484 removing stap_e878009262b7836eb07f0b5a0bf070_14544
staprun:parse_modpath:408 modpath="/lib/modules/2.6.32-358.el6.x86_64/systemtap/stap_e878009262b7836eb07f0b5a0bf070_14544.ko"
staprun:main:387 modpath="/lib/modules/2.6.32-358.el6.x86_64/systemtap/stap_e878009262b7836eb07f0b5a0bf070_14544.ko", modname="stap_e878009262b7836eb07f0b5a0bf070_14544"
staprun:init_staprun:305 init_staprun
staprun:remove_module:222 stap_e878009262b7836eb07f0b5a0bf070_14544
staprun:init_ctl_channel:31 Opened /sys/kernel/debug/systemtap/stap_e878009262b7836eb07f0b5a0bf070_14544/.cmd (4)
staprun:close_ctl_channel:66 Closed ctl fd 4
staprun:remove_module:247 removing module stap_e878009262b7836eb07f0b5a0bf070_14544
staprun:remove_module:259 Module stap_e878009262b7836eb07f0b5a0bf070_14544 removed.
Spawn waitpid result (0x0): 0
Pass 5: run completed in 0usr/20sys/326real ms.
Running rm -rf /tmp/stapNmEOL6
Spawn waitpid result (0x0): 0
Removed temporary directory "/tmp/stapNmEOL6"
[其他 ]
man stap
运行至某个步骤停止, 一般可用于生成可移动模块.
-p NUM Stop after pass NUM. The passes are numbered 1-5: parse, elaborate, translate, compile, run. See the
PROCESSING section for details.
提高输出详细级别
-v Increase verbosity for all passes. Produce a larger volume of informative (?) output each time option
repeated.
设置各步骤的输出详细级别
--vp ABCDE
Increase verbosity on a per-pass basis. For example, "--vp 002" adds 2 units of verbosity to pass 3
only. The combination "-v --vp 00004" adds 1 unit of verbosity for all passes, and 4 more for pass 5.
参考
1. https://sourceware.org/systemtap/man/stap.1.html
2. http://blog.163.com/digoal@126/blog/static/16387704020139142437763/
3. http://blog.163.com/digoal@126/blog/static/16387704020138109459201/
4. 宏以及条件预编译参考
http://blog.163.com/digoal@126/blog/static/16387704020139831157191/
http://blog.163.com/digoal@126/blog/static/16387704020139851437162/
5.
[root@db-172-16-3-150 e8]# cat /root/.systemtap/cache/e8/stap_e878009262b7836eb07f0b5a0bf0705e_970.c
#define STAP_MSG_RUNTIME_H_01 "myproc-unprivileged tapset function called without is_myproc checking for pid %d (euid %d)"
#define STAP_MSG_LOC2C_01 "kernel read fault at 0x%p (%s)"
#define STAP_MSG_LOC2C_02 "kernel write fault at 0x%p (%s)"
#define STAP_MSG_LOC2C_03 "divide by zero in DWARF operand (%s)"
#define STAP_VERSION(a, b) ( ((a) << 8) + (b) )
#ifndef STAP_COMPAT_VERSION
#define STAP_COMPAT_VERSION STAP_VERSION(1, 8)
#endif
#include "runtime_defines.h"
#define STP_PR_STAPUSR 0x2
#define STP_PR_STAPSYS 0x4
#define STP_PR_STAPDEV 0x8
#define STP_PRIVILEGE 0x8
int stp_required_privilege __attribute__ ((section (".stap_privilege"))) = STP_PRIVILEGE;
#ifndef MAXNESTING
#define MAXNESTING 1
#endif
#define STP_SKIP_BADVARS 0
#include "runtime.h"
#include "common_session_state.h"
struct context {
#include "common_probe_context.h"
union {
struct probe_3027_locals {
union {
};
} probe_3027;
} probe_locals;
union {
struct function_exit_locals {
/* no return value */
} function_exit;
} locals [MAXNESTING+1];
#if MAXNESTING < 0
#error "MAXNESTING must be positive"
#endif
#ifndef STP_LEGACY_PRINT
union {
} printf_locals;
#endif // STP_LEGACY_PRINT
};
static struct context *contexts[NR_CPUS] = { NULL };
#ifdef STAP_NEED_GETTIMEOFDAY
#include "time.c"
#endif
#ifndef STP_LEGACY_PRINT
#endif // STP_LEGACY_PRINT
#include "runtime_context.h"
#include "probe_lock.h"
static void function_exit (struct context * __restrict__ c);
static void function_exit (struct context* __restrict__ c) {
__label__ out;
struct function_exit_locals * __restrict__ l = & c->locals[c->nesting+1].function_exit;
(void) l;
#define CONTEXT c
#define THIS l
#define STAP_RETVALUE THIS->__retvalue
c->last_stmt = "identifier 'exit' at /usr/share/systemtap/tapset/logging.stp:49:10";
if (unlikely (c->nesting+1 >= MAXNESTING)) {
c->last_error = "MAXNESTING exceeded";
return;
} else {
c->nesting ++;
}
#define return goto out
{
/* unprivileged */
atomic_set (&session_state, STAP_SESSION_STOPPING);
_stp_exit ();
}
#undef return
out:
if (0) goto out;
c->nesting --;
#undef CONTEXT
#undef THIS
#undef STAP_RETVALUE
}
static void probe_3027 (struct context * __restrict__ c) {
__label__ out;
static const struct stp_probe_lock locks[] = {
};
struct probe_3027_locals * __restrict__ l = & c->probe_locals.probe_3027;
(void) l;
#if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \
! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS)
#error Internal Error: Probe kernel.function("sys_read@fs/read_write.c:389").call generated in --unprivileged mode
#endif
#if defined __ia64__
bspcache(c->unwaddr, c->kregs);
#endif
if (!stp_lock_probe(locks, ARRAY_SIZE(locks)))
return;
{
(void)
({
_stp_print ("hello i am digoal.\n");
});
(void)
({
function_exit (c);
if (unlikely(c->last_error)) goto out;
(void) 0;
});
}
c->actionremaining -= 2;
if (unlikely (c->actionremaining <= 0)) {
c->last_error = "MAXACTION exceeded";
c->last_stmt = "operator '{' at /usr/share/systemtap/tapset/syscalls2.stp:676:1";
goto out;
}
out:
stp_unlock_probe(locks, ARRAY_SIZE(locks));
_stp_print_flush();
}
static struct stap_probe {
void (* const ph) (struct context*);
#ifdef STP_ALIBI
atomic_t alibi;
#define STAP_PROBE_INIT_ALIBI() .alibi=ATOMIC_INIT(0),
#else
#define STAP_PROBE_INIT_ALIBI()
#endif
#ifdef STP_TIMING
Stat timing;
#endif
#if defined(STP_TIMING) || defined(STP_ALIBI)
const char location[14];
const char derivation[63];
#define STAP_PROBE_INIT_TIMING(L, D) .location=(L), .derivation=(D),
#else
#define STAP_PROBE_INIT_TIMING(L, D)
#endif
const char pp[57];
#ifdef STP_NEED_PROBE_NAME
const char pn[15];
#define STAP_PROBE_INIT_NAME(PN) .pn=(PN),
#else
#define STAP_PROBE_INIT_NAME(PN)
#endif
#define STAP_PROBE_INIT(PH, PP, PN, L, D) { .ph=(PH), .pp=(PP), STAP_PROBE_INIT_NAME(PN) STAP_PROBE_INIT_ALIBI() STAP_PROBE_INIT_TIMING(L, D) }
} stap_probes[] = {
STAP_PROBE_INIT(&probe_3027, "kernel.function(\"sys_read@fs/read_write.c:389\").call", "syscall.read", "<input>:1:7", " from: kernel.function(\"sys_read\").call from: syscall.read"),
};
/* ---- dwarf probes ---- */
#if ! defined(CONFIG_KPROBES)
#error "Need CONFIG_KPROBES!"
#endif
#ifndef KRETACTIVE
#define KRETACTIVE (max(15,6*(int)num_possible_cpus()))
#endif
#include "kprobes-common.h"
static int enter_kprobe_probe (struct kprobe *inst, struct pt_regs *regs);
static int enter_kretprobe_probe (struct kretprobe_instance *inst, struct pt_regs *regs);
#if defined(STAPCONF_UNREGISTER_KPROBES)
static void * stap_unreg_kprobes[1];
#endif
static struct stap_dwarf_kprobe stap_dwarf_kprobes[1];
static struct stap_dwarf_probe {
const unsigned return_p:1;
const unsigned maxactive_p:1;
const unsigned optional_p:1;
unsigned registered_p:1;
const unsigned short maxactive_val;
const unsigned short saved_longs;
const unsigned short saved_strings;
const char module[7];
const char section[7];
const unsigned long address;
struct stap_probe * const probe;
struct stap_probe * const entry_probe;
} stap_dwarf_probes[] = {
{ .address=(unsigned long)0x181618ULL, .module="kernel", .section="_stext", .probe=(&stap_probes[0]), },
};
static int enter_kprobe_probe (struct kprobe *inst, struct pt_regs *regs) {
int kprobe_idx = ((uintptr_t)inst-(uintptr_t)stap_dwarf_kprobes)/sizeof(struct stap_dwarf_kprobe);
struct stap_dwarf_probe *sdp = &stap_dwarf_probes[((kprobe_idx >= 0 && kprobe_idx < 1)?kprobe_idx:0)];
#ifdef STP_ALIBI
atomic_inc(&(sdp->probe->alibi));
#else
struct context* __restrict__ c;
#if !INTERRUPTIBLE
unsigned long flags;
#endif
#if defined(STP_TIMING) || defined(STP_OVERLOAD)
cycles_t cycles_atstart = get_cycles ();
#endif
#ifdef STP_TIMING
Stat stat = sdp->probe->timing;
#endif
#if INTERRUPTIBLE
preempt_disable ();
#else
local_irq_save (flags);
#endif
if (unlikely ((((unsigned long) (& c)) & (THREAD_SIZE-1))
< (MINSTACKSPACE + sizeof (struct thread_info)))) {
atomic_inc (& skipped_count);
#ifdef STP_TIMING
atomic_inc (& skipped_count_lowstack);
#endif
goto probe_epilogue;
}
if (atomic_read (&session_state) != STAP_SESSION_RUNNING)
goto probe_epilogue;
c = contexts[smp_processor_id()];
if (atomic_inc_return (& c->busy) != 1) {
#if !INTERRUPTIBLE
atomic_inc (& skipped_count);
#endif
#ifdef STP_TIMING
atomic_inc (& skipped_count_reentrant);
#ifdef DEBUG_REENTRANCY
_stp_warn ("Skipped %s due to %s residency on cpu %u\n", sdp->probe->pp, c->probe_point ?: "?", smp_processor_id());
#endif
#endif
atomic_dec (& c->busy);
goto probe_epilogue;
}
c->last_stmt = 0;
c->last_error = 0;
c->nesting = -1;
c->uregs = 0;
c->kregs = 0;
#if defined __ia64__
c->unwaddr = 0;
#endif
c->probe_point = sdp->probe->pp;
#ifdef STP_NEED_PROBE_NAME
c->probe_name = sdp->probe->pn;
#endif
c->probe_type = _STP_PROBE_HANDLER_KPROBE;
memset(&c->ips, 0, sizeof(c->ips));
c->probe_flags = 0;
#ifdef STAP_NEED_REGPARM
c->regparm = 0;
#endif
#if INTERRUPTIBLE
c->actionremaining = MAXACTION_INTERRUPTIBLE;
#else
c->actionremaining = MAXACTION;
#endif
c->kregs = regs;
{
unsigned long kprobes_ip = REG_IP(c->kregs);
SET_REG_IP(regs, (unsigned long) inst->addr);
(*sdp->probe->ph) (c);
SET_REG_IP(regs, kprobes_ip);
}
#if defined(STP_TIMING) || defined(STP_OVERLOAD)
{
cycles_t cycles_atend = get_cycles ();
int32_t cycles_elapsed = ((int32_t)cycles_atend > (int32_t)cycles_atstart)
? ((int32_t)cycles_atend - (int32_t)cycles_atstart)
: (~(int32_t)0) - (int32_t)cycles_atstart + (int32_t)cycles_atend + 1;
#ifdef STP_TIMING
if (likely (stat)) _stp_stat_add(stat, cycles_elapsed);
#endif
#ifdef STP_OVERLOAD
{
cycles_t interval = (cycles_atend > c->cycles_base)
? (cycles_atend - c->cycles_base)
: (STP_OVERLOAD_INTERVAL + 1);
c->cycles_sum += cycles_elapsed;
if (interval > STP_OVERLOAD_INTERVAL) {
if (c->cycles_sum > STP_OVERLOAD_THRESHOLD) {
_stp_error ("probe overhead exceeded threshold");
atomic_set (&session_state, STAP_SESSION_ERROR);
atomic_inc (&error_count);
}
c->cycles_base = cycles_atend;
c->cycles_sum = 0;
}
}
#endif
}
#endif
c->probe_point = 0;
#ifdef STP_NEED_PROBE_NAME
c->probe_name = 0;
#endif
c->probe_type = 0;
if (unlikely (c->last_error && c->last_error[0])) {
if (c->last_stmt != NULL)
_stp_softerror ("%s near %s", c->last_error, c->last_stmt);
else
_stp_softerror ("%s", c->last_error);
atomic_inc (& error_count);
if (atomic_read (& error_count) > MAXERRORS) {
atomic_set (& session_state, STAP_SESSION_ERROR);
_stp_exit ();
}
}
atomic_dec (&c->busy);
probe_epilogue:
if (unlikely (atomic_read (& skipped_count) > MAXSKIPPED)) {
if (unlikely (pseudo_atomic_cmpxchg(& session_state, STAP_SESSION_RUNNING, STAP_SESSION_ERROR) == STAP_SESSION_RUNNING))
_stp_error ("Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.");
}
#if INTERRUPTIBLE
preempt_enable_no_resched ();
#else
local_irq_restore (flags);
#endif
#endif // STP_ALIBI
return 0;
}
static int enter_kretprobe_common (struct kretprobe_instance *inst, struct pt_regs *regs, int entry) {
struct kretprobe *krp = inst->rp;
int kprobe_idx = ((uintptr_t)krp-(uintptr_t)stap_dwarf_kprobes)/sizeof(struct stap_dwarf_kprobe);
struct stap_dwarf_probe *sdp = &stap_dwarf_probes[((kprobe_idx >= 0 && kprobe_idx < 1)?kprobe_idx:0)];
struct stap_probe *sp = entry ? sdp->entry_probe : sdp->probe;
if (sp) {
#ifdef STP_ALIBI
atomic_inc(&(sp->alibi));
#else
struct context* __restrict__ c;
#if !INTERRUPTIBLE
unsigned long flags;
#endif
#if defined(STP_TIMING) || defined(STP_OVERLOAD)
cycles_t cycles_atstart = get_cycles ();
#endif
#ifdef STP_TIMING
Stat stat = sp->timing;
#endif
#if INTERRUPTIBLE
preempt_disable ();
#else
local_irq_save (flags);
#endif
if (unlikely ((((unsigned long) (& c)) & (THREAD_SIZE-1))
< (MINSTACKSPACE + sizeof (struct thread_info)))) {
atomic_inc (& skipped_count);
#ifdef STP_TIMING
atomic_inc (& skipped_count_lowstack);
#endif
goto probe_epilogue;
}
if (atomic_read (&session_state) != STAP_SESSION_RUNNING)
goto probe_epilogue;
c = contexts[smp_processor_id()];
if (atomic_inc_return (& c->busy) != 1) {
#if !INTERRUPTIBLE
atomic_inc (& skipped_count);
#endif
#ifdef STP_TIMING
atomic_inc (& skipped_count_reentrant);
#ifdef DEBUG_REENTRANCY
_stp_warn ("Skipped %s due to %s residency on cpu %u\n", sp->pp, c->probe_point ?: "?", smp_processor_id());
#endif
#endif
atomic_dec (& c->busy);
goto probe_epilogue;
}
c->last_stmt = 0;
c->last_error = 0;
c->nesting = -1;
c->uregs = 0;
c->kregs = 0;
#if defined __ia64__
c->unwaddr = 0;
#endif
c->probe_point = sp->pp;
#ifdef STP_NEED_PROBE_NAME
c->probe_name = sp->pn;
#endif
c->probe_type = _STP_PROBE_HANDLER_KRETPROBE;
memset(&c->ips, 0, sizeof(c->ips));
c->probe_flags = 0;
#ifdef STAP_NEED_REGPARM
c->regparm = 0;
#endif
#if INTERRUPTIBLE
c->actionremaining = MAXACTION_INTERRUPTIBLE;
#else
c->actionremaining = MAXACTION;
#endif
c->kregs = regs;
c->ips.krp.pi = inst;
c->ips.krp.pi_longs = sdp->saved_longs;
{
unsigned long kprobes_ip = REG_IP(c->kregs);
if (entry)
SET_REG_IP(regs, (unsigned long) inst->rp->kp.addr);
else
SET_REG_IP(regs, (unsigned long)inst->ret_addr);
(sp->ph) (c);
SET_REG_IP(regs, kprobes_ip);
}
#if defined(STP_TIMING) || defined(STP_OVERLOAD)
{
cycles_t cycles_atend = get_cycles ();
int32_t cycles_elapsed = ((int32_t)cycles_atend > (int32_t)cycles_atstart)
? ((int32_t)cycles_atend - (int32_t)cycles_atstart)
: (~(int32_t)0) - (int32_t)cycles_atstart + (int32_t)cycles_atend + 1;
#ifdef STP_TIMING
if (likely (stat)) _stp_stat_add(stat, cycles_elapsed);
#endif
#ifdef STP_OVERLOAD
{
cycles_t interval = (cycles_atend > c->cycles_base)
? (cycles_atend - c->cycles_base)
: (STP_OVERLOAD_INTERVAL + 1);
c->cycles_sum += cycles_elapsed;
if (interval > STP_OVERLOAD_INTERVAL) {
if (c->cycles_sum > STP_OVERLOAD_THRESHOLD) {
_stp_error ("probe overhead exceeded threshold");
atomic_set (&session_state, STAP_SESSION_ERROR);
atomic_inc (&error_count);
}
c->cycles_base = cycles_atend;
c->cycles_sum = 0;
}
}
#endif
}
#endif
c->probe_point = 0;
#ifdef STP_NEED_PROBE_NAME
c->probe_name = 0;
#endif
c->probe_type = 0;
if (unlikely (c->last_error && c->last_error[0])) {
if (c->last_stmt != NULL)
_stp_softerror ("%s near %s", c->last_error, c->last_stmt);
else
_stp_softerror ("%s", c->last_error);
atomic_inc (& error_count);
if (atomic_read (& error_count) > MAXERRORS) {
atomic_set (& session_state, STAP_SESSION_ERROR);
_stp_exit ();
}
}
atomic_dec (&c->busy);
probe_epilogue:
if (unlikely (atomic_read (& skipped_count) > MAXSKIPPED)) {
if (unlikely (pseudo_atomic_cmpxchg(& session_state, STAP_SESSION_RUNNING, STAP_SESSION_ERROR) == STAP_SESSION_RUNNING))
_stp_error ("Skipped too many probes, check MAXSKIPPED or try again with stap -t for more details.");
}
#if INTERRUPTIBLE
preempt_enable_no_resched ();
#else
local_irq_restore (flags);
#endif
#endif // STP_ALIBI
}
return 0;
}
static int enter_kretprobe_probe (struct kretprobe_instance *inst, struct pt_regs *regs) {
return enter_kretprobe_common(inst, regs, 0);
}
static int enter_kretprobe_entry_probe (struct kretprobe_instance *inst, struct pt_regs *regs) {
return enter_kretprobe_common(inst, regs, 1);
}
static int systemtap_module_init (void) {
int rc = 0;
int cpu;
int i=0, j=0;
const char *probe_point = "";
{
const char* release = UTS_RELEASE;
#ifdef STAPCONF_GENERATED_COMPILE
const char* version = UTS_VERSION;
#endif
if (strcmp (release, "2.6.32-358.el6.x86_64")) {
_stp_error ("module release mismatch (%s vs %s)", release, "2.6.32-358.el6.x86_64");
rc = -EINVAL;
}
#ifdef STAPCONF_GENERATED_COMPILE
if (strcmp (utsname()->version, version)) {
_stp_error ("module version mismatch (%s vs %s), release %s", version, utsname()->version, release);
rc = -EINVAL;
}
#endif
if (_stp_module_check()) rc = -EINVAL;
if (_stp_privilege_credentials == 0) {
if (STP_PRIVILEGE_CONTAINS(STP_PRIVILEGE, STP_PR_STAPDEV) ||
STP_PRIVILEGE_CONTAINS(STP_PRIVILEGE, STP_PR_STAPUSR)) {
_stp_privilege_credentials = STP_PRIVILEGE;
#ifdef DEBUG_PRIVILEGE
_dbug("User's privilege credentials default to %s\n",
privilege_to_text(_stp_privilege_credentials));
#endif
}
else {
_stp_error ("Unable to verify that you have the required privilege credentials to run this module (%s required). You must use staprun version 1.7 or higher.",
privilege_to_text(STP_PRIVILEGE));
rc = -EINVAL;
}
}
else {
#ifdef DEBUG_PRIVILEGE
_dbug("User's privilege credentials provided as %s\n",
privilege_to_text(_stp_privilege_credentials));
#endif
if (! STP_PRIVILEGE_CONTAINS(_stp_privilege_credentials, STP_PRIVILEGE)) {
_stp_error ("Your privilege credentials (%s) are insufficient to run this module (%s required).",
privilege_to_text(_stp_privilege_credentials), privilege_to_text(STP_PRIVILEGE));
rc = -EINVAL;
}
}
}
if (rc) goto out;
#ifdef STAP_NEED_GETTIMEOFDAY
rc = _stp_init_time();
if (rc) {
_stp_error ("couldn't initialize gettimeofday");
goto out;
}
#endif
(void) probe_point;
(void) i;
(void) j;
atomic_set (&session_state, STAP_SESSION_STARTING);
for_each_possible_cpu(cpu) {
contexts[cpu] = _stp_kzalloc_gfp(sizeof(struct context), STP_ALLOC_SLEEP_FLAGS);
if (contexts[cpu] == NULL) {
_stp_error ("context (size %lu) allocation failed", (unsigned long) sizeof (struct context));
rc = -ENOMEM;
goto out;
}
}
#ifdef STP_TIMING
for (i = 0; i < ARRAY_SIZE(stap_probes); ++i)
stap_probes[i].timing = _stp_stat_init (HIST_NONE);
#endif
_stp_print_kernel_info("1.8/0.152", (num_online_cpus() * sizeof(struct context)), 1);
for (i=0; i<1; i++) {
struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];
struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];
unsigned long relocated_addr = _stp_kmodule_relocate (sdp->module, sdp->section, sdp->address);
if (relocated_addr == 0) continue;
probe_point = sdp->probe->pp;
if (sdp->return_p) {
kp->u.krp.kp.addr = (void *) relocated_addr;
if (sdp->maxactive_p) {
kp->u.krp.maxactive = sdp->maxactive_val;
} else {
kp->u.krp.maxactive = KRETACTIVE;
}
kp->u.krp.handler = &enter_kretprobe_probe;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
if (sdp->entry_probe) {
kp->u.krp.entry_handler = &enter_kretprobe_entry_probe;
kp->u.krp.data_size = sdp->saved_longs * sizeof(int64_t) +
sdp->saved_strings * MAXSTRINGLEN;
}
#endif
#ifdef __ia64__
kp->dummy.addr = kp->u.krp.kp.addr;
kp->dummy.pre_handler = NULL;
rc = register_kprobe (& kp->dummy);
if (rc == 0) {
rc = register_kretprobe (& kp->u.krp);
if (rc != 0)
unregister_kprobe (& kp->dummy);
}
#else
rc = register_kretprobe (& kp->u.krp);
#endif
} else {
kp->u.kp.addr = (void *) relocated_addr;
kp->u.kp.pre_handler = &enter_kprobe_probe;
#ifdef __ia64__
kp->dummy.addr = kp->u.kp.addr;
kp->dummy.pre_handler = NULL;
rc = register_kprobe (& kp->dummy);
if (rc == 0) {
rc = register_kprobe (& kp->u.kp);
if (rc != 0)
unregister_kprobe (& kp->dummy);
}
#else
rc = register_kprobe (& kp->u.kp);
#endif
}
if (rc) {
sdp->registered_p = 0;
if (!sdp->optional_p)
_stp_warn ("probe %s (address 0x%lx) registration error (rc %d)", probe_point, (unsigned long) relocated_addr, rc);
rc = 0;
}
else sdp->registered_p = 1;
}
if (rc) {
if (probe_point)
_stp_error ("probe %s registration error (rc %d)", probe_point, rc);
atomic_set (&session_state, STAP_SESSION_ERROR);
goto out;
}
if (atomic_read (&session_state) == STAP_SESSION_STARTING)
atomic_set (&session_state, STAP_SESSION_RUNNING);
return 0;
out:
atomic_set (&session_state, STAP_SESSION_STOPPED);
#ifdef STAPCONF_SYNCHRONIZE_SCHED
synchronize_sched();
#endif
#ifdef STAP_NEED_GETTIMEOFDAY
_stp_kill_time();
#endif
for_each_possible_cpu(cpu) {
if (contexts[cpu] != NULL) {
_stp_kfree(contexts[cpu]);
contexts[cpu] = NULL;
}
}
return rc;
}
static void systemtap_module_refresh (void) {
int i=0, j=0;
(void) i;
(void) j;
for (i=0; i<1; i++) {
struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];
struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];
unsigned long relocated_addr = _stp_kmodule_relocate (sdp->module, sdp->section, sdp->address);
int rc;
if (sdp->registered_p == 0 && relocated_addr != 0) {
if (sdp->return_p) {
kp->u.krp.kp.addr = (void *) relocated_addr;
if (sdp->maxactive_p) {
kp->u.krp.maxactive = sdp->maxactive_val;
} else {
kp->u.krp.maxactive = KRETACTIVE;
}
kp->u.krp.handler = &enter_kretprobe_probe;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
if (sdp->entry_probe) {
kp->u.krp.entry_handler = &enter_kretprobe_entry_probe;
kp->u.krp.data_size = sdp->saved_longs * sizeof(int64_t) +
sdp->saved_strings * MAXSTRINGLEN;
}
#endif
#ifdef __ia64__
kp->dummy.addr = kp->u.krp.kp.addr;
kp->dummy.pre_handler = NULL;
rc = register_kprobe (& kp->dummy);
if (rc == 0) {
rc = register_kretprobe (& kp->u.krp);
if (rc != 0)
unregister_kprobe (& kp->dummy);
}
#else
rc = register_kretprobe (& kp->u.krp);
#endif
} else {
kp->u.kp.addr = (void *) relocated_addr;
kp->u.kp.pre_handler = &enter_kprobe_probe;
#ifdef __ia64__
kp->dummy.addr = kp->u.kp.addr;
kp->dummy.pre_handler = NULL;
rc = register_kprobe (& kp->dummy);
if (rc == 0) {
rc = register_kprobe (& kp->u.kp);
if (rc != 0)
unregister_kprobe (& kp->dummy);
}
#else
rc = register_kprobe (& kp->u.kp);
#endif
}
if (rc == 0) sdp->registered_p = 1;
} else if (sdp->registered_p == 1 && relocated_addr == 0) {
if (sdp->return_p) {
unregister_kretprobe (&kp->u.krp);
atomic_add (kp->u.krp.nmissed, & skipped_count);
#ifdef STP_TIMING
if (kp->u.krp.nmissed)
_stp_warn ("Skipped due to missed kretprobe/1 on '%s': %d\n", sdp->probe->pp, kp->u.krp.nmissed);
#endif
atomic_add (kp->u.krp.kp.nmissed, & skipped_count);
#ifdef STP_TIMING
if (kp->u.krp.kp.nmissed)
_stp_warn ("Skipped due to missed kretprobe/2 on '%s': %lu\n", sdp->probe->pp, kp->u.krp.kp.nmissed);
#endif
} else {
unregister_kprobe (&kp->u.kp);
atomic_add (kp->u.kp.nmissed, & skipped_count);
#ifdef STP_TIMING
if (kp->u.kp.nmissed)
_stp_warn ("Skipped due to missed kprobe on '%s': %lu\n", sdp->probe->pp, kp->u.kp.nmissed);
#endif
}
#if defined(__ia64__)
unregister_kprobe (&kp->dummy);
#endif
sdp->registered_p = 0;
}
}
}
static void systemtap_module_exit (void) {
int holdon;
int i=0, j=0;
int cpu;
unsigned long hold_start;
int hold_index;
(void) i;
(void) j;
if (atomic_read (&session_state) == STAP_SESSION_STARTING)
return;
if (atomic_read (&session_state) == STAP_SESSION_RUNNING)
atomic_set (&session_state, STAP_SESSION_STOPPING);
#if defined(STAPCONF_UNREGISTER_KPROBES)
j = 0;
for (i=0; i<1; i++) {
struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];
struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];
if (! sdp->registered_p) continue;
if (!sdp->return_p)
stap_unreg_kprobes[j++] = &kp->u.kp;
}
unregister_kprobes((struct kprobe **)stap_unreg_kprobes, j);
j = 0;
for (i=0; i<1; i++) {
struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];
struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];
if (! sdp->registered_p) continue;
if (sdp->return_p)
stap_unreg_kprobes[j++] = &kp->u.krp;
}
unregister_kretprobes((struct kretprobe **)stap_unreg_kprobes, j);
#ifdef __ia64__
j = 0;
for (i=0; i<1; i++) {
struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];
struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];
if (! sdp->registered_p) continue;
stap_unreg_kprobes[j++] = &kp->dummy;
}
unregister_kprobes((struct kprobe **)stap_unreg_kprobes, j);
#endif
#endif
for (i=0; i<1; i++) {
struct stap_dwarf_probe *sdp = & stap_dwarf_probes[i];
struct stap_dwarf_kprobe *kp = & stap_dwarf_kprobes[i];
if (! sdp->registered_p) continue;
if (sdp->return_p) {
#if !defined(STAPCONF_UNREGISTER_KPROBES)
unregister_kretprobe (&kp->u.krp);
#endif
atomic_add (kp->u.krp.nmissed, & skipped_count);
#ifdef STP_TIMING
if (kp->u.krp.nmissed)
_stp_warn ("Skipped due to missed kretprobe/1 on '%s': %d\n", sdp->probe->pp, kp->u.krp.nmissed);
#endif
atomic_add (kp->u.krp.kp.nmissed, & skipped_count);
#ifdef STP_TIMING
if (kp->u.krp.kp.nmissed)
_stp_warn ("Skipped due to missed kretprobe/2 on '%s': %lu\n", sdp->probe->pp, kp->u.krp.kp.nmissed);
#endif
} else {
#if !defined(STAPCONF_UNREGISTER_KPROBES)
unregister_kprobe (&kp->u.kp);
#endif
atomic_add (kp->u.kp.nmissed, & skipped_count);
#ifdef STP_TIMING
if (kp->u.kp.nmissed)
_stp_warn ("Skipped due to missed kprobe on '%s': %lu\n", sdp->probe->pp, kp->u.kp.nmissed);
#endif
}
#if !defined(STAPCONF_UNREGISTER_KPROBES) && defined(__ia64__)
unregister_kprobe (&kp->dummy);
#endif
sdp->registered_p = 0;
}
#ifdef STAPCONF_SYNCHRONIZE_SCHED
synchronize_sched();
#endif
hold_start = jiffies;
hold_index = -1;
do {
int i;
holdon = 0;
for_each_possible_cpu(i)
if (contexts[i] != NULL && atomic_read (& contexts[i]->busy)) {
holdon = 1;
if (time_after(jiffies, hold_start + HZ) && (i > hold_index)) {
hold_index = i;
printk(KERN_ERR "%s context[%d] stuck: %s\n", THIS_MODULE->name, i, contexts[i]->probe_point);
}
}
#ifdef STAP_OVERRIDE_STUCK_CONTEXT
if (time_after(jiffies, hold_start + HZ*10)) {
printk(KERN_ERR "%s overriding stuck context to allow module shutdown.", THIS_MODULE->name);
holdon = 0;
}
#else
msleep (250);
#endif
yield ();
} while (holdon);
atomic_set (&session_state, STAP_SESSION_STOPPED);
#ifdef STAPCONF_SYNCHRONIZE_SCHED
synchronize_sched();
#endif
for_each_possible_cpu(cpu) {
if (contexts[cpu] != NULL) {
_stp_kfree(contexts[cpu]);
contexts[cpu] = NULL;
}
}
#ifdef STAP_NEED_GETTIMEOFDAY
_stp_kill_time();
#endif
preempt_disable();
#if defined(STP_TIMING) || defined(STP_ALIBI)
_stp_printf("----- probe hit report: \n");
for (i = 0; i < ARRAY_SIZE(stap_probes); ++i) {
struct stap_probe *const p = &stap_probes[i];
#ifdef STP_ALIBI
int alibi = atomic_read(&(p->alibi));
if (alibi)
_stp_printf ("%s, (%s), hits: %d,%s\n",
p->pp, p->location, alibi, p->derivation);
#endif
#ifdef STP_TIMING
if (likely (p->timing)) {
struct stat_data *stats = _stp_stat_get (p->timing, 0);
if (stats->count) {
int64_t avg = _stp_div64 (NULL, stats->sum, stats->count);
_stp_printf ("%s, (%s), hits: %lld, cycles: %lldmin/%lldavg/%lldmax,%s\n",
p->pp, p->location, (long long) stats->count,
(long long) stats->min, (long long) avg, (long long) stats->max,
p->derivation);
}
_stp_stat_del (p->timing);
}
#endif
}
_stp_print_flush();
#endif
if (atomic_read (& skipped_count) || atomic_read (& error_count) || atomic_read (& skipped_count_reentrant)) {
_stp_warn ("Number of errors: %d, skipped probes: %d\n", (int) atomic_read (& error_count), (int) atomic_read (& skipped_count));
#ifdef STP_TIMING
{
int ctr;
ctr = atomic_read (& skipped_count_lowstack);
if (ctr) _stp_warn ("Skipped due to low stack: %d\n", ctr);
ctr = atomic_read (& skipped_count_reentrant);
if (ctr) _stp_warn ("Skipped due to reentrancy: %d\n", ctr);
ctr = atomic_read (& skipped_count_uprobe_reg);
if (ctr) _stp_warn ("Skipped due to uprobe register failure: %d\n", ctr);
ctr = atomic_read (& skipped_count_uprobe_unreg);
if (ctr) _stp_warn ("Skipped due to uprobe unregister failure: %d\n", ctr);
}
#endif
_stp_print_flush();
}
preempt_enable_no_resched();
}
#include "stap-symbols.h"
MODULE_DESCRIPTION("systemtap-generated probe");
MODULE_LICENSE("GPL");