--- /dev/null
+/* Copyright (C) 2013,2014 Oracle, Inc. */
+
+#ifndef _ASM_SPARC_DTRACE_CPUINFO_H_
+#define _ASM_SPARC_DTRACE_CPUINFO_H_
+
+#include <asm/cpudata.h>
+
+typedef cpuinfo_sparc cpuinfo_arch_t;
+
+#define dtrace_cpuinfo_chip(ci) ((ci)->proc_id)
+
+#define TSTATE_CCR_SHIFT 32
+#define TSTATE_ASI_SHIFT 24
+
+#endif /* _ASM_SPARC_DTRACE_CPUINFO_H_ */
--- /dev/null
+/* Copyright (C) 2013,2014 Oracle, Inc. */
+
+#ifndef _SPARC_DTRACE_SDT_H
+#define _SPARC_DTRACE_SDT_H
+
+typedef uint32_t sdt_instr_t;
+
+#define SDT_TRAMP_SIZE 11
+
+#endif /* _SPARC_DTRACE_SDT_H */
--- /dev/null
+/* Copyright (C) 2011-2014 Oracle, Inc. */
+
+DTRACE_SYSCALL_STUB(EXECVE, execve)
+DTRACE_SYSCALL_STUB(PIPE, pipe)
+DTRACE_SYSCALL_STUB(MEMORY_ORDERING, memory_ordering)
+DTRACE_SYSCALL_STUB(SIGALTSTACK, sigaltstack)
+DTRACE_SYSCALL_STUB(RT_SIGRETURN, rt_sigreturn)
+DTRACE_SYSCALL_STUB(VFORK, vfork)
+DTRACE_SYSCALL_STUB(FORK, fork)
+DTRACE_SYSCALL_STUB(CLONE, clone)
+DTRACE_SYSCALL_STUB(EXIT_GROUP, exit_group)
+DTRACE_SYSCALL_STUB(EXIT, exit)
--- /dev/null
+/* Copyright (C) 2013,2014 Oracle, Inc. */
+
+#ifndef _SPARC_DTRACE_UTIL_H
+#define _SPARC_DTRACE_UTIL_H
+
+/* Nothing for now */
+
+#endif /* _SPARC_DTRACE_UTIL_H */
--- /dev/null
+/*
+ * FILE: dtrace_sdt.c
+ * DESCRIPTION: Dynamic Tracing: SDT registration code (arch-specific)
+ *
+ * Copyright (C) 2010-2014 Oracle Corporation
+ */
+
+#include <linux/kernel.h>
+#include <linux/memory.h>
+#include <linux/module.h>
+#include <linux/dtrace_os.h>
+#include <linux/sdt.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/cacheflush.h>
+#include <asm/dtrace_sdt.h>
+
+void __init_or_module dtrace_sdt_nop_multi(sdt_instr_t **addrs, int cnt)
+{
+ int i;
+ sdt_instr_t *addr;
+
+ for (i = 0; i < cnt; i++) {
+ addr = addrs[i];
+ *addr = 0x01000000;
+ flushi(addr);
+ }
+}
+
+/*
+ * Perform architecture dependent initialization for SDT. On sparc64, we need
+ * not do anything.
+ */
+void dtrace_sdt_init_arch(void)
+{
+}
--- /dev/null
+/*
+ * FILE: dtrace_syscall.c
+ * DESCRIPTION: Dynamic Tracing: system call tracing support (arch-specific)
+ *
+ * Copyright (C) 2010-2014 Oracle Corporation
+ */
+
+#include <linux/dtrace_cpu.h>
+#include <linux/dtrace_os.h>
+#include <linux/dtrace_syscall.h>
+#include <linux/fs.h>
+#include <linux/kallsyms.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <asm/compat.h>
+
+#include "systbls.h"
+
+/*---------------------------------------------------------------------------*\
+(* SYSTEM CALL TRACING SUPPORT *)
+\*---------------------------------------------------------------------------*/
+void (*systrace_probe)(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t,
+ uintptr_t, uintptr_t);
+
+void systrace_stub(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
+ uintptr_t arg2, uintptr_t arg3, uintptr_t arg4,
+ uintptr_t arg5)
+{
+}
+
+asmlinkage long systrace_syscall(uintptr_t, uintptr_t,
+ uintptr_t, uintptr_t,
+ uintptr_t, uintptr_t);
+
+static systrace_info_t systrace_info =
+ {
+ &systrace_probe,
+ &systrace_stub,
+ &systrace_syscall,
+ {
+#define DTRACE_SYSCALL_STUB(t, n) \
+ [SCE_##t] dtrace_stub_##n,
+#include <asm/dtrace_syscall.h>
+#undef DTRACE_SYSCALL_STUB
+ },
+ {
+ }
+ };
+
+
+long systrace_syscall(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2,
+ uintptr_t arg3, uintptr_t arg4, uintptr_t arg5)
+{
+ long rc = 0;
+ unsigned long sysnum;
+ dtrace_id_t id;
+ dtrace_syscalls_t *sc;
+
+ sysnum = syscall_get_nr(current, current_pt_regs());
+ sc = &systrace_info.sysent[sysnum];
+
+ if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+ (*systrace_probe)(id, arg0, arg1, arg2, arg3, arg4, arg5);
+
+ /*
+ * FIXME: Add stop functionality for DTrace.
+ */
+
+ if (sc->stsy_underlying != NULL)
+ rc = (*sc->stsy_underlying)(arg0, arg1, arg2, arg3, arg4,
+ arg5);
+
+ if ((id = sc->stsy_return) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0);
+
+ return rc;
+}
+
+systrace_info_t *dtrace_syscalls_init() {
+ int i;
+
+ /*
+ * Only initialize this stuff once...
+ */
+ if (systrace_info.sysent[0].stsy_tblent != NULL)
+ return &systrace_info;
+
+ for (i = 0; i < NR_syscalls; i++) {
+ char sym[KSYM_SYMBOL_LEN];
+ char *p = sym;
+
+ /*
+ * We (ab)use the knowledge that the perfctr system call is
+ * not implemented, and is directed to sys_nis_syscall. We'd
+ * rather refer to that function directly, but it is not a
+ * global symbol.
+ */
+ if (sys_call_table[i] == (uintptr_t)sys_ni_syscall ||
+ sys_call_table[i] == sys_call_table[__NR_perfctr])
+ continue;
+
+ lookup_symbol_name(sys_call_table[i], sym);
+ p = strchr(sym, '_');
+ if (p == NULL)
+ continue;
+ p++;
+
+ systrace_info.sysent[i].name = kstrdup(p, GFP_KERNEL);
+ systrace_info.sysent[i].stsy_tblent =
+ (dt_sys_call_t *)&sys_call_table[i];
+ systrace_info.sysent[i].stsy_underlying =
+ (dt_sys_call_t)(uintptr_t)sys_call_table[i];
+ }
+
+ return &systrace_info;
+}
+EXPORT_SYMBOL(dtrace_syscalls_init);
+
+asmlinkage long dtrace_sys_clone(unsigned long clone_flags,
+ unsigned long newsp, struct pt_regs *regs,
+ unsigned long stack_size)
+{
+ int __user *parent_tidptr, *child_tidptr;
+ long rc = 0;
+ unsigned long orig_i1 = regs->u_regs[UREG_I1];
+ dtrace_id_t id;
+ dtrace_syscalls_t *sc;
+
+ sc = &systrace_info.sysent[__NR_clone];
+
+#ifdef CONFIG_COMPAT
+ if (test_thread_flag(TIF_32BIT)) {
+ parent_tidptr = compat_ptr(regs->u_regs[UREG_I2]);
+ child_tidptr = compat_ptr(regs->u_regs[UREG_I4]);
+ } else
+#endif
+ {
+ parent_tidptr = (int __user *) regs->u_regs[UREG_I2];
+ child_tidptr = (int __user *) regs->u_regs[UREG_I4];
+ }
+
+ if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+ (*systrace_probe)(id, clone_flags, newsp,
+ (uintptr_t)parent_tidptr,
+ (uintptr_t)child_tidptr, 0, 0);
+
+ /*
+ * FIXME: Add stop functionality for DTrace.
+ */
+
+ rc = do_fork(clone_flags, newsp, stack_size, parent_tidptr,
+ child_tidptr);
+
+ if ((unsigned long)rc >= -ERESTART_RESTARTBLOCK)
+ regs->u_regs[UREG_I1] = orig_i1;
+
+ if ((id = sc->stsy_return) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0);
+
+ return rc;
+}
+
+asmlinkage long dtrace_sys_execve(const char __user *name,
+ const char __user *const __user *argv,
+ const char __user *const __user *envp)
+{
+ long rc = 0;
+ dtrace_id_t id;
+ dtrace_syscalls_t *sc;
+
+ sc = &systrace_info.sysent[__NR_execve];
+
+ if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)name, (uintptr_t)argv,
+ (uintptr_t)envp, 0, 0, 0);
+
+ /*
+ * FIXME: Add stop functionality for DTrace.
+ */
+
+ rc = do_execve(getname(name), argv, envp);
+
+out:
+ if ((id = sc->stsy_return) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0);
+
+ return rc;
+}
+
+asmlinkage long dtrace_sys_exit(int error_code)
+{
+ long rc = 0;
+ dtrace_id_t id;
+ dtrace_syscalls_t *sc;
+
+ sc = &systrace_info.sysent[__NR_exit];
+
+ if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+ (*systrace_probe)(id, error_code, 0, 0, 0, 0, 0);
+
+ /*
+ * FIXME: Add stop functionality for DTrace.
+ */
+
+ do_exit((error_code&0xff)<<8);
+
+ if ((id = sc->stsy_return) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0);
+
+ return rc;
+}
+
+asmlinkage long dtrace_sys_exit_group(int error_code)
+{
+ long rc = 0;
+ dtrace_id_t id;
+ dtrace_syscalls_t *sc;
+
+ sc = &systrace_info.sysent[__NR_exit_group];
+
+ if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+ (*systrace_probe)(id, error_code, 0, 0, 0, 0, 0);
+
+ /*
+ * FIXME: Add stop functionality for DTrace.
+ */
+
+ do_group_exit((error_code & 0xff) << 8);
+
+ if ((id = sc->stsy_return) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0);
+
+ return rc;
+}
+
+asmlinkage long dtrace_sys_memory_ordering(unsigned long model,
+ struct pt_regs *regs)
+{
+ long rc = 0;
+ dtrace_id_t id;
+ dtrace_syscalls_t *sc;
+
+ sc = &systrace_info.sysent[__NR_memory_ordering];
+
+ if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)regs, 0, 0, 0, 0, 0);
+
+ /*
+ * FIXME: Add stop functionality for DTrace.
+ */
+
+ if (model >= 3)
+ rc = -EINVAL;
+ else
+ regs->tstate = (regs->tstate & ~TSTATE_MM) | (model << 14);
+
+ if ((id = sc->stsy_return) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0);
+
+ return rc;
+}
+
+asmlinkage long dtrace_sys_pipe(struct pt_regs *regs)
+{
+ int fd[2];
+ long rc = 0;
+ dtrace_id_t id;
+ dtrace_syscalls_t *sc;
+
+ sc = &systrace_info.sysent[__NR_pipe];
+
+ if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+ (*systrace_probe)(id, 0, 0, 0, 0, 0, 0);
+
+ /*
+ * FIXME: Add stop functionality for DTrace.
+ */
+
+ rc = do_pipe_flags(fd, 0);
+ if (rc)
+ goto out;
+
+ regs->u_regs[UREG_I1] = fd[1];
+ rc = fd[0];
+
+out:
+ if ((id = sc->stsy_return) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0);
+
+ return rc;
+}
+
+asmlinkage long dtrace_sys_rt_sigreturn(struct pt_regs *regs)
+{
+ long rc = 0;
+ dtrace_id_t id;
+ dtrace_syscalls_t *sc;
+
+ sc = &systrace_info.sysent[__NR_rt_sigreturn];
+
+ if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)regs, 0, 0, 0, 0, 0);
+
+ /*
+ * FIXME: Add stop functionality for DTrace.
+ */
+
+ do_rt_sigreturn(regs);
+
+ if ((id = sc->stsy_return) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0);
+
+ return rc;
+}
+
+asmlinkage long dtrace_sys_sigaltstack(const stack_t __user *uss,
+ stack_t __user *uoss, unsigned long sp)
+{
+ long rc = 0;
+ dtrace_id_t id;
+ dtrace_syscalls_t *sc;
+
+ sc = &systrace_info.sysent[__NR_sigaltstack];
+
+ if ((id = sc->stsy_entry) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)uss, (uintptr_t)uoss, sp, 0,
+ 0, 0);
+
+ /*
+ * FIXME: Add stop functionality for DTrace.
+ */
+
+ rc = do_sigaltstack(uss, uoss, sp);
+
+ if ((id = sc->stsy_return) != DTRACE_IDNONE)
+ (*systrace_probe)(id, (uintptr_t)rc, (uintptr_t)rc,
+ (uintptr_t)((uint64_t)rc >> 32), 0, 0, 0);
+
+ return rc;
+}
--- /dev/null
+/*
+ * FILE: dtrace_syscall_stubs.S
+ * DESCRIPTION: Dynamic Tracing: Syscall tracing stubs (arch-specific)
+ *
+ * Copyright (C) 2010-2014 Oracle Corporation
+ */
+
+#include <linux/linkage.h>
+#include <asm/head.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/thread_info.h>
+
+ ENTRY(dtrace_stub_execve)
+ set dtrace_sys_execve, %g1
+ jmpl %g1, %g0
+ flushw
+ ENDPROC(dtrace_stub_execve)
+
+ ENTRY(dtrace_stub_pipe)
+ ba,pt %xcc, dtrace_sys_pipe
+ add %sp, PTREGS_OFF, %o0
+ ENDPROC(dtrace_stub_pipe)
+
+ ENTRY(dtrace_stub_memory_ordering)
+ ba,pt %xcc, dtrace_sys_memory_ordering
+ add %sp, PTREGS_OFF, %o1
+ ENDPROC(dtrace_stub_memory_ordering)
+
+ ENTRY(dtrace_stub_sigaltstack)
+ ba,pt %xcc, dtrace_sys_sigaltstack
+ add %i6, STACK_BIAS, %o2
+ ENDPROC(dtrace_stub_sigaltstack)
+
+ ENTRY(dtrace_stub_rt_sigreturn)
+ add %sp, PTREGS_OFF, %o0
+ call dtrace_sys_rt_sigreturn
+ add %o7, 1f-.-4, %o7
+ nop
+ .align 32
+1: ldx [%g6 + TI_FLAGS], %l5
+ andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0
+ be,pt %icc, 2f
+ nop
+ call syscall_trace_leave
+ add %sp, PTREGS_OFF, %o0
+2: set rtrap, %g1
+ jmpl %g1, %g0
+ nop
+ ENDPROC(dtrace_stub_rt_sigreturn)
+
+ ENTRY(dtrace_stub_vfork)
+ sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0
+ or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
+ ba,pt %xcc, dtrace_stub_clone
+
+ ENTRY(dtrace_stub_fork)
+ clr %o1
+ mov SIGCHLD, %o0
+
+ ENTRY(dtrace_stub_clone)
+ flushw
+ movrz %o1, %fp, %o1
+ mov 0, %o3
+ ba,pt %xcc, dtrace_sys_clone
+ add %sp, PTREGS_OFF, %o2
+ ENDPROC(dtrace_stub_clone)
+ ENDPROC(dtrace_stub_fork)
+ ENDPROC(dtrace_stub_vfork)
+
+ ENTRY(dtrace_stub_exit_group)
+ sethi %hi(dtrace_sys_exit_group), %g7
+ ba,pt %xcc, 1f
+ or %g7, %lo(dtrace_sys_exit_group), %g7
+ ENDPROC(dtrace_stub_exit_group)
+
+ ENTRY(dtrace_stub_exit)
+ sethi %hi(dtrace_sys_exit), %g7
+ or %g7, %lo(dtrace_sys_exit), %g7
+1: rdpr %pstate, %g2
+ wrpr %g2, PSTATE_IE, %pstate
+ rdpr %otherwin, %g1
+ rdpr %cansave, %g3
+ add %g3, %g1, %g3
+ wrpr %g3, 0x0, %cansave
+ wrpr %g0, 0x0, %otherwin
+ wrpr %g2, 0x0, %pstate
+ jmpl %g7, %g0
+ stb %g0, [%g6 + TI_WSAVED]
+ ENDPROC(dtrace_stub_exit)
--- /dev/null
+/*
+ * FILE: dtrace_util.c
+ * DESCRIPTION: Dynamic Tracing: Architecture utility functions
+ *
+ * Copyright (C) 2010-2014 Oracle Corporation
+ */
+
+#include <linux/dtrace_cpu.h>
+#include <linux/kdebug.h>
+#include <linux/notifier.h>
+#include <linux/slab.h>
+#include <asm/ptrace.h>
+
+void dtrace_skip_instruction(struct pt_regs *regs) {
+ regs->tpc = regs->tnpc;
+ regs->tnpc += 4;
+}
+
+
+int dtrace_die_notifier(struct notifier_block *nb, unsigned long val,
+ void *args)
+{
+ struct die_args *dargs = args;
+
+ switch (val) {
+ case DIE_PAGE_FAULT: {
+ unsigned long addr = current_thread_info()->fault_address;
+
+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
+ return NOTIFY_DONE;
+
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+ this_cpu_core->cpuc_dtrace_illval = addr;
+
+ dtrace_skip_instruction(dargs->regs);
+
+ return NOTIFY_OK | NOTIFY_STOP_MASK;
+ }
+ case DIE_GPF: {
+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
+ return NOTIFY_DONE;
+
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
+
+ dtrace_skip_instruction(dargs->regs);
+
+ return NOTIFY_OK | NOTIFY_STOP_MASK;
+ }
+ case DIE_TRAP: {
+ unsigned long addr = current_thread_info()->fault_address;
+
+ if (dargs->trapnr != 0x34)
+ return NOTIFY_DONE;
+ if (!DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT))
+ return NOTIFY_DONE;
+
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+
+ dtrace_skip_instruction(dargs->regs);
+
+ return NOTIFY_OK | NOTIFY_STOP_MASK;
+ }
+ default:
+ return NOTIFY_DONE;
+ }
+}
#include <linux/interrupt.h>
#include <linux/kdebug.h>
#include <linux/module.h>
+#include <linux/moduleloader.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/stacktrace.h>
/*---------------------------------------------------------------------------*\
(* OS SPECIFIC DTRACE SETUP *)
\*---------------------------------------------------------------------------*/
+#define DTRACE_PDATA_MAXSIZE 2048
+
struct module *dtrace_kmod = NULL;
EXPORT_SYMBOL(dtrace_kmod);
void dtrace_os_init(void)
{
if (dtrace_kmod != NULL) {
- pr_warning("%s: cannot be called twice\n", __func__);
+ pr_warn_once("%s: cannot be called twice\n", __func__);
return;
}
- dtrace_kmod = kzalloc(sizeof(struct module), GFP_KERNEL);
+ /*
+ * A little bit of magic...
+ * We create a dummy module to represent the core Linux kernel. The
+ * only data we're interested in is the name, the SDT probe points data
+ * (to be filled in by dtrace_sdt_register()), and the probe data.
+ * DTrace uses an architecture-specific structure (hidden from us here)
+ * to hold some data, and since we do not know the layout or the size,
+ * we ensure that we allocate enough memory to accomodate the largest
+ * of those structures.
+ * So, the memory we allocate will hold:
+ * - the dtrace_kmod module structure
+ * - a block of memory (aligned at a structure boundary) to be
+ * used for pdata and other related data
+ * The memory is allocated from the modules space.
+ */
+ dtrace_kmod = module_alloc(ALIGN(sizeof(struct module), 8) +
+ DTRACE_PDATA_MAXSIZE);
if (dtrace_kmod == NULL) {
pr_warning("%s: cannot allocate kernel pseudo-module\n",
__func__);
return;
}
- dtrace_kmod->state = MODULE_STATE_LIVE;
strlcpy(dtrace_kmod->name, "vmlinux", MODULE_NAME_LEN);
+ dtrace_kmod->state = MODULE_STATE_LIVE;
+ dtrace_kmod->pdata = (char *)dtrace_kmod +
+ ALIGN(sizeof(struct module), 8);
+ dtrace_kmod->core_size = DTRACE_PDATA_MAXSIZE;
psinfo_cachep = kmem_cache_create("psinfo_cache",
sizeof(dtrace_psinfo_t), 0,
void dtrace_psinfo_alloc(struct task_struct *tsk)
{
dtrace_psinfo_t *psinfo;
- struct mm_struct *mm;
+ struct mm_struct *mm = NULL;
if (likely(tsk->dtrace_psinfo)) {
put_psinfo(tsk);
psinfo->argc = 0;
for (p = (char *)mm->arg_start; p < (char *)mm->arg_end;
psinfo->argc++) {
- size_t l = strnlen(p, MAX_ARG_STRLEN);
+ size_t l = strnlen_user(p, MAX_ARG_STRLEN);
if (!l)
break;
*/
for (i = 0, p = (char *)mm->arg_start; i < len; i++) {
psinfo->argv[i] = p;
- p += strnlen(p, MAX_ARG_STRLEN) + 1;
+ p += strnlen_user(p, MAX_ARG_STRLEN) + 1;
}
psinfo->argv[len] = NULL;
*/
for (p = (char *)mm->env_start; p < (char *)mm->env_end;
envc++) {
- size_t l = strnlen(p, MAX_ARG_STRLEN);
+ size_t l = strnlen_user(p, MAX_ARG_STRLEN);
if (!l)
break;
*/
for (i = 0, p = (char *)mm->env_start; i < len; i++) {
psinfo->envp[i] = p;
- p += strnlen(p, MAX_ARG_STRLEN) + 1;
+ p += strnlen_user(p, MAX_ARG_STRLEN) + 1;
}
psinfo->envp[len] = NULL;
* Just in case we run into failures further on...
*/
mp->sdt_probes = NULL;
- mp->num_dtrace_probes = 0;
+ mp->sdt_probec = 0;
if (dtrace_sdt_nprobes == 0)
return;
}
mp->sdt_probes = sdps;
- mp->num_dtrace_probes = cnt;
+ mp->sdt_probec = cnt;
dtrace_sdt_nop_multi(addrs, cnt);
return NOTIFY_DONE;
if (!mp)
return NOTIFY_DONE;
- if (mp->num_dtrace_probes == 0 || mp->sdt_probes == NULL)
+ if (mp->sdt_probec == 0 || mp->sdt_probes == NULL)
return NOTIFY_DONE;
/*
* Create a list of addresses (SDT probe locations) that need to be
* patched with a NOP instruction (or instruction sequence).
*/
- addrs = (sdt_instr_t **)vmalloc(mp->num_dtrace_probes *
+ addrs = (sdt_instr_t **)vmalloc(mp->sdt_probec *
sizeof(sdt_instr_t *));
if (addrs == NULL) {
pr_warning("%s: cannot allocate SDT probe address list (%s)\n",
return NOTIFY_DONE;
}
- for (i = cnt = 0, sdp = mp->sdt_probes; i < mp->num_dtrace_probes;
+ for (i = cnt = 0, sdp = mp->sdt_probes; i < mp->sdt_probec;
i++, sdp++) {
/*
* Fix-up the offset to reflect the relocated address of the
if [ "$opr" = "sdtstub" ]; then
${NM} -u $* | \
grep __dtrace_probe_ | sort | uniq | \
- ${AWK} '{
- printf("\t.globl %s\n\t.type %s,@function\n%s:\n",
- $2, $2, $2);
- count++;
- }
-
- END {
- if (count)
- print "\tret";
- else
- exit(1);
- }' > $tfn
+ ${AWK} -v arch=${ARCH} \
+ '{
+ printf("\t.globl %s\n\t.type %s,@function\n%s:\n",
+ $2, $2, $2);
+ count++;
+ }
+
+ END {
+ if (count) {
+ if (arch == "x86_64") {
+ print "\tret";
+ } else if (arch == "sparc64") {
+ print "\tretl";
+ print "\tnop";
+ }
+ } else
+ exit(1);
+ }' > $tfn
exit 0
fi
getline;
}
+
+ sect = 0;
next;
}
next;
}
- /__dtrace_probe_/ && sect !~ /debug/ {
+ /__dtrace_probe_/ && sect && sect !~ /debug/ {
$3 = substr($3, 16);
sub(/-.*$/, "", $3);
printf "%16s %s R %s %s\n", sect, $1, $3, sectbase[sect];
sort
[ "x${lfn}" != "x" -a "x${lfn}" != "xkmod" ] && nm ${lfn}
) | \
+ tee /tmp/DEBUG | \
awk -v lfn="${lfn}" \
+ -v arch=${ARCH} \
'function addl(v0, v1, v0h, v0l, v1h, v1l, d, tmp) {
tmp = $0;
- if (length(v0) > 8) {
+ if (length(v0) > 8 || length(v1) > 8) {
d = length(v0);
v0h = strtonum("0x"substr(v0, 1, d - 8));
v0l = strtonum("0x"substr(v0, d - 8 + 1));
pn = fun":"prb;
ad = addl(baseaddr, poffst[pn]);
+ if (arch == "x86_64")
+ ad = subl(ad, 1);
+
if (lfn != "kmod") {
- print "\tPTR\t0x" ad;
- print "\tPTR\t" length(prb);
- print "\tPTR\t" length(fun);
- print "\t.asciz\t\042" prb "\042";
- print "\t.asciz\t\042" fun "\042";
+ printf "\tPTR\t0x%s\n", ad;
+ printf "\tPTR\t%d\n", length(prb);
+ printf "\tPTR\t%d\n", length(fun);
+ printf "\t.asciz\t\042%s\042\n", prb;
+ printf "\t.asciz\t\042%s\042\n", fun;
print "\tALGN";
} else {
if (probec == 0)
print "static sdt_probedesc_t\t_sdt_probes[] = {";
- print " {\042" prb "\042, \042"fun"\042, 0x" ad " },";
+ printf " {\042%s\042, \042%s\042, 0x%s },\n", \
+ prb, fun, ad;
}
probec++;
print ".globl dtrace_sdt_nprobes";
print "\tALGN";
print "dtrace_sdt_nprobes:";
- print "\tPTR\t" probec;
+ printf "\tPTR\t%d\n", probec;
} else {
if (probec > 0)
print "};";