Systemtap : stap PROCESSING 5 steps introduce

21 minute read

背景

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");  

Flag Counter

digoal’s 大量PostgreSQL文章入口