mirror of
https://github.com/opnsense/src.git
synced 2026-04-23 15:19:31 -04:00
Currently this argument is a pointer into the stack which is used by FBT to fetch the first five probe arguments. On all non-x86 architectures it's simply the trapframe address, so this change has no functional impact. On amd64 it's a pointer into the trapframe such that stack[1 .. 5] gives the first five argument registers, which are deliberately grouped together in the amd64 trapframe definition. A trapframe argument simplifies the invop handlers on !x86 and makes the x86 FBT invop handler easier to understand. Moreover, it allows for invop handlers that may want to modify the register set of the interrupted thread.
679 lines
15 KiB
C
679 lines
15 KiB
C
/*
|
|
* CDDL HEADER START
|
|
*
|
|
* The contents of this file are subject to the terms of the
|
|
* Common Development and Distribution License, Version 1.0 only
|
|
* (the "License"). You may not use this file except in compliance
|
|
* with the License.
|
|
*
|
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
* or http://www.opensolaris.org/os/licensing.
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
*
|
|
* When distributing Covered Code, include this CDDL HEADER in each
|
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
* If applicable, add the following below this CDDL HEADER, with the
|
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
*
|
|
* CDDL HEADER END
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
/*
|
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
|
* Use is subject to license terms.
|
|
*/
|
|
#include <sys/cdefs.h>
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/stack.h>
|
|
#include <sys/pcpu.h>
|
|
|
|
#include <machine/frame.h>
|
|
#include <machine/md_var.h>
|
|
#include <machine/pcb.h>
|
|
#include <machine/stack.h>
|
|
|
|
#include <vm/vm.h>
|
|
#include <vm/vm_param.h>
|
|
#include <vm/pmap.h>
|
|
|
|
#include "regset.h"
|
|
|
|
extern uintptr_t kernbase;
|
|
uintptr_t kernelbase = (uintptr_t) &kernbase;
|
|
|
|
uint8_t dtrace_fuword8_nocheck(void *);
|
|
uint16_t dtrace_fuword16_nocheck(void *);
|
|
uint32_t dtrace_fuword32_nocheck(void *);
|
|
uint64_t dtrace_fuword64_nocheck(void *);
|
|
|
|
int dtrace_ustackdepth_max = 2048;
|
|
|
|
void
|
|
dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
|
|
uint32_t *intrpc)
|
|
{
|
|
int depth = 0;
|
|
register_t ebp;
|
|
struct i386_frame *frame;
|
|
vm_offset_t callpc;
|
|
pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
|
|
|
|
if (intrpc != 0)
|
|
pcstack[depth++] = (pc_t) intrpc;
|
|
|
|
aframes++;
|
|
|
|
__asm __volatile("movl %%ebp,%0" : "=r" (ebp));
|
|
|
|
frame = (struct i386_frame *)ebp;
|
|
while (depth < pcstack_limit) {
|
|
if (!INKERNEL(frame))
|
|
break;
|
|
|
|
callpc = frame->f_retaddr;
|
|
|
|
if (!INKERNEL(callpc))
|
|
break;
|
|
|
|
if (aframes > 0) {
|
|
aframes--;
|
|
if ((aframes == 0) && (caller != 0)) {
|
|
pcstack[depth++] = caller;
|
|
}
|
|
}
|
|
else {
|
|
pcstack[depth++] = callpc;
|
|
}
|
|
|
|
if (frame->f_frame <= frame ||
|
|
(vm_offset_t)frame->f_frame >= curthread->td_kstack +
|
|
curthread->td_kstack_pages * PAGE_SIZE)
|
|
break;
|
|
frame = frame->f_frame;
|
|
}
|
|
|
|
for (; depth < pcstack_limit; depth++) {
|
|
pcstack[depth] = 0;
|
|
}
|
|
}
|
|
|
|
static int
|
|
dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
|
|
uintptr_t sp)
|
|
{
|
|
#ifdef notyet
|
|
proc_t *p = curproc;
|
|
uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */
|
|
size_t s1, s2;
|
|
#endif
|
|
uintptr_t oldsp;
|
|
volatile uint16_t *flags =
|
|
(volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
|
|
int ret = 0;
|
|
|
|
ASSERT(pcstack == NULL || pcstack_limit > 0);
|
|
ASSERT(dtrace_ustackdepth_max > 0);
|
|
|
|
#ifdef notyet /* XXX signal stack. */
|
|
if (p->p_model == DATAMODEL_NATIVE) {
|
|
s1 = sizeof (struct frame) + 2 * sizeof (long);
|
|
s2 = s1 + sizeof (siginfo_t);
|
|
} else {
|
|
s1 = sizeof (struct frame32) + 3 * sizeof (int);
|
|
s2 = s1 + sizeof (siginfo32_t);
|
|
}
|
|
#endif
|
|
|
|
while (pc != 0) {
|
|
/*
|
|
* We limit the number of times we can go around this
|
|
* loop to account for a circular stack.
|
|
*/
|
|
if (ret++ >= dtrace_ustackdepth_max) {
|
|
*flags |= CPU_DTRACE_BADSTACK;
|
|
cpu_core[curcpu].cpuc_dtrace_illval = sp;
|
|
break;
|
|
}
|
|
|
|
if (pcstack != NULL) {
|
|
*pcstack++ = (uint64_t)pc;
|
|
pcstack_limit--;
|
|
if (pcstack_limit <= 0)
|
|
break;
|
|
}
|
|
|
|
if (sp == 0)
|
|
break;
|
|
|
|
oldsp = sp;
|
|
|
|
#ifdef notyet /* XXX signal stack. */
|
|
if (oldcontext == sp + s1 || oldcontext == sp + s2) {
|
|
if (p->p_model == DATAMODEL_NATIVE) {
|
|
ucontext_t *ucp = (ucontext_t *)oldcontext;
|
|
greg_t *gregs = ucp->uc_mcontext.gregs;
|
|
|
|
sp = dtrace_fulword(&gregs[REG_FP]);
|
|
pc = dtrace_fulword(&gregs[REG_PC]);
|
|
|
|
oldcontext = dtrace_fulword(&ucp->uc_link);
|
|
} else {
|
|
ucontext32_t *ucp = (ucontext32_t *)oldcontext;
|
|
greg32_t *gregs = ucp->uc_mcontext.gregs;
|
|
|
|
sp = dtrace_fuword32(&gregs[EBP]);
|
|
pc = dtrace_fuword32(&gregs[EIP]);
|
|
|
|
oldcontext = dtrace_fuword32(&ucp->uc_link);
|
|
}
|
|
} else {
|
|
if (p->p_model == DATAMODEL_NATIVE) {
|
|
struct frame *fr = (struct frame *)sp;
|
|
|
|
pc = dtrace_fulword(&fr->fr_savpc);
|
|
sp = dtrace_fulword(&fr->fr_savfp);
|
|
} else {
|
|
struct frame32 *fr = (struct frame32 *)sp;
|
|
|
|
pc = dtrace_fuword32(&fr->fr_savpc);
|
|
sp = dtrace_fuword32(&fr->fr_savfp);
|
|
}
|
|
}
|
|
#else
|
|
pc = dtrace_fuword32((void *)(sp +
|
|
offsetof(struct i386_frame, f_retaddr)));
|
|
sp = dtrace_fuword32((void *)sp);
|
|
#endif /* ! notyet */
|
|
|
|
if (sp == oldsp) {
|
|
*flags |= CPU_DTRACE_BADSTACK;
|
|
cpu_core[curcpu].cpuc_dtrace_illval = sp;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* This is totally bogus: if we faulted, we're going to clear
|
|
* the fault and break. This is to deal with the apparently
|
|
* broken Java stacks on x86.
|
|
*/
|
|
if (*flags & CPU_DTRACE_FAULT) {
|
|
*flags &= ~CPU_DTRACE_FAULT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (ret);
|
|
}
|
|
|
|
void
|
|
dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
|
|
{
|
|
proc_t *p = curproc;
|
|
struct trapframe *tf;
|
|
uintptr_t pc, sp, fp;
|
|
volatile uint16_t *flags =
|
|
(volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
|
|
int n;
|
|
|
|
if (*flags & CPU_DTRACE_FAULT)
|
|
return;
|
|
|
|
if (pcstack_limit <= 0)
|
|
return;
|
|
|
|
/*
|
|
* If there's no user context we still need to zero the stack.
|
|
*/
|
|
if (p == NULL || (tf = curthread->td_frame) == NULL)
|
|
goto zero;
|
|
|
|
*pcstack++ = (uint64_t)p->p_pid;
|
|
pcstack_limit--;
|
|
|
|
if (pcstack_limit <= 0)
|
|
return;
|
|
|
|
pc = tf->tf_eip;
|
|
fp = tf->tf_ebp;
|
|
sp = tf->tf_esp;
|
|
|
|
if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
|
|
/*
|
|
* In an entry probe. The frame pointer has not yet been
|
|
* pushed (that happens in the function prologue). The
|
|
* best approach is to add the current pc as a missing top
|
|
* of stack and back the pc up to the caller, which is stored
|
|
* at the current stack pointer address since the call
|
|
* instruction puts it there right before the branch.
|
|
*/
|
|
|
|
*pcstack++ = (uint64_t)pc;
|
|
pcstack_limit--;
|
|
if (pcstack_limit <= 0)
|
|
return;
|
|
|
|
pc = dtrace_fuword32((void *) sp);
|
|
}
|
|
|
|
n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
|
|
ASSERT(n >= 0);
|
|
ASSERT(n <= pcstack_limit);
|
|
|
|
pcstack += n;
|
|
pcstack_limit -= n;
|
|
|
|
zero:
|
|
while (pcstack_limit-- > 0)
|
|
*pcstack++ = 0;
|
|
}
|
|
|
|
int
|
|
dtrace_getustackdepth(void)
|
|
{
|
|
proc_t *p = curproc;
|
|
struct trapframe *tf;
|
|
uintptr_t pc, fp, sp;
|
|
int n = 0;
|
|
|
|
if (p == NULL || (tf = curthread->td_frame) == NULL)
|
|
return (0);
|
|
|
|
if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
|
|
return (-1);
|
|
|
|
pc = tf->tf_eip;
|
|
fp = tf->tf_ebp;
|
|
sp = tf->tf_esp;
|
|
|
|
if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
|
|
/*
|
|
* In an entry probe. The frame pointer has not yet been
|
|
* pushed (that happens in the function prologue). The
|
|
* best approach is to add the current pc as a missing top
|
|
* of stack and back the pc up to the caller, which is stored
|
|
* at the current stack pointer address since the call
|
|
* instruction puts it there right before the branch.
|
|
*/
|
|
|
|
pc = dtrace_fuword32((void *) sp);
|
|
n++;
|
|
}
|
|
|
|
n += dtrace_getustack_common(NULL, 0, pc, fp);
|
|
|
|
return (n);
|
|
}
|
|
|
|
void
|
|
dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
|
|
{
|
|
proc_t *p = curproc;
|
|
struct trapframe *tf;
|
|
uintptr_t pc, sp, fp;
|
|
volatile uint16_t *flags =
|
|
(volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
|
|
#ifdef notyet /* XXX signal stack */
|
|
uintptr_t oldcontext;
|
|
size_t s1, s2;
|
|
#endif
|
|
|
|
if (*flags & CPU_DTRACE_FAULT)
|
|
return;
|
|
|
|
if (pcstack_limit <= 0)
|
|
return;
|
|
|
|
/*
|
|
* If there's no user context we still need to zero the stack.
|
|
*/
|
|
if (p == NULL || (tf = curthread->td_frame) == NULL)
|
|
goto zero;
|
|
|
|
*pcstack++ = (uint64_t)p->p_pid;
|
|
pcstack_limit--;
|
|
|
|
if (pcstack_limit <= 0)
|
|
return;
|
|
|
|
pc = tf->tf_eip;
|
|
fp = tf->tf_ebp;
|
|
sp = tf->tf_esp;
|
|
|
|
#ifdef notyet /* XXX signal stack */
|
|
oldcontext = lwp->lwp_oldcontext;
|
|
|
|
if (p->p_model == DATAMODEL_NATIVE) {
|
|
s1 = sizeof (struct frame) + 2 * sizeof (long);
|
|
s2 = s1 + sizeof (siginfo_t);
|
|
} else {
|
|
s1 = sizeof (struct frame32) + 3 * sizeof (int);
|
|
s2 = s1 + sizeof (siginfo32_t);
|
|
}
|
|
#endif
|
|
|
|
if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
|
|
*pcstack++ = (uint64_t)pc;
|
|
*fpstack++ = 0;
|
|
pcstack_limit--;
|
|
if (pcstack_limit <= 0)
|
|
return;
|
|
|
|
pc = dtrace_fuword32((void *)sp);
|
|
}
|
|
|
|
while (pc != 0) {
|
|
*pcstack++ = (uint64_t)pc;
|
|
*fpstack++ = fp;
|
|
pcstack_limit--;
|
|
if (pcstack_limit <= 0)
|
|
break;
|
|
|
|
if (fp == 0)
|
|
break;
|
|
|
|
#ifdef notyet /* XXX signal stack */
|
|
if (oldcontext == sp + s1 || oldcontext == sp + s2) {
|
|
if (p->p_model == DATAMODEL_NATIVE) {
|
|
ucontext_t *ucp = (ucontext_t *)oldcontext;
|
|
greg_t *gregs = ucp->uc_mcontext.gregs;
|
|
|
|
sp = dtrace_fulword(&gregs[REG_FP]);
|
|
pc = dtrace_fulword(&gregs[REG_PC]);
|
|
|
|
oldcontext = dtrace_fulword(&ucp->uc_link);
|
|
} else {
|
|
ucontext_t *ucp = (ucontext_t *)oldcontext;
|
|
greg_t *gregs = ucp->uc_mcontext.gregs;
|
|
|
|
sp = dtrace_fuword32(&gregs[EBP]);
|
|
pc = dtrace_fuword32(&gregs[EIP]);
|
|
|
|
oldcontext = dtrace_fuword32(&ucp->uc_link);
|
|
}
|
|
} else
|
|
#endif /* XXX */
|
|
{
|
|
pc = dtrace_fuword32((void *)(fp +
|
|
offsetof(struct i386_frame, f_retaddr)));
|
|
fp = dtrace_fuword32((void *)fp);
|
|
}
|
|
|
|
/*
|
|
* This is totally bogus: if we faulted, we're going to clear
|
|
* the fault and break. This is to deal with the apparently
|
|
* broken Java stacks on x86.
|
|
*/
|
|
if (*flags & CPU_DTRACE_FAULT) {
|
|
*flags &= ~CPU_DTRACE_FAULT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
zero:
|
|
while (pcstack_limit-- > 0)
|
|
*pcstack++ = 0;
|
|
}
|
|
|
|
uint64_t
|
|
dtrace_getarg(int arg, int aframes)
|
|
{
|
|
struct trapframe *frame;
|
|
struct i386_frame *fp = (struct i386_frame *)dtrace_getfp();
|
|
uintptr_t *stack, val;
|
|
int i;
|
|
|
|
for (i = 1; i <= aframes; i++) {
|
|
fp = fp->f_frame;
|
|
|
|
if (P2ROUNDUP(fp->f_retaddr, 4) ==
|
|
(long)dtrace_invop_callsite) {
|
|
/*
|
|
* If we pass through the invalid op handler, we will
|
|
* use the trap frame pointer that it pushed on the
|
|
* stack as the second argument to dtrace_invop() as
|
|
* the pointer to the stack. When using this stack, we
|
|
* must skip the third argument to dtrace_invop(),
|
|
* which is included in the i386_frame.
|
|
*/
|
|
frame = (struct trapframe *)(((uintptr_t **)&fp[1])[0]);
|
|
/*
|
|
* Skip the three hardware-saved registers and the
|
|
* return address.
|
|
*/
|
|
stack = (uintptr_t *)frame->tf_isp + 4;
|
|
goto load;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* We know that we did not come through a trap to get into
|
|
* dtrace_probe() -- the provider simply called dtrace_probe()
|
|
* directly. As this is the case, we need to shift the argument
|
|
* that we're looking for: the probe ID is the first argument to
|
|
* dtrace_probe(), so the argument n will actually be found where
|
|
* one would expect to find argument (n + 1).
|
|
*/
|
|
arg++;
|
|
|
|
stack = (uintptr_t *)fp + 2;
|
|
|
|
load:
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
|
|
val = stack[arg];
|
|
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
|
|
|
|
return (val);
|
|
}
|
|
|
|
int
|
|
dtrace_getstackdepth(int aframes)
|
|
{
|
|
int depth = 0;
|
|
struct i386_frame *frame;
|
|
vm_offset_t ebp;
|
|
|
|
aframes++;
|
|
ebp = dtrace_getfp();
|
|
frame = (struct i386_frame *)ebp;
|
|
depth++;
|
|
for(;;) {
|
|
if (!INKERNEL((long) frame))
|
|
break;
|
|
if (!INKERNEL((long) frame->f_frame))
|
|
break;
|
|
depth++;
|
|
if (frame->f_frame <= frame ||
|
|
(vm_offset_t)frame->f_frame >= curthread->td_kstack +
|
|
curthread->td_kstack_pages * PAGE_SIZE)
|
|
break;
|
|
frame = frame->f_frame;
|
|
}
|
|
if (depth < aframes)
|
|
return 0;
|
|
else
|
|
return depth - aframes;
|
|
}
|
|
|
|
ulong_t
|
|
dtrace_getreg(struct trapframe *rp, uint_t reg)
|
|
{
|
|
struct pcb *pcb;
|
|
int regmap[] = { /* Order is dependent on reg.d */
|
|
REG_GS, /* 0 GS */
|
|
REG_FS, /* 1 FS */
|
|
REG_ES, /* 2 ES */
|
|
REG_DS, /* 3 DS */
|
|
REG_RDI, /* 4 EDI */
|
|
REG_RSI, /* 5 ESI */
|
|
REG_RBP, /* 6 EBP, REG_FP */
|
|
REG_RSP, /* 7 ESP */
|
|
REG_RBX, /* 8 EBX */
|
|
REG_RDX, /* 9 EDX, REG_R1 */
|
|
REG_RCX, /* 10 ECX */
|
|
REG_RAX, /* 11 EAX, REG_R0 */
|
|
REG_TRAPNO, /* 12 TRAPNO */
|
|
REG_ERR, /* 13 ERR */
|
|
REG_RIP, /* 14 EIP, REG_PC */
|
|
REG_CS, /* 15 CS */
|
|
REG_RFL, /* 16 EFL, REG_PS */
|
|
REG_RSP, /* 17 UESP, REG_SP */
|
|
REG_SS /* 18 SS */
|
|
};
|
|
|
|
if (reg > SS) {
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
|
|
return (0);
|
|
}
|
|
|
|
if (reg >= sizeof (regmap) / sizeof (int)) {
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
|
|
return (0);
|
|
}
|
|
|
|
reg = regmap[reg];
|
|
|
|
switch(reg) {
|
|
case REG_GS:
|
|
if ((pcb = curthread->td_pcb) == NULL) {
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
|
|
return (0);
|
|
}
|
|
return (pcb->pcb_gs);
|
|
case REG_FS:
|
|
return (rp->tf_fs);
|
|
case REG_ES:
|
|
return (rp->tf_es);
|
|
case REG_DS:
|
|
return (rp->tf_ds);
|
|
case REG_RDI:
|
|
return (rp->tf_edi);
|
|
case REG_RSI:
|
|
return (rp->tf_esi);
|
|
case REG_RBP:
|
|
return (rp->tf_ebp);
|
|
case REG_RSP:
|
|
return (rp->tf_isp);
|
|
case REG_RBX:
|
|
return (rp->tf_ebx);
|
|
case REG_RCX:
|
|
return (rp->tf_ecx);
|
|
case REG_RAX:
|
|
return (rp->tf_eax);
|
|
case REG_TRAPNO:
|
|
return (rp->tf_trapno);
|
|
case REG_ERR:
|
|
return (rp->tf_err);
|
|
case REG_RIP:
|
|
return (rp->tf_eip);
|
|
case REG_CS:
|
|
return (rp->tf_cs);
|
|
case REG_RFL:
|
|
return (rp->tf_eflags);
|
|
#if 0
|
|
case REG_RSP:
|
|
return (rp->tf_esp);
|
|
#endif
|
|
case REG_SS:
|
|
return (rp->tf_ss);
|
|
default:
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
static int
|
|
dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
|
|
{
|
|
ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
|
|
|
|
if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
|
|
cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
|
|
return (0);
|
|
}
|
|
|
|
return (1);
|
|
}
|
|
|
|
void
|
|
dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
|
|
volatile uint16_t *flags)
|
|
{
|
|
if (dtrace_copycheck(uaddr, kaddr, size))
|
|
dtrace_copy(uaddr, kaddr, size);
|
|
}
|
|
|
|
void
|
|
dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
|
|
volatile uint16_t *flags)
|
|
{
|
|
if (dtrace_copycheck(uaddr, kaddr, size))
|
|
dtrace_copy(kaddr, uaddr, size);
|
|
}
|
|
|
|
void
|
|
dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
|
|
volatile uint16_t *flags)
|
|
{
|
|
if (dtrace_copycheck(uaddr, kaddr, size))
|
|
dtrace_copystr(uaddr, kaddr, size, flags);
|
|
}
|
|
|
|
void
|
|
dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
|
|
volatile uint16_t *flags)
|
|
{
|
|
if (dtrace_copycheck(uaddr, kaddr, size))
|
|
dtrace_copystr(kaddr, uaddr, size, flags);
|
|
}
|
|
|
|
uint8_t
|
|
dtrace_fuword8(void *uaddr)
|
|
{
|
|
if ((uintptr_t)uaddr >= kernelbase) {
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
|
|
cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
|
|
return (0);
|
|
}
|
|
return (dtrace_fuword8_nocheck(uaddr));
|
|
}
|
|
|
|
uint16_t
|
|
dtrace_fuword16(void *uaddr)
|
|
{
|
|
if ((uintptr_t)uaddr >= kernelbase) {
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
|
|
cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
|
|
return (0);
|
|
}
|
|
return (dtrace_fuword16_nocheck(uaddr));
|
|
}
|
|
|
|
uint32_t
|
|
dtrace_fuword32(void *uaddr)
|
|
{
|
|
if ((uintptr_t)uaddr >= kernelbase) {
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
|
|
cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
|
|
return (0);
|
|
}
|
|
return (dtrace_fuword32_nocheck(uaddr));
|
|
}
|
|
|
|
uint64_t
|
|
dtrace_fuword64(void *uaddr)
|
|
{
|
|
if ((uintptr_t)uaddr >= kernelbase) {
|
|
DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
|
|
cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
|
|
return (0);
|
|
}
|
|
return (dtrace_fuword64_nocheck(uaddr));
|
|
}
|