forked from Minki/linux
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6: [SPARC32]: Use regsets in arch_ptrace(). [SPARC64]: Use regsets in arch_ptrace(). [SPARC32]: Use regsets for ELF core dumping. [SPARC64]: Use regsets for ELF core dumping. [SPARC64]: Remove unintentional ptrace debugging messages. [SPARC]: Move over to arch_ptrace(). [SPARC]: Remove PTRACE_SUN* handling. [SPARC]: Kill DEBUG_PTRACE code. [SPARC32]: Add user regset support. [SPARC64]: Add user regsets. [SPARC64]: Fix booting on non-zero cpu.
This commit is contained in:
commit
0afc2edfad
@ -1224,23 +1224,6 @@ sys_nis_syscall:
|
||||
call c_sys_nis_syscall
|
||||
mov %l5, %o7
|
||||
|
||||
.align 4
|
||||
.globl sys_ptrace
|
||||
sys_ptrace:
|
||||
call do_ptrace
|
||||
add %sp, STACKFRAME_SZ, %o0
|
||||
|
||||
ld [%curptr + TI_FLAGS], %l5
|
||||
andcc %l5, _TIF_SYSCALL_TRACE, %g0
|
||||
be 1f
|
||||
nop
|
||||
|
||||
call syscall_trace
|
||||
nop
|
||||
|
||||
1:
|
||||
RESTORE_ALL
|
||||
|
||||
.align 4
|
||||
.globl sys_execve
|
||||
sys_execve:
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ptrace.c: Sparc process tracing support.
|
||||
*
|
||||
* Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
|
||||
* Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
|
||||
*
|
||||
* Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
|
||||
* and David Mosberger.
|
||||
@ -19,234 +19,14 @@
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/regset.h>
|
||||
#include <linux/elf.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#define MAGIC_CONSTANT 0x80000000
|
||||
|
||||
|
||||
/* Returning from ptrace is a bit tricky because the syscall return
|
||||
* low level code assumes any value returned which is negative and
|
||||
* is a valid errno will mean setting the condition codes to indicate
|
||||
* an error return. This doesn't work, so we have this hook.
|
||||
*/
|
||||
static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
|
||||
{
|
||||
regs->u_regs[UREG_I0] = error;
|
||||
regs->psr |= PSR_C;
|
||||
regs->pc = regs->npc;
|
||||
regs->npc += 4;
|
||||
}
|
||||
|
||||
static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
|
||||
{
|
||||
regs->u_regs[UREG_I0] = value;
|
||||
regs->psr &= ~PSR_C;
|
||||
regs->pc = regs->npc;
|
||||
regs->npc += 4;
|
||||
}
|
||||
|
||||
static void
|
||||
pt_succ_return_linux(struct pt_regs *regs, unsigned long value, long __user *addr)
|
||||
{
|
||||
if (put_user(value, addr)) {
|
||||
pt_error_return(regs, EFAULT);
|
||||
return;
|
||||
}
|
||||
regs->u_regs[UREG_I0] = 0;
|
||||
regs->psr &= ~PSR_C;
|
||||
regs->pc = regs->npc;
|
||||
regs->npc += 4;
|
||||
}
|
||||
|
||||
static void
|
||||
pt_os_succ_return (struct pt_regs *regs, unsigned long val, long __user *addr)
|
||||
{
|
||||
if (current->personality == PER_SUNOS)
|
||||
pt_succ_return (regs, val);
|
||||
else
|
||||
pt_succ_return_linux (regs, val, addr);
|
||||
}
|
||||
|
||||
/* Fuck me gently with a chainsaw... */
|
||||
static inline void read_sunos_user(struct pt_regs *regs, unsigned long offset,
|
||||
struct task_struct *tsk, long __user *addr)
|
||||
{
|
||||
struct pt_regs *cregs = tsk->thread.kregs;
|
||||
struct thread_info *t = task_thread_info(tsk);
|
||||
int v;
|
||||
|
||||
if(offset >= 1024)
|
||||
offset -= 1024; /* whee... */
|
||||
if(offset & ((sizeof(unsigned long) - 1))) {
|
||||
pt_error_return(regs, EIO);
|
||||
return;
|
||||
}
|
||||
if(offset >= 16 && offset < 784) {
|
||||
offset -= 16; offset >>= 2;
|
||||
pt_os_succ_return(regs, *(((unsigned long *)(&t->reg_window[0]))+offset), addr);
|
||||
return;
|
||||
}
|
||||
if(offset >= 784 && offset < 832) {
|
||||
offset -= 784; offset >>= 2;
|
||||
pt_os_succ_return(regs, *(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset), addr);
|
||||
return;
|
||||
}
|
||||
switch(offset) {
|
||||
case 0:
|
||||
v = t->ksp;
|
||||
break;
|
||||
case 4:
|
||||
v = t->kpc;
|
||||
break;
|
||||
case 8:
|
||||
v = t->kpsr;
|
||||
break;
|
||||
case 12:
|
||||
v = t->uwinmask;
|
||||
break;
|
||||
case 832:
|
||||
v = t->w_saved;
|
||||
break;
|
||||
case 896:
|
||||
v = cregs->u_regs[UREG_I0];
|
||||
break;
|
||||
case 900:
|
||||
v = cregs->u_regs[UREG_I1];
|
||||
break;
|
||||
case 904:
|
||||
v = cregs->u_regs[UREG_I2];
|
||||
break;
|
||||
case 908:
|
||||
v = cregs->u_regs[UREG_I3];
|
||||
break;
|
||||
case 912:
|
||||
v = cregs->u_regs[UREG_I4];
|
||||
break;
|
||||
case 916:
|
||||
v = cregs->u_regs[UREG_I5];
|
||||
break;
|
||||
case 920:
|
||||
v = cregs->u_regs[UREG_I6];
|
||||
break;
|
||||
case 924:
|
||||
if(tsk->thread.flags & MAGIC_CONSTANT)
|
||||
v = cregs->u_regs[UREG_G1];
|
||||
else
|
||||
v = 0;
|
||||
break;
|
||||
case 940:
|
||||
v = cregs->u_regs[UREG_I0];
|
||||
break;
|
||||
case 944:
|
||||
v = cregs->u_regs[UREG_I1];
|
||||
break;
|
||||
|
||||
case 948:
|
||||
/* Isn't binary compatibility _fun_??? */
|
||||
if(cregs->psr & PSR_C)
|
||||
v = cregs->u_regs[UREG_I0] << 24;
|
||||
else
|
||||
v = 0;
|
||||
break;
|
||||
|
||||
/* Rest of them are completely unsupported. */
|
||||
default:
|
||||
printk("%s [%d]: Wants to read user offset %ld\n",
|
||||
current->comm, task_pid_nr(current), offset);
|
||||
pt_error_return(regs, EIO);
|
||||
return;
|
||||
}
|
||||
if (current->personality == PER_SUNOS)
|
||||
pt_succ_return (regs, v);
|
||||
else
|
||||
pt_succ_return_linux (regs, v, addr);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void write_sunos_user(struct pt_regs *regs, unsigned long offset,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
struct pt_regs *cregs = tsk->thread.kregs;
|
||||
struct thread_info *t = task_thread_info(tsk);
|
||||
unsigned long value = regs->u_regs[UREG_I3];
|
||||
|
||||
if(offset >= 1024)
|
||||
offset -= 1024; /* whee... */
|
||||
if(offset & ((sizeof(unsigned long) - 1)))
|
||||
goto failure;
|
||||
if(offset >= 16 && offset < 784) {
|
||||
offset -= 16; offset >>= 2;
|
||||
*(((unsigned long *)(&t->reg_window[0]))+offset) = value;
|
||||
goto success;
|
||||
}
|
||||
if(offset >= 784 && offset < 832) {
|
||||
offset -= 784; offset >>= 2;
|
||||
*(((unsigned long *)(&t->rwbuf_stkptrs[0]))+offset) = value;
|
||||
goto success;
|
||||
}
|
||||
switch(offset) {
|
||||
case 896:
|
||||
cregs->u_regs[UREG_I0] = value;
|
||||
break;
|
||||
case 900:
|
||||
cregs->u_regs[UREG_I1] = value;
|
||||
break;
|
||||
case 904:
|
||||
cregs->u_regs[UREG_I2] = value;
|
||||
break;
|
||||
case 908:
|
||||
cregs->u_regs[UREG_I3] = value;
|
||||
break;
|
||||
case 912:
|
||||
cregs->u_regs[UREG_I4] = value;
|
||||
break;
|
||||
case 916:
|
||||
cregs->u_regs[UREG_I5] = value;
|
||||
break;
|
||||
case 920:
|
||||
cregs->u_regs[UREG_I6] = value;
|
||||
break;
|
||||
case 924:
|
||||
cregs->u_regs[UREG_I7] = value;
|
||||
break;
|
||||
case 940:
|
||||
cregs->u_regs[UREG_I0] = value;
|
||||
break;
|
||||
case 944:
|
||||
cregs->u_regs[UREG_I1] = value;
|
||||
break;
|
||||
|
||||
/* Rest of them are completely unsupported or "no-touch". */
|
||||
default:
|
||||
printk("%s [%d]: Wants to write user offset %ld\n",
|
||||
current->comm, task_pid_nr(current), offset);
|
||||
goto failure;
|
||||
}
|
||||
success:
|
||||
pt_succ_return(regs, 0);
|
||||
return;
|
||||
failure:
|
||||
pt_error_return(regs, EIO);
|
||||
return;
|
||||
}
|
||||
|
||||
/* #define ALLOW_INIT_TRACING */
|
||||
/* #define DEBUG_PTRACE */
|
||||
|
||||
#ifdef DEBUG_PTRACE
|
||||
char *pt_rq [] = {
|
||||
/* 0 */ "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSR",
|
||||
/* 4 */ "POKETEXT", "POKEDATA", "POKEUSR", "CONT",
|
||||
/* 8 */ "KILL", "SINGLESTEP", "SUNATTACH", "SUNDETACH",
|
||||
/* 12 */ "GETREGS", "SETREGS", "GETFPREGS", "SETFPREGS",
|
||||
/* 16 */ "READDATA", "WRITEDATA", "READTEXT", "WRITETEXT",
|
||||
/* 20 */ "GETFPAREGS", "SETFPAREGS", "unknown", "unknown",
|
||||
/* 24 */ "SYSCALL", ""
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Called by kernel/ptrace.c when detaching..
|
||||
@ -258,150 +38,324 @@ void ptrace_disable(struct task_struct *child)
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
asmlinkage void do_ptrace(struct pt_regs *regs)
|
||||
enum sparc_regset {
|
||||
REGSET_GENERAL,
|
||||
REGSET_FP,
|
||||
};
|
||||
|
||||
static int genregs32_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
void *kbuf, void __user *ubuf)
|
||||
{
|
||||
unsigned long request = regs->u_regs[UREG_I0];
|
||||
unsigned long pid = regs->u_regs[UREG_I1];
|
||||
unsigned long addr = regs->u_regs[UREG_I2];
|
||||
unsigned long data = regs->u_regs[UREG_I3];
|
||||
unsigned long addr2 = regs->u_regs[UREG_I4];
|
||||
struct task_struct *child;
|
||||
const struct pt_regs *regs = target->thread.kregs;
|
||||
unsigned long __user *reg_window;
|
||||
unsigned long *k = kbuf;
|
||||
unsigned long __user *u = ubuf;
|
||||
unsigned long reg;
|
||||
|
||||
if (target == current)
|
||||
flush_user_windows();
|
||||
|
||||
pos /= sizeof(reg);
|
||||
count /= sizeof(reg);
|
||||
|
||||
if (kbuf) {
|
||||
for (; count > 0 && pos < 16; count--)
|
||||
*k++ = regs->u_regs[pos++];
|
||||
|
||||
reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
|
||||
for (; count > 0 && pos < 32; count--) {
|
||||
if (get_user(*k++, ®_window[pos++]))
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
for (; count > 0 && pos < 16; count--) {
|
||||
if (put_user(regs->u_regs[pos++], u++))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
|
||||
for (; count > 0 && pos < 32; count--) {
|
||||
if (get_user(reg, ®_window[pos++]) ||
|
||||
put_user(reg, u++))
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
while (count > 0) {
|
||||
switch (pos) {
|
||||
case 32: /* PSR */
|
||||
reg = regs->psr;
|
||||
break;
|
||||
case 33: /* PC */
|
||||
reg = regs->pc;
|
||||
break;
|
||||
case 34: /* NPC */
|
||||
reg = regs->npc;
|
||||
break;
|
||||
case 35: /* Y */
|
||||
reg = regs->y;
|
||||
break;
|
||||
case 36: /* WIM */
|
||||
case 37: /* TBR */
|
||||
reg = 0;
|
||||
break;
|
||||
default:
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (kbuf)
|
||||
*k++ = reg;
|
||||
else if (put_user(reg, u++))
|
||||
return -EFAULT;
|
||||
pos++;
|
||||
count--;
|
||||
}
|
||||
finish:
|
||||
pos *= sizeof(reg);
|
||||
count *= sizeof(reg);
|
||||
|
||||
return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
|
||||
38 * sizeof(reg), -1);
|
||||
}
|
||||
|
||||
static int genregs32_set(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
struct pt_regs *regs = target->thread.kregs;
|
||||
unsigned long __user *reg_window;
|
||||
const unsigned long *k = kbuf;
|
||||
const unsigned long __user *u = ubuf;
|
||||
unsigned long reg;
|
||||
|
||||
if (target == current)
|
||||
flush_user_windows();
|
||||
|
||||
pos /= sizeof(reg);
|
||||
count /= sizeof(reg);
|
||||
|
||||
if (kbuf) {
|
||||
for (; count > 0 && pos < 16; count--)
|
||||
regs->u_regs[pos++] = *k++;
|
||||
|
||||
reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
|
||||
for (; count > 0 && pos < 32; count--) {
|
||||
if (put_user(*k++, ®_window[pos++]))
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
for (; count > 0 && pos < 16; count--) {
|
||||
if (get_user(reg, u++))
|
||||
return -EFAULT;
|
||||
regs->u_regs[pos++] = reg;
|
||||
}
|
||||
|
||||
reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
|
||||
for (; count > 0 && pos < 32; count--) {
|
||||
if (get_user(reg, u++) ||
|
||||
put_user(reg, ®_window[pos++]))
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
while (count > 0) {
|
||||
unsigned long psr;
|
||||
|
||||
if (kbuf)
|
||||
reg = *k++;
|
||||
else if (get_user(reg, u++))
|
||||
return -EFAULT;
|
||||
|
||||
switch (pos) {
|
||||
case 32: /* PSR */
|
||||
psr = regs->psr;
|
||||
psr &= ~PSR_ICC;
|
||||
psr |= (reg & PSR_ICC);
|
||||
regs->psr = psr;
|
||||
break;
|
||||
case 33: /* PC */
|
||||
regs->pc = reg;
|
||||
break;
|
||||
case 34: /* NPC */
|
||||
regs->npc = reg;
|
||||
break;
|
||||
case 35: /* Y */
|
||||
regs->y = reg;
|
||||
break;
|
||||
case 36: /* WIM */
|
||||
case 37: /* TBR */
|
||||
break;
|
||||
default:
|
||||
goto finish;
|
||||
}
|
||||
|
||||
pos++;
|
||||
count--;
|
||||
}
|
||||
finish:
|
||||
pos *= sizeof(reg);
|
||||
count *= sizeof(reg);
|
||||
|
||||
return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
|
||||
38 * sizeof(reg), -1);
|
||||
}
|
||||
|
||||
static int fpregs32_get(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
void *kbuf, void __user *ubuf)
|
||||
{
|
||||
const unsigned long *fpregs = target->thread.float_regs;
|
||||
int ret = 0;
|
||||
|
||||
#if 0
|
||||
if (target == current)
|
||||
save_and_clear_fpu();
|
||||
#endif
|
||||
|
||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
fpregs,
|
||||
0, 32 * sizeof(u32));
|
||||
|
||||
if (!ret)
|
||||
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
|
||||
32 * sizeof(u32),
|
||||
33 * sizeof(u32));
|
||||
if (!ret)
|
||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.fsr,
|
||||
33 * sizeof(u32),
|
||||
34 * sizeof(u32));
|
||||
|
||||
if (!ret) {
|
||||
unsigned long val;
|
||||
|
||||
val = (1 << 8) | (8 << 16);
|
||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||
&val,
|
||||
34 * sizeof(u32),
|
||||
35 * sizeof(u32));
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
|
||||
35 * sizeof(u32), -1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fpregs32_set(struct task_struct *target,
|
||||
const struct user_regset *regset,
|
||||
unsigned int pos, unsigned int count,
|
||||
const void *kbuf, const void __user *ubuf)
|
||||
{
|
||||
unsigned long *fpregs = target->thread.float_regs;
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
#ifdef DEBUG_PTRACE
|
||||
{
|
||||
char *s;
|
||||
|
||||
if ((request >= 0) && (request <= 24))
|
||||
s = pt_rq [request];
|
||||
else
|
||||
s = "unknown";
|
||||
|
||||
if (request == PTRACE_POKEDATA && data == 0x91d02001){
|
||||
printk ("do_ptrace: breakpoint pid=%d, addr=%08lx addr2=%08lx\n",
|
||||
pid, addr, addr2);
|
||||
} else
|
||||
printk("do_ptrace: rq=%s(%d) pid=%d addr=%08lx data=%08lx addr2=%08lx\n",
|
||||
s, (int) request, (int) pid, addr, data, addr2);
|
||||
}
|
||||
#if 0
|
||||
if (target == current)
|
||||
save_and_clear_fpu();
|
||||
#endif
|
||||
|
||||
if (request == PTRACE_TRACEME) {
|
||||
ret = ptrace_traceme();
|
||||
if (ret < 0)
|
||||
pt_error_return(regs, -ret);
|
||||
else
|
||||
pt_succ_return(regs, 0);
|
||||
goto out;
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
fpregs,
|
||||
0, 32 * sizeof(u32));
|
||||
if (!ret)
|
||||
user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
|
||||
32 * sizeof(u32),
|
||||
33 * sizeof(u32));
|
||||
if (!ret && count > 0) {
|
||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||
&target->thread.fsr,
|
||||
33 * sizeof(u32),
|
||||
34 * sizeof(u32));
|
||||
}
|
||||
|
||||
child = ptrace_get_task_struct(pid);
|
||||
if (IS_ERR(child)) {
|
||||
ret = PTR_ERR(child);
|
||||
pt_error_return(regs, -ret);
|
||||
goto out;
|
||||
}
|
||||
if (!ret)
|
||||
ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
|
||||
34 * sizeof(u32), -1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
|
||||
|| (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
|
||||
if (ptrace_attach(child)) {
|
||||
pt_error_return(regs, EPERM);
|
||||
goto out_tsk;
|
||||
}
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
}
|
||||
static const struct user_regset sparc32_regsets[] = {
|
||||
/* Format is:
|
||||
* G0 --> G7
|
||||
* O0 --> O7
|
||||
* L0 --> L7
|
||||
* I0 --> I7
|
||||
* PSR, PC, nPC, Y, WIM, TBR
|
||||
*/
|
||||
[REGSET_GENERAL] = {
|
||||
.core_note_type = NT_PRSTATUS,
|
||||
.n = 38 * sizeof(u32),
|
||||
.size = sizeof(u32), .align = sizeof(u32),
|
||||
.get = genregs32_get, .set = genregs32_set
|
||||
},
|
||||
/* Format is:
|
||||
* F0 --> F31
|
||||
* empty 32-bit word
|
||||
* FSR (32--bit word)
|
||||
* FPU QUEUE COUNT (8-bit char)
|
||||
* FPU QUEUE ENTRYSIZE (8-bit char)
|
||||
* FPU ENABLED (8-bit char)
|
||||
* empty 8-bit char
|
||||
* FPU QUEUE (64 32-bit ints)
|
||||
*/
|
||||
[REGSET_FP] = {
|
||||
.core_note_type = NT_PRFPREG,
|
||||
.n = 99 * sizeof(u32),
|
||||
.size = sizeof(u32), .align = sizeof(u32),
|
||||
.get = fpregs32_get, .set = fpregs32_set
|
||||
},
|
||||
};
|
||||
|
||||
ret = ptrace_check_attach(child, request == PTRACE_KILL);
|
||||
if (ret < 0) {
|
||||
pt_error_return(regs, -ret);
|
||||
goto out_tsk;
|
||||
}
|
||||
static const struct user_regset_view user_sparc32_view = {
|
||||
.name = "sparc", .e_machine = EM_SPARC,
|
||||
.regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
|
||||
};
|
||||
|
||||
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
|
||||
{
|
||||
return &user_sparc32_view;
|
||||
}
|
||||
|
||||
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||
{
|
||||
unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
|
||||
const struct user_regset_view *view;
|
||||
int ret;
|
||||
|
||||
view = task_user_regset_view(child);
|
||||
|
||||
switch(request) {
|
||||
case PTRACE_PEEKTEXT: /* read word at location addr. */
|
||||
case PTRACE_PEEKDATA: {
|
||||
unsigned long tmp;
|
||||
|
||||
if (access_process_vm(child, addr,
|
||||
&tmp, sizeof(tmp), 0) == sizeof(tmp))
|
||||
pt_os_succ_return(regs, tmp, (long __user *)data);
|
||||
else
|
||||
pt_error_return(regs, EIO);
|
||||
goto out_tsk;
|
||||
}
|
||||
|
||||
case PTRACE_PEEKUSR:
|
||||
read_sunos_user(regs, addr, child, (long __user *) data);
|
||||
goto out_tsk;
|
||||
|
||||
case PTRACE_POKEUSR:
|
||||
write_sunos_user(regs, addr, child);
|
||||
goto out_tsk;
|
||||
|
||||
case PTRACE_POKETEXT: /* write the word at location addr. */
|
||||
case PTRACE_POKEDATA: {
|
||||
if (access_process_vm(child, addr,
|
||||
&data, sizeof(data), 1) == sizeof(data))
|
||||
pt_succ_return(regs, 0);
|
||||
else
|
||||
pt_error_return(regs, EIO);
|
||||
goto out_tsk;
|
||||
}
|
||||
|
||||
case PTRACE_GETREGS: {
|
||||
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
|
||||
struct pt_regs *cregs = child->thread.kregs;
|
||||
int rval;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) {
|
||||
rval = -EFAULT;
|
||||
pt_error_return(regs, -rval);
|
||||
goto out_tsk;
|
||||
}
|
||||
__put_user(cregs->psr, (&pregs->psr));
|
||||
__put_user(cregs->pc, (&pregs->pc));
|
||||
__put_user(cregs->npc, (&pregs->npc));
|
||||
__put_user(cregs->y, (&pregs->y));
|
||||
for(rval = 1; rval < 16; rval++)
|
||||
__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]));
|
||||
pt_succ_return(regs, 0);
|
||||
#ifdef DEBUG_PTRACE
|
||||
printk ("PC=%x nPC=%x o7=%x\n", cregs->pc, cregs->npc, cregs->u_regs [15]);
|
||||
#endif
|
||||
goto out_tsk;
|
||||
ret = copy_regset_to_user(child, view, REGSET_GENERAL,
|
||||
32 * sizeof(u32),
|
||||
4 * sizeof(u32),
|
||||
&pregs->psr);
|
||||
if (!ret)
|
||||
copy_regset_to_user(child, view, REGSET_GENERAL,
|
||||
1 * sizeof(u32),
|
||||
15 * sizeof(u32),
|
||||
&pregs->u_regs[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
case PTRACE_SETREGS: {
|
||||
struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
|
||||
struct pt_regs *cregs = child->thread.kregs;
|
||||
unsigned long psr, pc, npc, y;
|
||||
int i;
|
||||
|
||||
/* Must be careful, tracing process can only set certain
|
||||
* bits in the psr.
|
||||
*/
|
||||
if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) {
|
||||
pt_error_return(regs, EFAULT);
|
||||
goto out_tsk;
|
||||
}
|
||||
__get_user(psr, (&pregs->psr));
|
||||
__get_user(pc, (&pregs->pc));
|
||||
__get_user(npc, (&pregs->npc));
|
||||
__get_user(y, (&pregs->y));
|
||||
psr &= PSR_ICC;
|
||||
cregs->psr &= ~PSR_ICC;
|
||||
cregs->psr |= psr;
|
||||
if (!((pc | npc) & 3)) {
|
||||
cregs->pc = pc;
|
||||
cregs->npc =npc;
|
||||
}
|
||||
cregs->y = y;
|
||||
for(i = 1; i < 16; i++)
|
||||
__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]));
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
ret = copy_regset_from_user(child, view, REGSET_GENERAL,
|
||||
32 * sizeof(u32),
|
||||
4 * sizeof(u32),
|
||||
&pregs->psr);
|
||||
if (!ret)
|
||||
copy_regset_from_user(child, view, REGSET_GENERAL,
|
||||
1 * sizeof(u32),
|
||||
15 * sizeof(u32),
|
||||
&pregs->u_regs[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
case PTRACE_GETFPREGS: {
|
||||
@ -417,26 +371,25 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
|
||||
} fpq[16];
|
||||
};
|
||||
struct fps __user *fps = (struct fps __user *) addr;
|
||||
int i;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) {
|
||||
i = -EFAULT;
|
||||
pt_error_return(regs, -i);
|
||||
goto out_tsk;
|
||||
ret = copy_regset_to_user(child, view, REGSET_FP,
|
||||
0 * sizeof(u32),
|
||||
32 * sizeof(u32),
|
||||
&fps->regs[0]);
|
||||
if (!ret)
|
||||
ret = copy_regset_to_user(child, view, REGSET_FP,
|
||||
33 * sizeof(u32),
|
||||
1 * sizeof(u32),
|
||||
&fps->fsr);
|
||||
|
||||
if (!ret) {
|
||||
if (__put_user(0, &fps->fpqd) ||
|
||||
__put_user(0, &fps->flags) ||
|
||||
__put_user(0, &fps->extra) ||
|
||||
clear_user(fps->fpq, sizeof(fps->fpq)))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
for(i = 0; i < 32; i++)
|
||||
__put_user(child->thread.float_regs[i], (&fps->regs[i]));
|
||||
__put_user(child->thread.fsr, (&fps->fsr));
|
||||
__put_user(child->thread.fpqdepth, (&fps->fpqd));
|
||||
__put_user(0, (&fps->flags));
|
||||
__put_user(0, (&fps->extra));
|
||||
for(i = 0; i < 16; i++) {
|
||||
__put_user(child->thread.fpqueue[i].insn_addr,
|
||||
(&fps->fpq[i].insnaddr));
|
||||
__put_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
|
||||
}
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
break;
|
||||
}
|
||||
|
||||
case PTRACE_SETFPREGS: {
|
||||
@ -452,137 +405,55 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
|
||||
} fpq[16];
|
||||
};
|
||||
struct fps __user *fps = (struct fps __user *) addr;
|
||||
int i;
|
||||
|
||||
if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) {
|
||||
i = -EFAULT;
|
||||
pt_error_return(regs, -i);
|
||||
goto out_tsk;
|
||||
}
|
||||
copy_from_user(&child->thread.float_regs[0], &fps->regs[0], (32 * sizeof(unsigned long)));
|
||||
__get_user(child->thread.fsr, (&fps->fsr));
|
||||
__get_user(child->thread.fpqdepth, (&fps->fpqd));
|
||||
for(i = 0; i < 16; i++) {
|
||||
__get_user(child->thread.fpqueue[i].insn_addr,
|
||||
(&fps->fpq[i].insnaddr));
|
||||
__get_user(child->thread.fpqueue[i].insn, (&fps->fpq[i].insn));
|
||||
}
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
ret = copy_regset_from_user(child, view, REGSET_FP,
|
||||
0 * sizeof(u32),
|
||||
32 * sizeof(u32),
|
||||
&fps->regs[0]);
|
||||
if (!ret)
|
||||
ret = copy_regset_from_user(child, view, REGSET_FP,
|
||||
33 * sizeof(u32),
|
||||
1 * sizeof(u32),
|
||||
&fps->fsr);
|
||||
break;
|
||||
}
|
||||
|
||||
case PTRACE_READTEXT:
|
||||
case PTRACE_READDATA: {
|
||||
int res = ptrace_readdata(child, addr,
|
||||
(void __user *) addr2, data);
|
||||
case PTRACE_READDATA:
|
||||
ret = ptrace_readdata(child, addr,
|
||||
(void __user *) addr2, data);
|
||||
|
||||
if (res == data) {
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
}
|
||||
/* Partial read is an IO failure */
|
||||
if (res >= 0)
|
||||
res = -EIO;
|
||||
pt_error_return(regs, -res);
|
||||
goto out_tsk;
|
||||
}
|
||||
if (ret == data)
|
||||
ret = 0;
|
||||
else if (ret >= 0)
|
||||
ret = -EIO;
|
||||
break;
|
||||
|
||||
case PTRACE_WRITETEXT:
|
||||
case PTRACE_WRITEDATA: {
|
||||
int res = ptrace_writedata(child, (void __user *) addr2,
|
||||
addr, data);
|
||||
case PTRACE_WRITEDATA:
|
||||
ret = ptrace_writedata(child, (void __user *) addr2,
|
||||
addr, data);
|
||||
|
||||
if (res == data) {
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
}
|
||||
/* Partial write is an IO failure */
|
||||
if (res >= 0)
|
||||
res = -EIO;
|
||||
pt_error_return(regs, -res);
|
||||
goto out_tsk;
|
||||
if (ret == data)
|
||||
ret = 0;
|
||||
else if (ret >= 0)
|
||||
ret = -EIO;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = ptrace_request(child, request, addr, data);
|
||||
break;
|
||||
}
|
||||
|
||||
case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
|
||||
addr = 1;
|
||||
|
||||
case PTRACE_CONT: { /* restart after signal. */
|
||||
if (!valid_signal(data)) {
|
||||
pt_error_return(regs, EIO);
|
||||
goto out_tsk;
|
||||
}
|
||||
|
||||
if (request == PTRACE_SYSCALL)
|
||||
set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||
else
|
||||
clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
|
||||
|
||||
child->exit_code = data;
|
||||
#ifdef DEBUG_PTRACE
|
||||
printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n",
|
||||
child->comm, child->pid, child->exit_code,
|
||||
child->thread.kregs->pc,
|
||||
child->thread.kregs->npc);
|
||||
#endif
|
||||
wake_up_process(child);
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
}
|
||||
|
||||
/*
|
||||
* make the child exit. Best I can do is send it a sigkill.
|
||||
* perhaps it should be put in the status that it wants to
|
||||
* exit.
|
||||
*/
|
||||
case PTRACE_KILL: {
|
||||
if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
}
|
||||
wake_up_process(child);
|
||||
child->exit_code = SIGKILL;
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
}
|
||||
|
||||
case PTRACE_SUNDETACH: { /* detach a process that was attached. */
|
||||
int err = ptrace_detach(child, data);
|
||||
if (err) {
|
||||
pt_error_return(regs, EIO);
|
||||
goto out_tsk;
|
||||
}
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
}
|
||||
|
||||
/* PTRACE_DUMPCORE unsupported... */
|
||||
|
||||
default: {
|
||||
int err = ptrace_request(child, request, addr, data);
|
||||
if (err)
|
||||
pt_error_return(regs, -err);
|
||||
else
|
||||
pt_succ_return(regs, 0);
|
||||
goto out_tsk;
|
||||
}
|
||||
}
|
||||
out_tsk:
|
||||
if (child)
|
||||
put_task_struct(child);
|
||||
out:
|
||||
unlock_kernel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage void syscall_trace(void)
|
||||
{
|
||||
#ifdef DEBUG_PTRACE
|
||||
printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
|
||||
#endif
|
||||
if (!test_thread_flag(TIF_SYSCALL_TRACE))
|
||||
return;
|
||||
if (!(current->ptrace & PT_PTRACED))
|
||||
return;
|
||||
current->thread.flags ^= MAGIC_CONSTANT;
|
||||
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
|
||||
? 0x80 : 0));
|
||||
/*
|
||||
@ -590,10 +461,6 @@ asmlinkage void syscall_trace(void)
|
||||
* for normal use. strace only continues with a signal if the
|
||||
* stopping signal is not SIGTRAP. -brl
|
||||
*/
|
||||
#ifdef DEBUG_PTRACE
|
||||
printk("%s [%d]: syscall_trace exit= %x\n", current->comm,
|
||||
current->pid, current->exit_code);
|
||||
#endif
|
||||
if (current->exit_code) {
|
||||
send_sig (current->exit_code, current, 1);
|
||||
current->exit_code = 0;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra.
|
||||
*
|
||||
* Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@davemloft.net)
|
||||
* Copyright (C) 1995, 1996, 1997, 1998, 2008 David S. Miller (davem@davemloft.net)
|
||||
* Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
|
||||
*/
|
||||
|
||||
@ -9,13 +9,6 @@
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ELF_DATA ELFDATA2MSB;
|
||||
|
||||
/* For the most part we present code dumps in the format
|
||||
* Solaris does.
|
||||
*/
|
||||
typedef unsigned int elf_greg_t;
|
||||
#define ELF_NGREG 38
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
|
||||
/* Format is:
|
||||
* G0 --> G7
|
||||
* O0 --> O7
|
||||
@ -23,25 +16,9 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
* I0 --> I7
|
||||
* PSR, PC, nPC, Y, WIM, TBR
|
||||
*/
|
||||
#include <asm/psrcompat.h>
|
||||
#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \
|
||||
do { unsigned int *dest = &(__elf_regs[0]); \
|
||||
struct pt_regs *src = (__pt_regs); \
|
||||
unsigned int __user *sp; \
|
||||
int i; \
|
||||
for(i = 0; i < 16; i++) \
|
||||
dest[i] = (unsigned int) src->u_regs[i];\
|
||||
/* Don't try this at home kids... */ \
|
||||
sp = (unsigned int __user *) (src->u_regs[14] & \
|
||||
0x00000000fffffffc); \
|
||||
for(i = 0; i < 16; i++) \
|
||||
__get_user(dest[i+16], &sp[i]); \
|
||||
dest[32] = tstate_to_psr(src->tstate); \
|
||||
dest[33] = (unsigned int) src->tpc; \
|
||||
dest[34] = (unsigned int) src->tnpc; \
|
||||
dest[35] = src->y; \
|
||||
dest[36] = dest[37] = 0; /* XXX */ \
|
||||
} while(0);
|
||||
typedef unsigned int elf_greg_t;
|
||||
#define ELF_NGREG 38
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
|
@ -1477,10 +1477,6 @@ sys32_rt_sigreturn:
|
||||
add %o7, 1f-.-4, %o7
|
||||
nop
|
||||
#endif
|
||||
sys_ptrace: add %sp, PTREGS_OFF, %o0
|
||||
call do_ptrace
|
||||
add %o7, 1f-.-4, %o7
|
||||
nop
|
||||
.align 32
|
||||
1: ldx [%curptr + TI_FLAGS], %l5
|
||||
andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
|
||||
|
@ -632,11 +632,36 @@ tlb_fixup_done:
|
||||
/* Not reached... */
|
||||
|
||||
1:
|
||||
/* If we boot on a non-zero cpu, all of the per-cpu
|
||||
* variable references we make before setting up the
|
||||
* per-cpu areas will use a bogus offset. Put a
|
||||
* compensating factor into __per_cpu_base to handle
|
||||
* this cleanly.
|
||||
*
|
||||
* What the per-cpu code calculates is:
|
||||
*
|
||||
* __per_cpu_base + (cpu << __per_cpu_shift)
|
||||
*
|
||||
* These two variables are zero initially, so to
|
||||
* make it all cancel out to zero we need to put
|
||||
* "0 - (cpu << 0)" into __per_cpu_base so that the
|
||||
* above formula evaluates to zero.
|
||||
*
|
||||
* We cannot even perform a printk() until this stuff
|
||||
* is setup as that calls cpu_clock() which uses
|
||||
* per-cpu variables.
|
||||
*/
|
||||
sub %g0, %o0, %o1
|
||||
sethi %hi(__per_cpu_base), %o2
|
||||
stx %o1, [%o2 + %lo(__per_cpu_base)]
|
||||
#else
|
||||
mov 0, %o0
|
||||
#endif
|
||||
sth %o0, [%g6 + TI_CPU]
|
||||
|
||||
call prom_init_report
|
||||
nop
|
||||
|
||||
/* Off we go.... */
|
||||
call start_kernel
|
||||
nop
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -48,7 +48,10 @@ void __init prom_init(void *cif_handler, void *cif_stack)
|
||||
prom_getstring(node, "version", prom_version, sizeof(prom_version));
|
||||
|
||||
prom_printf("\n");
|
||||
}
|
||||
|
||||
void __init prom_init_report(void)
|
||||
{
|
||||
printk("PROMLIB: Sun IEEE Boot Prom '%s'\n", prom_version);
|
||||
printk("PROMLIB: Root node compatible: %s\n", prom_root_compatible);
|
||||
}
|
||||
|
@ -65,8 +65,14 @@
|
||||
#define HWCAP_SPARC_V9 16
|
||||
#define HWCAP_SPARC_ULTRA3 32
|
||||
|
||||
/* For the most part we present code dumps in the format
|
||||
* Solaris does.
|
||||
#define CORE_DUMP_USE_REGSET
|
||||
|
||||
/* Format is:
|
||||
* G0 --> G7
|
||||
* O0 --> O7
|
||||
* L0 --> L7
|
||||
* I0 --> I7
|
||||
* PSR, PC, nPC, Y, WIM, TBR
|
||||
*/
|
||||
typedef unsigned long elf_greg_t;
|
||||
#define ELF_NGREG 38
|
||||
@ -86,34 +92,6 @@ typedef struct {
|
||||
} elf_fpregset_t;
|
||||
|
||||
#include <asm/mbus.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
/* Format is:
|
||||
* G0 --> G7
|
||||
* O0 --> O7
|
||||
* L0 --> L7
|
||||
* I0 --> I7
|
||||
* PSR, PC, nPC, Y, WIM, TBR
|
||||
*/
|
||||
#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \
|
||||
do { unsigned long *dest = &(__elf_regs[0]); \
|
||||
struct pt_regs *src = (__pt_regs); \
|
||||
unsigned long __user *sp; \
|
||||
memcpy(&dest[0], &src->u_regs[0], \
|
||||
sizeof(unsigned long) * 16); \
|
||||
/* Don't try this at home kids... */ \
|
||||
sp = (unsigned long __user *) src->u_regs[14]; \
|
||||
copy_from_user(&dest[16], sp, \
|
||||
sizeof(unsigned long) * 16); \
|
||||
dest[32] = src->psr; \
|
||||
dest[33] = src->pc; \
|
||||
dest[34] = src->npc; \
|
||||
dest[35] = src->y; \
|
||||
dest[36] = dest[37] = 0; /* XXX */ \
|
||||
} while(0); /* Janitors: Don't touch this semicolon. */
|
||||
|
||||
#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \
|
||||
({ ELF_CORE_COPY_REGS((*(__elf_regs)), (__tsk)->thread.kregs); 1; })
|
||||
|
||||
/*
|
||||
* This is used to ensure we don't load something for the wrong architecture.
|
||||
|
@ -61,8 +61,6 @@ struct sparc_stackf {
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define __ARCH_SYS_PTRACE 1
|
||||
|
||||
#define user_mode(regs) (!((regs)->psr & PSR_PS))
|
||||
#define instruction_pointer(regs) ((regs)->pc)
|
||||
unsigned long profile_pc(struct pt_regs *);
|
||||
@ -151,8 +149,6 @@ extern void show_regs(struct pt_regs *);
|
||||
#define SF_XXARG 0x5c
|
||||
|
||||
/* Stuff for the ptrace system call */
|
||||
#define PTRACE_SUNATTACH 10
|
||||
#define PTRACE_SUNDETACH 11
|
||||
#define PTRACE_GETREGS 12
|
||||
#define PTRACE_SETREGS 13
|
||||
#define PTRACE_GETFPREGS 14
|
||||
@ -164,7 +160,4 @@ extern void show_regs(struct pt_regs *);
|
||||
#define PTRACE_GETFPAREGS 20
|
||||
#define PTRACE_SETFPAREGS 21
|
||||
|
||||
#define PTRACE_GETUCODE 29 /* stupid bsd-ism */
|
||||
|
||||
|
||||
#endif /* !(_SPARC_PTRACE_H) */
|
||||
|
@ -70,6 +70,8 @@
|
||||
#define HWCAP_SPARC_BLKINIT 64
|
||||
#define HWCAP_SPARC_N2 128
|
||||
|
||||
#define CORE_DUMP_USE_REGSET
|
||||
|
||||
/*
|
||||
* These are used to set parameters in the core dumps.
|
||||
*/
|
||||
@ -78,10 +80,6 @@
|
||||
#define ELF_CLASS ELFCLASS64
|
||||
#define ELF_DATA ELFDATA2MSB
|
||||
|
||||
typedef unsigned long elf_greg_t;
|
||||
|
||||
#define ELF_NGREG 36
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
/* Format of 64-bit elf_gregset_t is:
|
||||
* G0 --> G7
|
||||
* O0 --> O7
|
||||
@ -92,24 +90,9 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
* TNPC
|
||||
* Y
|
||||
*/
|
||||
#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs) \
|
||||
do { unsigned long *dest = &(__elf_regs[0]); \
|
||||
struct pt_regs *src = (__pt_regs); \
|
||||
unsigned long __user *sp; \
|
||||
int i; \
|
||||
for(i = 0; i < 16; i++) \
|
||||
dest[i] = src->u_regs[i]; \
|
||||
/* Don't try this at home kids... */ \
|
||||
sp = (unsigned long __user *) \
|
||||
((src->u_regs[14] + STACK_BIAS) \
|
||||
& 0xfffffffffffffff8UL); \
|
||||
for(i = 0; i < 16; i++) \
|
||||
__get_user(dest[i+16], &sp[i]); \
|
||||
dest[32] = src->tstate; \
|
||||
dest[33] = src->tpc; \
|
||||
dest[34] = src->tnpc; \
|
||||
dest[35] = src->y; \
|
||||
} while (0);
|
||||
typedef unsigned long elf_greg_t;
|
||||
#define ELF_NGREG 36
|
||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||
|
||||
typedef struct {
|
||||
unsigned long pr_regs[32];
|
||||
@ -119,9 +102,6 @@ typedef struct {
|
||||
} elf_fpregset_t;
|
||||
#endif
|
||||
|
||||
#define ELF_CORE_COPY_TASK_REGS(__tsk, __elf_regs) \
|
||||
({ ELF_CORE_COPY_REGS((*(__elf_regs)), task_pt_regs(__tsk)); 1; })
|
||||
|
||||
/*
|
||||
* This is used to ensure we don't load something for the wrong architecture.
|
||||
*/
|
||||
|
@ -95,8 +95,6 @@ struct sparc_trapf {
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define __ARCH_SYS_PTRACE 1
|
||||
|
||||
#define force_successful_syscall_return() \
|
||||
do { current_thread_info()->syscall_noerror = 1; \
|
||||
} while (0)
|
||||
@ -261,8 +259,6 @@ extern void show_regs(struct pt_regs *);
|
||||
#define SF_XXARG 0x5c
|
||||
|
||||
/* Stuff for the ptrace system call */
|
||||
#define PTRACE_SUNATTACH 10
|
||||
#define PTRACE_SUNDETACH 11
|
||||
#define PTRACE_GETREGS 12
|
||||
#define PTRACE_SETREGS 13
|
||||
#define PTRACE_GETFPREGS 14
|
||||
@ -284,18 +280,4 @@ extern void show_regs(struct pt_regs *);
|
||||
#define PTRACE_GETFPREGS64 25
|
||||
#define PTRACE_SETFPREGS64 26
|
||||
|
||||
#define PTRACE_GETUCODE 29 /* stupid bsd-ism */
|
||||
|
||||
/* These are for 32-bit processes debugging 64-bit ones.
|
||||
* Here addr and addr2 are passed in %g2 and %g3 respectively.
|
||||
*/
|
||||
#define PTRACE_PEEKTEXT64 (30 + PTRACE_PEEKTEXT)
|
||||
#define PTRACE_POKETEXT64 (30 + PTRACE_POKETEXT)
|
||||
#define PTRACE_PEEKDATA64 (30 + PTRACE_PEEKDATA)
|
||||
#define PTRACE_POKEDATA64 (30 + PTRACE_POKEDATA)
|
||||
#define PTRACE_READDATA64 (30 + PTRACE_READDATA)
|
||||
#define PTRACE_WRITEDATA64 (30 + PTRACE_WRITEDATA)
|
||||
#define PTRACE_READTEXT64 (30 + PTRACE_READTEXT)
|
||||
#define PTRACE_WRITETEXT64 (30 + PTRACE_WRITETEXT)
|
||||
|
||||
#endif /* !(_SPARC64_PTRACE_H) */
|
||||
|
Loading…
Reference in New Issue
Block a user