/* * linux/arch/m68k/kernel/ptrace.c * * Copyright (C) 1994 by Hamish Macdonald * Taken from linux/kernel/ptrace.c and modified for M680x0. * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of * this archive for more details.
*/
/* Find the stack offset for a register, relative to thread.esp0. */ #define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg) #define SW_REG(reg) ((long)&((struct switch_stack *)0)->reg \
- sizeof(struct switch_stack)) /* Mapping from PT_xxx to the stack offset at which the register is saved. Notice that usp has no stack-slot and needs to be treated
specially (see get_reg/put_reg below). */ staticconstint regoff[] = {
[0] = PT_REG(d1),
[1] = PT_REG(d2),
[2] = PT_REG(d3),
[3] = PT_REG(d4),
[4] = PT_REG(d5),
[5] = SW_REG(d6),
[6] = SW_REG(d7),
[7] = PT_REG(a0),
[8] = PT_REG(a1),
[9] = PT_REG(a2),
[10] = SW_REG(a3),
[11] = SW_REG(a4),
[12] = SW_REG(a5),
[13] = SW_REG(a6),
[14] = PT_REG(d0),
[15] = -1,
[16] = PT_REG(orig_d0),
[17] = PT_REG(sr),
[18] = PT_REG(pc),
};
/* * Get contents of register REGNO in task TASK.
*/ staticinlinelong get_reg(struct task_struct *task, int regno)
{ unsignedlong *addr;
if (regno == PT_USP)
addr = &task->thread.usp; elseif (regno < ARRAY_SIZE(regoff))
addr = (unsignedlong *)(task->thread.esp0 + regoff[regno]); else return 0; /* Need to take stkadj into account. */ if (regno == PT_SR || regno == PT_PC) { long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
addr = (unsignedlong *) ((unsignedlong)addr + stkadj); /* The sr is actually a 16 bit register. */ if (regno == PT_SR) return *(unsignedshort *)addr;
} return *addr;
}
/* * Write contents of register REGNO in task TASK.
*/ staticinlineint put_reg(struct task_struct *task, int regno, unsignedlong data)
{ unsignedlong *addr;
if (regno == PT_USP)
addr = &task->thread.usp; elseif (regno < ARRAY_SIZE(regoff))
addr = (unsignedlong *)(task->thread.esp0 + regoff[regno]); else return -1; /* Need to take stkadj into account. */ if (regno == PT_SR || regno == PT_PC) { long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
addr = (unsignedlong *) ((unsignedlong)addr + stkadj); /* The sr is actually a 16 bit register. */ if (regno == PT_SR) {
*(unsignedshort *)addr = data; return 0;
}
}
*addr = data; return 0;
}
/* * Make sure the single step bit is not set.
*/ staticinlinevoid singlestep_disable(struct task_struct *child)
{ unsignedlong tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
put_reg(child, PT_SR, tmp);
clear_tsk_thread_flag(child, TIF_DELAYED_TRACE);
}
/* * Called by kernel/ptrace.c when detaching..
*/ void ptrace_disable(struct task_struct *child)
{
singlestep_disable(child);
}
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ if (addr & 3) goto out_eio;
if (regno == PT_SR) {
data &= SR_MASK;
data |= get_reg(child, PT_SR) & ~SR_MASK;
} if (regno >= 0 && regno < 19) { if (put_reg(child, regno, data)) goto out_eio;
} elseif (regno >= 21 && regno < 48) { /* Convert long double format * into internal fpu reg representation
*/ if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
data <<= 15;
data = (data & 0xffff0000) |
((data & 0x0000ffff) >> 1);
}
child->thread.fp[regno - 21] = data;
} else goto out_eio; break;
case PTRACE_GETREGS: /* Get all gp regs from the child. */ for (i = 0; i < 19; i++) {
tmp = get_reg(child, i);
ret = put_user(tmp, datap); if (ret) break;
datap++;
} break;
case PTRACE_SETREGS: /* Set all gp regs in the child. */ for (i = 0; i < 19; i++) {
ret = get_user(tmp, datap); if (ret) break; if (i == PT_SR) {
tmp &= SR_MASK;
tmp |= get_reg(child, PT_SR) & ~SR_MASK;
}
put_reg(child, i, tmp);
datap++;
} break;
case PTRACE_GETFPREGS: /* Get the child FPU state. */ if (copy_to_user(datap, &child->thread.fp, sizeof(struct user_m68kfp_struct)))
ret = -EFAULT; break;
case PTRACE_SETFPREGS: /* Set the child FPU state. */ if (copy_from_user(&child->thread.fp, datap, sizeof(struct user_m68kfp_struct)))
ret = -EFAULT; break;
case PTRACE_GET_THREAD_AREA:
ret = put_user(task_thread_info(child)->tp_value, datap); break;
default:
ret = ptrace_request(child, request, addr, data); break;
}
return ret;
out_eio: return -EIO;
}
asmlinkage int syscall_trace_enter(void)
{ int ret = 0;
if (test_thread_flag(TIF_SYSCALL_TRACE))
ret = ptrace_report_syscall_entry(task_pt_regs(current));
if (secure_computing() == -1) return -1;
return ret;
}
asmlinkage void syscall_trace_leave(void)
{ if (test_thread_flag(TIF_SYSCALL_TRACE))
ptrace_report_syscall_exit(task_pt_regs(current), 0);
}
#ifdefined(CONFIG_BINFMT_ELF_FDPIC) && defined(CONFIG_ELF_CORE) /* * Currently the only thing that needs to use regsets for m68k is the * coredump support of the elf_fdpic loader. Implement the minimum * definitions required for that.
*/ staticint m68k_regset_get(struct task_struct *target, conststruct user_regset *regset, struct membuf to)
{ struct pt_regs *ptregs = task_pt_regs(target);
u32 uregs[ELF_NGREG];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.