blob: 2e0af189f4c81969f383addb3d3d581851167442 [file] [log] [blame]
Juan Cespedesa4850832002-03-03 02:37:50 +01001#include "config.h"
Juan Cespedesa4850832002-03-03 02:37:50 +01002
3#include <sys/ptrace.h>
Ian Wienand5570a772006-02-17 02:00:00 +01004#include <string.h>
Juan Cespedes61da3372009-07-03 11:55:44 +02005
Juan Cespedes8d1b92b2009-07-03 10:39:34 +02006#include "common.h"
Petr Machatad3dc17b2012-03-21 03:23:25 +01007#include "sysdep.h"
Petr Machata9294d822012-02-07 12:35:58 +01008#include "breakpoint.h"
Petr Machata366c2f42012-02-09 19:34:36 +01009#include "proc.h"
Petr Machata2b46cfc2012-02-18 11:17:29 +010010#include "library.h"
Juan Cespedesa4850832002-03-03 02:37:50 +010011
Petr Machataf789c9c2011-07-09 10:54:27 +020012#ifdef ARCH_HAVE_ENABLE_BREAKPOINT
Petr Machatabc373262012-02-07 23:31:15 +010013extern void arch_enable_breakpoint(pid_t, struct breakpoint *);
Petr Machataf789c9c2011-07-09 10:54:27 +020014#else /* ARCH_HAVE_ENABLE_BREAKPOINT */
Juan Cespedesf1350522008-12-16 18:19:58 +010015void
Petr Machatabc373262012-02-07 23:31:15 +010016arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
Petr Machataf789c9c2011-07-09 10:54:27 +020017{
Petr Machata28e80f62011-08-09 23:33:52 +020018 static unsigned char break_insn[] = BREAKPOINT_VALUE;
Paul Gilliam3f1219f2006-04-24 18:25:38 +020019 unsigned int i, j;
Juan Cespedesa4850832002-03-03 02:37:50 +010020
Juan Cespedescd8976d2009-05-14 13:47:58 +020021 if (sbp->libsym) {
22 debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
23 } else {
24 debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
25 }
Juan Cespedesa4850832002-03-03 02:37:50 +010026
Ian Wienand2d45b1a2006-02-20 22:48:07 +010027 for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
Petr Machata26627682011-07-08 18:15:32 +020028 long a = ptrace(PTRACE_PEEKTEXT, pid,
29 sbp->addr + i * sizeof(long), 0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010030 for (j = 0;
31 j < sizeof(long)
32 && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
33 unsigned char *bytes = (unsigned char *)&a;
Juan Cespedesa4850832002-03-03 02:37:50 +010034
Paul Gilliam76c61f12006-06-14 06:55:21 +020035 sbp->orig_value[i * sizeof(long) + j] = bytes[j];
Ian Wienand2d45b1a2006-02-20 22:48:07 +010036 bytes[j] = break_insn[i * sizeof(long) + j];
Juan Cespedesa4850832002-03-03 02:37:50 +010037 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010038 ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
Juan Cespedesa4850832002-03-03 02:37:50 +010039 }
40}
Ian Wienand2d45b1a2006-02-20 22:48:07 +010041#endif /* ARCH_HAVE_ENABLE_BREAKPOINT */
Juan Cespedesa4850832002-03-03 02:37:50 +010042
Petr Machataf789c9c2011-07-09 10:54:27 +020043void
Petr Machatabc373262012-02-07 23:31:15 +010044enable_breakpoint(Process *proc, struct breakpoint *sbp)
45{
Petr Machataf789c9c2011-07-09 10:54:27 +020046 if (sbp->libsym) {
47 debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", proc->pid, sbp->addr, sbp->libsym->name);
48 } else {
49 debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
50 }
51 arch_enable_breakpoint(proc->pid, sbp);
52}
53
Ian Wienand5570a772006-02-17 02:00:00 +010054#ifdef ARCH_HAVE_DISABLE_BREAKPOINT
Petr Machatabc373262012-02-07 23:31:15 +010055extern void arch_disable_breakpoint(pid_t, const struct breakpoint *sbp);
Petr Machataf789c9c2011-07-09 10:54:27 +020056#else /* ARCH_HAVE_DISABLE_BREAKPOINT */
Juan Cespedesf1350522008-12-16 18:19:58 +010057void
Petr Machatabc373262012-02-07 23:31:15 +010058arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
Petr Machataf789c9c2011-07-09 10:54:27 +020059{
Paul Gilliam3f1219f2006-04-24 18:25:38 +020060 unsigned int i, j;
Juan Cespedesa4850832002-03-03 02:37:50 +010061
Juan Cespedescd8976d2009-05-14 13:47:58 +020062 if (sbp->libsym) {
63 debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
64 } else {
65 debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
66 }
Juan Cespedesa4850832002-03-03 02:37:50 +010067
Ian Wienand2d45b1a2006-02-20 22:48:07 +010068 for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
69 long a =
70 ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long),
71 0);
72 for (j = 0;
73 j < sizeof(long)
74 && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
75 unsigned char *bytes = (unsigned char *)&a;
Juan Cespedesa4850832002-03-03 02:37:50 +010076
Ian Wienand2d45b1a2006-02-20 22:48:07 +010077 bytes[j] = sbp->orig_value[i * sizeof(long) + j];
Juan Cespedesa4850832002-03-03 02:37:50 +010078 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010079 ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
Juan Cespedesa4850832002-03-03 02:37:50 +010080 }
81}
Ian Wienand2d45b1a2006-02-20 22:48:07 +010082#endif /* ARCH_HAVE_DISABLE_BREAKPOINT */
Petr Machataf789c9c2011-07-09 10:54:27 +020083
84void
Petr Machatabc373262012-02-07 23:31:15 +010085disable_breakpoint(Process *proc, struct breakpoint *sbp)
86{
Petr Machataf789c9c2011-07-09 10:54:27 +020087 if (sbp->libsym) {
88 debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", proc->pid, sbp->addr, sbp->libsym->name);
89 } else {
90 debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
91 }
92 arch_disable_breakpoint(proc->pid, sbp);
93}