// SPDX-License-Identifier: GPL-2.0 /* ptrace.c */ /* By Ross Biro 1/23/92 */ /* edited by Linus Torvalds */ /* mangled further by Bob Manson (manson@santafe.edu) */ /* more mutilation by David Mosberger (davidm@azstarnet.com) */
/* * The following table maps a register index into the stack offset at * which the register is saved. Register indices are 0-31 for integer * regs, 32-63 for fp regs, and 64 for the pc. Notice that sp and * zero have no stack-slot and need to be treated specially (see * get_reg/put_reg below).
*/ enum {
REG_R0 = 0, REG_F0 = 32, REG_FPCR = 63, REG_PC = 64
};
/* * Set breakpoint.
*/ int
ptrace_set_bpt(struct task_struct * child)
{ int displ, i, res, reg_b, nsaved = 0; unsignedint insn, op_code; unsignedlong pc;
pc = get_reg(child, REG_PC);
res = read_int(child, pc, (int *) &insn); if (res < 0) return res;
op_code = insn >> 26; if (op_code >= 0x30) { /* * It's a branch: instead of trying to figure out * whether the branch will be taken or not, we'll put * a breakpoint at either location. This is simpler, * more reliable, and probably not a whole lot slower * than the alternative approach of emulating the * branch (emulation can be tricky for fp branches).
*/
displ = ((s32)(insn << 11)) >> 9;
task_thread_info(child)->bpt_addr[nsaved++] = pc + 4; if (displ) /* guard against unoptimized code */
task_thread_info(child)->bpt_addr[nsaved++]
= pc + 4 + displ;
DBG(DBG_BPT, ("execing branch\n"));
} elseif (op_code == 0x1a) {
reg_b = (insn >> 16) & 0x1f;
task_thread_info(child)->bpt_addr[nsaved++] = get_reg(child, reg_b);
DBG(DBG_BPT, ("execing jump\n"));
} else {
task_thread_info(child)->bpt_addr[nsaved++] = pc + 4;
DBG(DBG_BPT, ("execing normal insn\n"));
}
/* install breakpoints: */ for (i = 0; i < nsaved; ++i) {
res = read_int(child, task_thread_info(child)->bpt_addr[i],
(int *) &insn); if (res < 0) return res;
task_thread_info(child)->bpt_insn[i] = insn;
DBG(DBG_BPT, (" -> next_pc=%lx\n",
task_thread_info(child)->bpt_addr[i]));
res = write_int(child, task_thread_info(child)->bpt_addr[i],
BREAKINST); if (res < 0) return res;
}
task_thread_info(child)->bpt_nsaved = nsaved; return 0;
}
/* * Ensure no single-step breakpoint is pending. Returns non-zero * value if child was being single-stepped.
*/ int
ptrace_cancel_bpt(struct task_struct * child)
{ int i, nsaved = task_thread_info(child)->bpt_nsaved;
/* * Called by kernel/ptrace.c when detaching.. * * Make sure the single step bit is not set.
*/ void ptrace_disable(struct task_struct *child)
{
user_disable_single_step(child);
}
long arch_ptrace(struct task_struct *child, long request, unsignedlong addr, unsignedlong data)
{ unsignedlong tmp;
size_t copied; long ret;
switch (request) { /* When I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA:
copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp),
FOLL_FORCE);
ret = -EIO; if (copied != sizeof(tmp)) break;
force_successful_syscall_return();
ret = tmp; break;
/* Read register number ADDR. */ case PTRACE_PEEKUSR:
force_successful_syscall_return();
ret = get_reg(child, addr);
DBG(DBG_MEM, ("peek $%lu->%#lx\n", addr, ret)); break;
/* When I and D space are separate, this will have to be fixed. */ case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA:
ret = generic_ptrace_pokedata(child, addr, data); break;
case PTRACE_POKEUSR: /* write the specified register */
DBG(DBG_MEM, ("poke $%lu<-%#lx\n", addr, data));
ret = put_reg(child, addr, data); break; default:
ret = ptrace_request(child, request, addr, data); break;
} return ret;
}
asmlinkage unsignedlong syscall_trace_enter(void)
{ unsignedlong ret = 0; struct pt_regs *regs = current_pt_regs(); if (test_thread_flag(TIF_SYSCALL_TRACE) &&
ptrace_report_syscall_entry(current_pt_regs()))
ret = -1UL;
audit_syscall_entry(regs->r0, regs->r16, regs->r17, regs->r18, regs->r19); return ret ?: current_pt_regs()->r0;
}
asmlinkage void
syscall_trace_leave(void)
{
audit_syscall_exit(current_pt_regs()); if (test_thread_flag(TIF_SYSCALL_TRACE))
ptrace_report_syscall_exit(current_pt_regs(), 0);
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet)
¤
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.