diff options
author | David Smith <dsmith@redhat.com> | 2009-03-12 12:58:49 -0500 |
---|---|---|
committer | David Smith <dsmith@redhat.com> | 2009-03-12 12:58:49 -0500 |
commit | 2791f774da562b5a2bfc976baad246999da29ea6 (patch) | |
tree | d1ece2d650e6307d86ed6269d4afffbaf30e05c3 /runtime | |
parent | 976f6b6a6fae081d1d72d06457d64af87db789ef (diff) | |
parent | 96b030fe8a0bb0297d23638e2975a3e9eb2b85b6 (diff) | |
download | systemtap-steved-2791f774da562b5a2bfc976baad246999da29ea6.tar.gz systemtap-steved-2791f774da562b5a2bfc976baad246999da29ea6.tar.xz systemtap-steved-2791f774da562b5a2bfc976baad246999da29ea6.zip |
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap into pr7043
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/alloc.c | 25 | ||||
-rw-r--r-- | runtime/autoconf-alloc-percpu-align.c | 6 | ||||
-rw-r--r-- | runtime/autoconf-save-stack-trace.c | 22 | ||||
-rw-r--r-- | runtime/itrace.c | 146 | ||||
-rw-r--r-- | runtime/sduprobes.c | 61 | ||||
-rw-r--r-- | runtime/stack-i386.c | 2 | ||||
-rw-r--r-- | runtime/stack-x86_64.c | 2 | ||||
-rw-r--r-- | runtime/stack.c | 7 |
8 files changed, 153 insertions, 118 deletions
diff --git a/runtime/alloc.c b/runtime/alloc.c index 89d16612..439e8a7e 100644 --- a/runtime/alloc.c +++ b/runtime/alloc.c @@ -233,30 +233,14 @@ static void *_stp_vmalloc(unsigned long size) } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) static void *_stp_alloc_percpu(size_t size) { -#ifdef DEBUG_MEM +#ifdef STAPCONF_ALLOC_PERCPU_ALIGN void *ret = __alloc_percpu(size, 8); - if (likely(ret)) { - struct _stp_mem_entry *m = kmalloc(sizeof(struct _stp_mem_entry), STP_ALLOC_FLAGS); - if (unlikely(m == NULL)) { - free_percpu(ret); - return NULL; - } - _stp_mem_debug_percpu(m, ret, size); - _stp_allocated_memory += size * num_online_cpus(); - } - return ret; #else - return __alloc_percpu(size, 8); + void *ret = __alloc_percpu(size); #endif -} -#else -static void *_stp_alloc_percpu(size_t size) -{ #ifdef DEBUG_MEM - void *ret = __alloc_percpu(size); if (likely(ret)) { struct _stp_mem_entry *m = kmalloc(sizeof(struct _stp_mem_entry), STP_ALLOC_FLAGS); if (unlikely(m == NULL)) { @@ -266,12 +250,9 @@ static void *_stp_alloc_percpu(size_t size) _stp_mem_debug_percpu(m, ret, size); _stp_allocated_memory += size * num_online_cpus(); } - return ret; -#else - return __alloc_percpu(size); #endif + return ret; } -#endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) #define _stp_kmalloc_node(size,node) _stp_kmalloc(size) diff --git a/runtime/autoconf-alloc-percpu-align.c b/runtime/autoconf-alloc-percpu-align.c new file mode 100644 index 00000000..158d579c --- /dev/null +++ b/runtime/autoconf-alloc-percpu-align.c @@ -0,0 +1,6 @@ +#include <linux/percpu.h> + +/* kernel commit f2a8205c */ +void foo (void) { + (void) __alloc_percpu(sizeof(int), 8); +} diff --git a/runtime/autoconf-save-stack-trace.c b/runtime/autoconf-save-stack-trace.c new file mode 100644 index 00000000..39ded684 --- /dev/null +++ b/runtime/autoconf-save-stack-trace.c @@ -0,0 +1,22 @@ +#include <linux/string.h> +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <asm/stacktrace.h> + +void foo(struct task_struct *foo) +{ + struct stack_trace trace; + unsigned long backtrace[20]; + memset(&trace, 0, sizeof(trace)); + trace.entries = &backtrace[0]; + trace.max_entries = 20; + trace.skip = 0; + save_stack_trace_tsk(tsk, &trace); +} + +static const struct stacktrace_ops print_stack_ops; + +void dumper(struct task_struct *foo) +{ + dump_trace(foo, 0, 0, 0, &print_stack_ops, 0); +} diff --git a/runtime/itrace.c b/runtime/itrace.c index df18a400..ed32b0bc 100644 --- a/runtime/itrace.c +++ b/runtime/itrace.c @@ -1,6 +1,6 @@ /* * user space instruction tracing - * Copyright (C) 2005, 2006, 2007, 2008 IBM Corp. + * Copyright (C) 2005, 2006, 2007, 2008, 2009 IBM Corp. * * 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 @@ -18,8 +18,6 @@ #include <linux/rcupdate.h> #include <linux/utrace.h> #include <asm/string.h> -#include <asm/tracehook.h> -#include <asm/ptrace.h> #include "uprobes/uprobes.h" #ifndef put_task_struct @@ -65,10 +63,81 @@ static struct itrace_info *create_itrace_info( struct task_struct *tsk, u32 step_flag, struct stap_itrace_probe *itrace_probe); -static u32 usr_itrace_report_signal(struct utrace_attached_engine *engine, +/* + * The kernel's access_process_vm is not exported in kernel.org kernels, although + * some distros export it on some architectures. To workaround this inconsistency, + * we copied and pasted it here. Fortunately, everything it calls is exported. + */ +#include <linux/pagemap.h> +#include <asm/cacheflush.h> +static int __access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) +{ + struct mm_struct *mm; + struct vm_area_struct *vma; + struct page *page; + void *old_buf = buf; + + mm = get_task_mm(tsk); + if (!mm) + return 0; + + down_read(&mm->mmap_sem); + /* ignore errors, just check how much was sucessfully transfered */ + while (len) { + int bytes, ret, offset; + void *maddr; + + ret = get_user_pages(tsk, mm, addr, 1, + write, 1, &page, &vma); + if (ret <= 0) + break; + + bytes = len; + offset = addr & (PAGE_SIZE-1); + if (bytes > PAGE_SIZE-offset) + bytes = PAGE_SIZE-offset; + + maddr = kmap(page); + if (write) { + copy_to_user_page(vma, page, addr, + maddr + offset, buf, bytes); + set_page_dirty_lock(page); + } else { + copy_from_user_page(vma, page, addr, + buf, maddr + offset, bytes); + } + kunmap(page); + page_cache_release(page); + len -= bytes; + buf += bytes; + addr += bytes; + } + up_read(&mm->mmap_sem); + mmput(mm); + + return buf - old_buf; +} + +static u32 usr_itrace_report_quiesce(enum utrace_resume_action action, + struct utrace_attached_engine *engine, + struct task_struct *tsk, + unsigned long event) +{ + int status; + struct itrace_info *ui; + + ui = rcu_dereference(engine->data); + WARN_ON(!ui); + + return (event == 0 ? ui->step_flag : UTRACE_RESUME); +} + + +static u32 usr_itrace_report_signal(u32 action, + struct utrace_attached_engine *engine, struct task_struct *tsk, struct pt_regs *regs, - u32 action, siginfo_t *info, + siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { @@ -83,12 +152,10 @@ static u32 usr_itrace_report_signal(struct utrace_attached_engine *engine, WARN_ON(!ui); if (info->si_signo != SIGTRAP || !ui) - return UTRACE_ACTION_RESUME; - - /* normal case: continue stepping, hide this trap from other engines */ - return_flags = ui->step_flag | UTRACE_ACTION_HIDE | UTRACE_SIGNAL_IGN | - UTRACE_ACTION_NEWSTATE; + return UTRACE_RESUME; + /* normal case: continue stepping */ + return_flags = ui->step_flag | UTRACE_SIGNAL_IGN; #ifdef CONFIG_PPC if (ui->ppc_atomic_ss.step_over_atomic) { remove_atomic_ss_breakpoint(tsk, &ui->ppc_atomic_ss.end_bpt); @@ -99,8 +166,7 @@ static u32 usr_itrace_report_signal(struct utrace_attached_engine *engine, } if (handle_ppc_atomic_seq(tsk, regs, &ui->ppc_atomic_ss)) - return_flags = UTRACE_ACTION_RESUME | UTRACE_ACTION_NEWSTATE | - UTRACE_SIGNAL_IGN; + return_flags = UTRACE_RESUME | UTRACE_SIGNAL_IGN; #endif enter_itrace_probe(ui->itrace_probe, regs, (void *)&data); @@ -108,24 +174,26 @@ static u32 usr_itrace_report_signal(struct utrace_attached_engine *engine, return return_flags; } -static u32 usr_itrace_report_clone(struct utrace_attached_engine *engine, +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) { - return UTRACE_ACTION_RESUME; + return UTRACE_RESUME; } static u32 usr_itrace_report_death(struct utrace_attached_engine *e, - struct task_struct *tsk) + struct task_struct *tsk, bool group_dead, int signal) { struct itrace_info *ui = rcu_dereference(e->data); WARN_ON(!ui); - return (UTRACE_ACTION_NEWSTATE | UTRACE_ACTION_DETACH); + 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 @@ -137,6 +205,7 @@ static struct itrace_info *create_itrace_info( 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); @@ -154,20 +223,34 @@ static struct itrace_info *create_itrace_info( /* 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 */ - ui->engine = utrace_attach(ui->tsk, UTRACE_ATTACH_CREATE, &utrace_ops, ui); + ui->engine = utrace_attach_task(ui->tsk, UTRACE_ATTACH_CREATE, &utrace_ops, ui); if (IS_ERR(ui->engine)) { printk(KERN_ERR "utrace_attach returns %ld\n", PTR_ERR(ui->engine)); - ui = NULL; - } else { - utrace_set_flags(tsk, ui->engine, ui->engine->flags | - ui->step_flag | - UTRACE_EVENT(CLONE) | UTRACE_EVENT_SIGNAL_ALL | - UTRACE_EVENT(DEATH)); + return NULL; } - spin_unlock(&itrace_lock); + 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); + 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); + return NULL; + } + } + return ui; } @@ -193,7 +276,7 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe struct task_struct *tsk; rcu_read_lock(); - tsk = find_task_by_pid(tid); + tsk = find_task_by_vpid(tid); if (!tsk) { printk(KERN_ERR "usr_itrace_init: Cannot find process %d\n", tid); rcu_read_unlock(); @@ -203,7 +286,7 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe get_task_struct(tsk); ui = create_itrace_info(tsk, (single_step ? - UTRACE_ACTION_SINGLESTEP : UTRACE_ACTION_BLOCKSTEP), p); + UTRACE_SINGLESTEP : UTRACE_BLOCKSTEP), p); if (!ui) return 1; @@ -223,6 +306,7 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe void static remove_usr_itrace_info(struct itrace_info *ui) { struct itrace_info *tmp; + int status; if (!ui) return; @@ -232,7 +316,11 @@ void static remove_usr_itrace_info(struct itrace_info *ui) spin_lock(&itrace_lock); if (ui->tsk && ui->engine) { - (void) utrace_detach(ui->tsk, ui->engine); + status = utrace_control(ui->tsk, ui->engine, UTRACE_DETACH); + if (status < 0 && status != -ESRCH && status != -EALREADY) + printk(KERN_ERR + "utrace_control(UTRACE_DETACH) returns %d\n", + status); } list_del(&ui->link); spin_unlock(&itrace_lock); @@ -292,7 +380,7 @@ static void insert_atomic_ss_breakpoint (struct task_struct *tsk, 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) != + WARN_ON(__access_process_vm(tsk, bpt->addr, &bp_instr, INSTR_SZ, 1) != INSTR_SZ); } } @@ -300,7 +388,7 @@ static void insert_atomic_ss_breakpoint (struct task_struct *tsk, 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) != + WARN_ON(__access_process_vm(tsk, bpt->addr, &bpt->instr, INSTR_SZ, 1) != INSTR_SZ); } diff --git a/runtime/sduprobes.c b/runtime/sduprobes.c deleted file mode 100644 index 83bc8e72..00000000 --- a/runtime/sduprobes.c +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2005-2008 Red Hat Inc. -// Copyright (C) 2006 Intel Corporation. -// -// 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 <stddef.h> -#define unused __attribute__ ((unused)) - -int -_stap_probe_0 (char* probe unused) -{ - return 1; -} - -int -_stap_probe_1 (char* probe unused, - size_t arg1 unused) -{ - return 1; -} - -int -_stap_probe_2 (char* probe unused , - size_t arg1 unused, - size_t arg2 unused) -{ - return 1; -} - -int -_stap_probe_3 (char* probe unused, - size_t arg1 unused, - size_t arg2 unused, - size_t arg3 unused) -{ - return 1; -} - -int -_stap_probe_4 (char* probe unused, - size_t arg1 unused, - size_t arg2 unused, - size_t arg3 unused, - size_t arg4 unused) -{ - return 1; -} - -int -_stap_probe_5 (char* probe unused, - size_t arg1 unused, - size_t arg2 unused, - size_t arg3 unused, - size_t arg4 unused, - size_t arg5 unused) -{ - return 1; -} diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c index 206801d8..5a18c9d8 100644 --- a/runtime/stack-i386.c +++ b/runtime/stack-i386.c @@ -14,7 +14,7 @@ static int _stp_valid_stack_ptr(unsigned long context, unsigned long p) } /* DWARF unwinder failed. Just dump intereting addresses on kernel stack. */ -#if ! (defined(CONFIG_STACKTRACE) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) +#if !defined(STAPCONF_KERNEL_STACKTRACE) static void _stp_stack_print_fallback(unsigned long stack, int verbose, int levels) { unsigned long addr; diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c index 183de0a0..03d88ef0 100644 --- a/runtime/stack-x86_64.c +++ b/runtime/stack-x86_64.c @@ -10,7 +10,7 @@ /* DWARF unwinder failed. Just dump intereting addresses on kernel stack. */ -#if ! (defined(CONFIG_STACKTRACE) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) +#if !defined(STAPCONF_KERNEL_STACKTRACE) static void _stp_stack_print_fallback(unsigned long stack, int verbose, int levels) { unsigned long addr; diff --git a/runtime/stack.c b/runtime/stack.c index aa0e6d65..f6b1cd08 100644 --- a/runtime/stack.c +++ b/runtime/stack.c @@ -27,8 +27,7 @@ #define MAXBACKTRACE 20 -#if defined(CONFIG_STACKTRACE) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26) -// XXX: PR9866: hacky temporarily restriction to recent kernels +#if defined(STAPCONF_KERNEL_STACKTRACE) #include <linux/stacktrace.h> #include <asm/stacktrace.h> #endif @@ -51,7 +50,7 @@ static void _stp_stack_print_fallback(unsigned long, int, int); #error "Unsupported architecture" #endif -#if defined(CONFIG_STACKTRACE) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26) +#if defined(STAPCONF_KERNEL_STACKTRACE) struct print_stack_data { @@ -161,7 +160,7 @@ static void _stp_ustack_print(char *str) void _stp_stack_print_tsk(struct task_struct *tsk, int verbose, int levels) { -#if defined(CONFIG_STACKTRACE) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26) +#if defined(STAPCONF_KERNEL_STACKTRACE) int i; unsigned long backtrace[MAXBACKTRACE]; struct stack_trace trace; |