/usr/share/systemtap/runtime/linux
NameSizeModeActions
uprobes/-0755rm
uprobes2/-0755rm
access_process_vm.h43110644editdlrm
addr-map.c97490644editdlrm
alloc.c159000644editdlrm
arith.c167990644editdlrm
autoconf-514-panic.c680644editdlrm
autoconf-access_ok_2args.c900644editdlrm
autoconf-alloc-percpu-align.c1180644editdlrm
autoconf-asm-syscall.c510644editdlrm
autoconf-atomic_fetch_add_unless.c940644editdlrm
autoconf-bio-bi_opf.c8240644editdlrm
autoconf-blk-types.c3590644editdlrm
autoconf-compat-utimbuf.c530644editdlrm
autoconf-compat_sigaction.c4480644editdlrm
autoconf-constant-tsc.c630644editdlrm
autoconf-cpu-clock.c12770644editdlrm
autoconf-dpath-path.c1210644editdlrm
autoconf-files_lookup_fd_raw.c1360644editdlrm
autoconf-from_kuid_munged.c1910644editdlrm
autoconf-fs_supers-hlist.c3540644editdlrm
autoconf-generated-compile.c560644editdlrm
autoconf-genhd.c2010644editdlrm
autoconf-get-kretprobe.c1070644editdlrm
autoconf-get_user_pages-flags.c15490644editdlrm
autoconf-get_user_pages-notask_struct.c13010644editdlrm
autoconf-get_user_pages_remote-flags.c15500644editdlrm
autoconf-get_user_pages_remote-flags_locked.c13310644editdlrm
autoconf-get_user_pages_remote-notask_struct.c14380644editdlrm
autoconf-grsecurity.c2190644editdlrm
autoconf-hlist-4args.c2960644editdlrm
autoconf-hlist_add_tail_rcu.c1120644editdlrm
autoconf-hrtimer-getset-expires.c1260644editdlrm
autoconf-hrtimer-rel.c870644editdlrm
autoconf-hw_breakpoint_context.c3150644editdlrm
autoconf-inode-private.c1730644editdlrm
autoconf-inode-rwsem.c1720644editdlrm
autoconf-inode-uretprobes.c2640644editdlrm
autoconf-kernel_read-new-args.c10300644editdlrm
autoconf-kprobe-symbol-name.c900644editdlrm
autoconf-ktime-get-real.c980644editdlrm
autoconf-linux-sched_headers.c16780644editdlrm
autoconf-local-clock.c12820644editdlrm
autoconf-lockdown-debugfs.c1020644editdlrm
autoconf-lockdown-kernel.c900644editdlrm
autoconf-mm-context-vdso-base.c1170644editdlrm
autoconf-mm-context-vdso.c1140644editdlrm
autoconf-mm-shmempages.c720644editdlrm
autoconf-mmap_lock.c1750644editdlrm
autoconf-module-sect-attrs.c1580644editdlrm
autoconf-module_layout.c520644editdlrm
autoconf-mod_kallsyms.c510644editdlrm
autoconf-nameidata.c960644editdlrm
autoconf-netfilter-4_1.c7690644editdlrm
autoconf-netfilter-4_4.c14600644editdlrm
autoconf-netfilter-313b.c6020644editdlrm
autoconf-netfilter.c4220644editdlrm
autoconf-old-inode-uprobes.c3570644editdlrm
autoconf-oneachcpu-retry.c9570644editdlrm
autoconf-pagefault_disable.c1370644editdlrm
autoconf-pde_data.c2260644editdlrm
autoconf-perf-structpid.c4440644editdlrm
autoconf-procfs-owner.c1580644editdlrm
autoconf-proc_ops.c5660644editdlrm
autoconf-rcu_is_watching.c3850644editdlrm
autoconf-real-parent.c4270644editdlrm
autoconf-regset.c2390644editdlrm
autoconf-relay-umode_t.c7300644editdlrm
autoconf-relay_buf-per_cpu_ptr.c9200644editdlrm
autoconf-ring_buffer-flags.c1120644editdlrm
autoconf-ring_buffer_lost_events.c2960644editdlrm
autoconf-ring_buffer_read_prepare.c1810644editdlrm
autoconf-save-stack-trace-no-bp.c4980644editdlrm
autoconf-save-stack-trace.c5010644editdlrm
autoconf-set_fs.c2210644editdlrm
autoconf-smpcall-4args.c1660644editdlrm
autoconf-smpcall-5args.c1690644editdlrm
autoconf-stack-trace-save-regs.c1760644editdlrm
autoconf-stacktrace_ops-int-address.c4090644editdlrm
autoconf-stacktrace_ops-warning.c1880644editdlrm
autoconf-syscall_get_args_3args.c2390644editdlrm
autoconf-task-state.c5500644editdlrm
autoconf-task-uid.c1520644editdlrm
autoconf-task_work-struct.c2190644editdlrm
autoconf-time32-old.c520644editdlrm
autoconf-time32.c530644editdlrm
autoconf-timerfd.c2320644editdlrm
autoconf-trace-printk.c1510644editdlrm
autoconf-tracepoint-has-data.c4930644editdlrm
autoconf-tracepoint-strings.c2330644editdlrm
autoconf-uaccess.c280644editdlrm
autoconf-uapi-mount.c520644editdlrm
autoconf-udelay_simple.c900644editdlrm
autoconf-uidgid.c500644editdlrm
autoconf-unwind-stack-trace.c3260644editdlrm
autoconf-uprobe-get-pc.c3740644editdlrm
autoconf-utrace-regset.c2730644editdlrm
autoconf-utrace-via-tracepoints.c17120644editdlrm
autoconf-vm-area-pte.c1410644editdlrm
autoconf-walk-stack.c2170644editdlrm
autoconf-x86-fs.c900644editdlrm
autoconf-x86-gs.c900644editdlrm
autoconf-x86-uniregs.c1400644editdlrm
autoconf-x86-xfs.c910644editdlrm
common_session_state.h32490644editdlrm
compat_net.h8580644editdlrm
compat_structs.h44090644editdlrm
compat_unistd.h683840644editdlrm
copy.c27170644editdlrm
debug.h29780644editdlrm
io.c52910644editdlrm
itrace.c148740644editdlrm
kprobes.c251260644editdlrm
loc2c-runtime.h298740644editdlrm
map_list.h12200644editdlrm
map_runtime.h52660644editdlrm
namespaces.h71280644editdlrm
netfilter.c14100644editdlrm
perf.c75960644editdlrm
perf.h12720644editdlrm
perf_event_counter_context.c3360644editdlrm
perf_probe_handler_nmi.c2780644editdlrm
perf_read.h9590644editdlrm
print.c114020644editdlrm
probe_lock.h18070644editdlrm
regs-ia64.c37410644editdlrm
regs.c134900644editdlrm
runtime.h125910644editdlrm
runtime_context.h60890644editdlrm
runtime_defines.h10410644editdlrm
stap_mmap_lock.h3430644editdlrm
stat_runtime.h17740644editdlrm
stp_tls.h11810644editdlrm
stp_tracepoint.c114810644editdlrm
stp_tracepoint.h22700644editdlrm
syscalls-common.h9760644editdlrm
task_finder.c538600644editdlrm
task_finder2.c576400644editdlrm
task_finder_map.c51940644editdlrm
task_finder_stubs.c24420644editdlrm
task_work_compatibility.h12830644editdlrm
timer.c22000644editdlrm
timer.h13830644editdlrm
timer_compatibility.h23170644editdlrm
uprobes-common.c155730644editdlrm
uprobes-common.h16530644editdlrm
uprobes-inc.h4840644editdlrm
uprobes-inode.c340860644editdlrm
Edit: /usr/share/systemtap/runtime/linux/itrace.c (14874B)
/* * user space instruction tracing * Copyright (C) 2005, 2006, 2007, 2008, 2009 IBM Corp. * Copyright (C) 2009 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General * Public License (GPL); either version 2, or (at your option) any * later version. */ #include #include #include #include #include #include #include #include #include #include "ptrace_compatibility.h" /* PR10171: To avoid ia64 lockups, disable itrace on ia64. */ #if defined(__ia64__) #error "Unsupported itrace architecture" #endif /* PR9974: Adapt to struct renaming. */ #ifdef UTRACE_API_VERSION #define utrace_attached_engine utrace_engine #endif #include #include "uprobes/uprobes.h" #include "utrace_compatibility.h" #ifndef put_task_struct #define put_task_struct(t) \ BUG_ON(atomic_dec_and_test(&tsk->usage)) #endif #ifdef CONFIG_PPC struct bpt_info { unsigned long addr; unsigned int instr; }; struct atomic_ss_info { int step_over_atomic; struct bpt_info end_bpt; struct bpt_info br_bpt; }; static int handle_ppc_atomic_seq(struct task_struct *tsk, struct pt_regs *regs, struct atomic_ss_info *ss_info); static void remove_atomic_ss_breakpoint (struct task_struct *tsk, struct bpt_info *bpt); #endif struct itrace_info { u32 step_flag; struct stap_itrace_probe *itrace_probe; #ifdef CONFIG_PPC struct atomic_ss_info ppc_atomic_ss; #endif struct task_struct *tsk; struct utrace_attached_engine *engine; struct list_head link; }; static u32 debug = 0 /* 1 */; static LIST_HEAD(usr_itrace_info); static spinlock_t itrace_lock; static struct itrace_info *create_itrace_info( struct task_struct *tsk, u32 step_flag, struct stap_itrace_probe *itrace_probe); /* Note: __access_process_vm moved to access_process_vm.h */ #ifdef UTRACE_ORIG_VERSION static u32 usr_itrace_report_quiesce(struct utrace_attached_engine *engine, struct task_struct *tsk) #else #if defined(UTRACE_API_VERSION) && (UTRACE_API_VERSION >= 20091216) static u32 usr_itrace_report_quiesce(u32 action, struct utrace_attached_engine *engine, unsigned long event) #else static u32 usr_itrace_report_quiesce(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *tsk, unsigned long event) #endif #endif { int status; struct itrace_info *ui; rcu_read_lock(); ui = rcu_dereference(engine->data); rcu_read_unlock(); WARN_ON(!ui); #ifdef UTRACE_ORIG_VERSION return (ui->step_flag | UTRACE_ACTION_NEWSTATE); #else return (event == 0 ? ui->step_flag : UTRACE_RESUME); #endif } #ifdef UTRACE_ORIG_VERSION static u32 usr_itrace_report_signal( struct utrace_attached_engine *engine, struct task_struct *tsk, struct pt_regs *regs, u32 action, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) #else #if defined(UTRACE_API_VERSION) && (UTRACE_API_VERSION >= 20091216) static u32 usr_itrace_report_signal(u32 action, struct utrace_attached_engine *engine, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) #else static u32 usr_itrace_report_signal(u32 action, struct utrace_attached_engine *engine, struct task_struct *tsk, struct pt_regs *regs, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) #endif #endif { #if defined(UTRACE_API_VERSION) && (UTRACE_API_VERSION >= 20091216) struct task_struct *tsk = current; #endif struct itrace_info *ui; u32 return_flags; unsigned long data = 0; #ifdef CONFIG_PPC data = mfspr(SPRN_SDAR); #endif rcu_read_lock(); ui = rcu_dereference(engine->data); rcu_read_unlock(); WARN_ON(!ui); #if defined(UTRACE_ORIG_VERSION) if (info->si_signo != SIGTRAP || !ui) return UTRACE_RESUME; #else if (utrace_signal_action(action) == UTRACE_SIGNAL_HANDLER || utrace_signal_action(action) == UTRACE_SIGNAL_REPORT || info->si_signo != SIGTRAP || !ui) return UTRACE_RESUME | utrace_signal_action(action); #endif #if defined(UTRACE_ORIG_VERSION) && defined(CONFIG_PPC) /* Because of a ppc utrace bug, we need to stop the task here. usr_itrace_report_quiesce() will continue stepping the task. */ return_flags = UTRACE_SIGNAL_IGN | UTRACE_STOP | UTRACE_ACTION_NEWSTATE; #else /* normal case: continue stepping */ return_flags = ui->step_flag | UTRACE_SIGNAL_IGN; #endif #ifdef CONFIG_PPC if (ui->ppc_atomic_ss.step_over_atomic) { remove_atomic_ss_breakpoint(tsk, &ui->ppc_atomic_ss.end_bpt); if (ui->ppc_atomic_ss.br_bpt.addr) remove_atomic_ss_breakpoint(tsk, &ui->ppc_atomic_ss.br_bpt); ui->ppc_atomic_ss.step_over_atomic = 0; } if (handle_ppc_atomic_seq(tsk, regs, &ui->ppc_atomic_ss)) return_flags = UTRACE_RESUME | UTRACE_SIGNAL_IGN; #endif enter_itrace_probe(ui->itrace_probe, regs, (void *)&data); return return_flags; } #ifdef UTRACE_ORIG_VERSION static u32 usr_itrace_report_clone( struct utrace_attached_engine *engine, struct task_struct *parent, unsigned long clone_flags, struct task_struct *child) #else #if defined(UTRACE_API_VERSION) && (UTRACE_API_VERSION >= 20091216) static u32 usr_itrace_report_clone(u32 action, struct utrace_attached_engine *engine, unsigned long clone_flags, struct task_struct *child) #else static u32 usr_itrace_report_clone(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *parent, unsigned long clone_flags, struct task_struct *child) #endif #endif { return UTRACE_RESUME; } #ifdef UTRACE_ORIG_VERSION static u32 usr_itrace_report_death(struct utrace_attached_engine *e, struct task_struct *tsk) #else #if defined(UTRACE_API_VERSION) && (UTRACE_API_VERSION >= 20091216) static u32 usr_itrace_report_death(struct utrace_attached_engine *e, bool group_dead, int signal) #else static u32 usr_itrace_report_death(struct utrace_attached_engine *e, struct task_struct *tsk, bool group_dead, int signal) #endif #endif { struct itrace_info *ui; rcu_read_lock(); ui = rcu_dereference(e->data); rcu_read_unlock(); WARN_ON(!ui); return (UTRACE_DETACH); } static const struct utrace_engine_ops utrace_ops = { .report_quiesce = usr_itrace_report_quiesce, .report_signal = usr_itrace_report_signal, .report_clone = usr_itrace_report_clone, .report_death = usr_itrace_report_death }; static struct itrace_info *create_itrace_info( struct task_struct *tsk, u32 step_flag, struct stap_itrace_probe *itrace_probe) { struct itrace_info *ui; int status; if (debug) printk(KERN_INFO "create_itrace_info: tid=%d\n", tsk->pid); /* initialize ui */ ui = _stp_kzalloc(sizeof(struct itrace_info)); if (ui == NULL) { printk(KERN_ERR "%s:%d: Unable to allocate memory\n", __FUNCTION__, __LINE__); return NULL; } ui->tsk = tsk; ui->step_flag = step_flag; ui->itrace_probe = itrace_probe; #ifdef CONFIG_PPC ui->ppc_atomic_ss.step_over_atomic = 0; #endif INIT_LIST_HEAD(&ui->link); /* push ui onto usr_itrace_info */ spin_lock(&itrace_lock); list_add(&ui->link, &usr_itrace_info); spin_unlock(&itrace_lock); /* attach a single stepping engine. create_itrace_info is called under rcu read lock, so needs atomic. */ ui->engine = utrace_attach_task(ui->tsk, (UTRACE_ATTACH_CREATE | UTRACE_ATTACH_ATOMIC), &utrace_ops, ui); if (IS_ERR(ui->engine)) { printk(KERN_ERR "utrace_attach returns %ld\n", PTR_ERR(ui->engine)); return NULL; } status = utrace_set_events(tsk, ui->engine, ui->engine->flags | UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | UTRACE_EVENT_SIGNAL_ALL | UTRACE_EVENT(DEATH)); if (status < 0) { printk(KERN_ERR "utrace_attach returns %d\n", status); utrace_engine_put(ui->engine); return NULL; } status = utrace_control(tsk, ui->engine, UTRACE_STOP); if (status == 0) { status = utrace_control(tsk, ui->engine, step_flag); if (status < 0) { printk(KERN_ERR "utrace_control(%d) returns %d\n", step_flag, status); utrace_engine_put(ui->engine); return NULL; } } utrace_engine_put(ui->engine); return ui; } static struct itrace_info *find_itrace_info(struct task_struct *tsk) { struct itrace_info *ui = NULL; spin_lock(&itrace_lock); list_for_each_entry(ui, &usr_itrace_info, link) { if (ui->tsk == tsk) goto done; } ui = NULL; done: spin_unlock(&itrace_lock); return ui; } static int usr_itrace_init(int single_step, struct task_struct *tsk, struct stap_itrace_probe *p) { struct itrace_info *ui; spin_lock_init(&itrace_lock); rcu_read_lock(); if (tsk == NULL) { printk(KERN_ERR "usr_itrace_init: Invalid task\n"); rcu_read_unlock(); return 1; } get_task_struct(tsk); ui = create_itrace_info(tsk, (single_step ? UTRACE_SINGLESTEP : UTRACE_BLOCKSTEP), p); if (!ui) return 1; put_task_struct(tsk); rcu_read_unlock(); if (debug) printk(KERN_INFO "usr_itrace_init: completed for tid = %d\n", tsk->pid); return 0; } void static remove_usr_itrace_info(struct itrace_info *ui) { struct itrace_info *tmp; int status; if (!ui) return; if (debug) printk(KERN_INFO "remove_usr_itrace_info: tid=%d\n", (ui->tsk ? ui->tsk->pid : -1)); if (ui->tsk && ui->engine) { status = utrace_control(ui->tsk, ui->engine, UTRACE_DETACH); if (status == -EINPROGRESS) { do { status = utrace_barrier(ui->tsk, ui->engine); } while (status == -ERESTARTSYS); } if (status < 0 && status != -ESRCH && status != -EALREADY) printk(KERN_ERR "utrace_control(UTRACE_DETACH) returns %d\n", status); } spin_lock(&itrace_lock); list_del(&ui->link); spin_unlock(&itrace_lock); _stp_kfree(ui); } void static cleanup_usr_itrace(void) { struct itrace_info *tmp; struct itrace_info *ui; if (debug) printk(KERN_INFO "cleanup_usr_itrace called\n"); list_for_each_entry_safe(ui, tmp, &usr_itrace_info, link) { remove_usr_itrace_info(ui); } } #ifdef CONFIG_PPC #define PPC_INSTR_SIZE 4 #define TEXT_SEGMENT_BASE 1 /* Instruction masks used during single-stepping of atomic sequences. */ #define LWARX_MASK 0xfc0007fe #define LWARX_INSTR 0x7c000028 #define LDARX_INSTR 0x7c0000A8 #define STWCX_MASK 0xfc0007ff #define STWCX_INSTR 0x7c00012d #define STDCX_INSTR 0x7c0001ad #define BC_MASK 0xfc000000 #define BC_INSTR 0x40000000 #define ATOMIC_SEQ_LENGTH 16 #define BPT_TRAP 0x7fe00008 #define INSTR_SZ sizeof(int) static int get_instr(unsigned long addr, char *msg) { unsigned int instr; if (copy_from_user(&instr, (const void __user *) addr, sizeof(instr))) { printk(KERN_ERR "get_instr failed: %s\n", msg); WARN_ON(1); } return instr; } static void insert_atomic_ss_breakpoint (struct task_struct *tsk, struct bpt_info *bpt) { unsigned int bp_instr = BPT_TRAP; unsigned int cur_instr; cur_instr = get_instr(bpt->addr, "insert_atomic_ss_breakpoint"); if (cur_instr != BPT_TRAP) { bpt->instr = cur_instr; WARN_ON(__access_process_vm(tsk, bpt->addr, &bp_instr, INSTR_SZ, 1) != INSTR_SZ); } } static void remove_atomic_ss_breakpoint (struct task_struct *tsk, struct bpt_info *bpt) { WARN_ON(__access_process_vm(tsk, bpt->addr, &bpt->instr, INSTR_SZ, 1) != INSTR_SZ); } /* locate the branch destination. Return -1 if not a branch. */ static unsigned long branch_dest (int opcode, int instr, struct pt_regs *regs, unsigned long pc) { unsigned long dest; int immediate; int absolute; int ext_op; absolute = (int) ((instr >> 1) & 1); switch (opcode) { case 18: immediate = ((instr & ~3) << 6) >> 6; /* br unconditional */ if (absolute) dest = immediate; else dest = pc + immediate; break; case 16: immediate = ((instr & ~3) << 16) >> 16; /* br conditional */ if (absolute) dest = immediate; else dest = pc + immediate; break; case 19: ext_op = (instr >> 1) & 0x3ff; if (ext_op == 16) { /* br conditional register */ dest = regs->link & ~3; /* FIX: we might be in a signal handler */ WARN_ON(dest > 0); } else if (ext_op == 528) { /* br cond to ctr reg */ dest = regs->ctr & ~3; /* for system call dest < TEXT_SEGMENT_BASE */ if (dest < TEXT_SEGMENT_BASE) dest = regs->link & ~3; } else return -1; break; default: return -1; } return dest; } /* Checks for an atomic sequence of instructions beginning with a LWARX/LDARX instruction and ending with a STWCX/STDCX instruction. If such a sequence is found, attempt to step through it. A breakpoint is placed at the end of the sequence. */ static int handle_ppc_atomic_seq(struct task_struct *tsk, struct pt_regs *regs, struct atomic_ss_info *ss_info) { unsigned long ip = regs->nip; unsigned long start_addr; unsigned int instr; int got_stx = 0; int i; int ret; unsigned long br_dest; /* bpt at branch instr's destination */ int bc_instr_count = 0; /* conditional branch instr count */ instr = get_instr(regs->nip, "handle_ppc_atomic_seq:1"); /* Beginning of atomic sequence starts with lwarx/ldarx instr */ if ((instr & LWARX_MASK) != LWARX_INSTR && (instr & LWARX_MASK) != LDARX_INSTR) return 0; start_addr = regs->nip; for (i = 0; i < ATOMIC_SEQ_LENGTH; ++i) { ip += INSTR_SZ; instr = get_instr(ip, "handle_ppc_atomic_seq:2"); /* look for at most one conditional branch in the sequence * and put a bpt at it's destination address */ if ((instr & BC_MASK) == BC_INSTR) { if (bc_instr_count >= 1) return 0; /* only handle a single branch */ br_dest = branch_dest (BC_INSTR >> 26, instr, regs, ip); if (br_dest != -1 && br_dest >= TEXT_SEGMENT_BASE) { ss_info->br_bpt.addr = br_dest; bc_instr_count++; } } if ((instr & STWCX_MASK) == STWCX_INSTR || (instr & STWCX_MASK) == STDCX_INSTR) { got_stx = 1; break; } } /* Atomic sequence ends with a stwcx/stdcx instr */ if (!got_stx) return 0; ip += INSTR_SZ; instr = get_instr(ip, "handle_ppc_atomic_seq:3"); if ((instr & BC_MASK) == BC_INSTR) { ip += INSTR_SZ; instr = get_instr(ip, "handle_ppc_atomic_seq:4"); } /* Insert a breakpoint right after the end of the atomic sequence. */ ss_info->end_bpt.addr = ip; /* Check for duplicate bpts */ if (bc_instr_count && (ss_info->br_bpt.addr >= start_addr && ss_info->br_bpt.addr <= ss_info->end_bpt.addr)) ss_info->br_bpt.addr = 0; insert_atomic_ss_breakpoint (tsk, &ss_info->end_bpt); if (ss_info->br_bpt.addr) insert_atomic_ss_breakpoint (tsk, &ss_info->br_bpt); ss_info->step_over_atomic = 1; return 1; } #endif