blob: e05e73009476575d06f781a9484a61e15cbc0ba2 [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>
Petr Machata81c65272012-03-21 04:57:25 +01004#include <errno.h>
Petr Machataf0f90ed2012-04-13 18:44:12 +02005#include <string.h>
Petr Machatacc0e1e42012-04-25 13:42:07 +02006#include <stdio.h>
Juan Cespedes61da3372009-07-03 11:55:44 +02007
Juan Cespedes8d1b92b2009-07-03 10:39:34 +02008#include "common.h"
Petr Machatad3dc17b2012-03-21 03:23:25 +01009#include "sysdep.h"
Petr Machata9294d822012-02-07 12:35:58 +010010#include "breakpoint.h"
Petr Machata366c2f42012-02-09 19:34:36 +010011#include "proc.h"
Petr Machata2b46cfc2012-02-18 11:17:29 +010012#include "library.h"
Juan Cespedesa4850832002-03-03 02:37:50 +010013
Petr Machataf789c9c2011-07-09 10:54:27 +020014#ifdef ARCH_HAVE_ENABLE_BREAKPOINT
Petr Machatabc373262012-02-07 23:31:15 +010015extern void arch_enable_breakpoint(pid_t, struct breakpoint *);
Petr Machataf789c9c2011-07-09 10:54:27 +020016#else /* ARCH_HAVE_ENABLE_BREAKPOINT */
Juan Cespedesf1350522008-12-16 18:19:58 +010017void
Petr Machatabc373262012-02-07 23:31:15 +010018arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
Petr Machataf789c9c2011-07-09 10:54:27 +020019{
Petr Machata28e80f62011-08-09 23:33:52 +020020 static unsigned char break_insn[] = BREAKPOINT_VALUE;
Paul Gilliam3f1219f2006-04-24 18:25:38 +020021 unsigned int i, j;
Juan Cespedesa4850832002-03-03 02:37:50 +010022
Petr Machataf0f90ed2012-04-13 18:44:12 +020023 debug(DEBUG_PROCESS,
24 "arch_enable_breakpoint: pid=%d, addr=%p, symbol=%s",
Petr Machata050b0a62012-04-03 01:30:30 +020025 pid, sbp->addr, breakpoint_name(sbp));
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);
Petr Machata81c65272012-03-21 04:57:25 +010030 if (a == -1 && errno) {
Petr Machatacc0e1e42012-04-25 13:42:07 +020031 fprintf(stderr, "enable_breakpoint"
32 " pid=%d, addr=%p, symbol=%s: %s\n",
33 pid, sbp->addr, breakpoint_name(sbp),
34 strerror(errno));
Petr Machata81c65272012-03-21 04:57:25 +010035 return;
36 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010037 for (j = 0;
38 j < sizeof(long)
39 && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
40 unsigned char *bytes = (unsigned char *)&a;
Juan Cespedesa4850832002-03-03 02:37:50 +010041
Paul Gilliam76c61f12006-06-14 06:55:21 +020042 sbp->orig_value[i * sizeof(long) + j] = bytes[j];
Ian Wienand2d45b1a2006-02-20 22:48:07 +010043 bytes[j] = break_insn[i * sizeof(long) + j];
Juan Cespedesa4850832002-03-03 02:37:50 +010044 }
Petr Machata949a56a2012-04-03 00:32:03 +020045 a = ptrace(PTRACE_POKETEXT, pid,
46 sbp->addr + i * sizeof(long), a);
Petr Machata81c65272012-03-21 04:57:25 +010047 if (a == -1) {
Petr Machatacc0e1e42012-04-25 13:42:07 +020048 fprintf(stderr, "enable_breakpoint"
49 " pid=%d, addr=%p, symbol=%s: %s\n",
50 pid, sbp->addr, breakpoint_name(sbp),
51 strerror(errno));
Petr Machata81c65272012-03-21 04:57:25 +010052 return;
53 }
Juan Cespedesa4850832002-03-03 02:37:50 +010054 }
55}
Ian Wienand2d45b1a2006-02-20 22:48:07 +010056#endif /* ARCH_HAVE_ENABLE_BREAKPOINT */
Juan Cespedesa4850832002-03-03 02:37:50 +010057
Petr Machataf789c9c2011-07-09 10:54:27 +020058void
Petr Machatabc373262012-02-07 23:31:15 +010059enable_breakpoint(Process *proc, struct breakpoint *sbp)
60{
Petr Machata050b0a62012-04-03 01:30:30 +020061 debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s",
62 proc->pid, sbp->addr, breakpoint_name(sbp));
Petr Machataf789c9c2011-07-09 10:54:27 +020063 arch_enable_breakpoint(proc->pid, sbp);
64}
65
Ian Wienand5570a772006-02-17 02:00:00 +010066#ifdef ARCH_HAVE_DISABLE_BREAKPOINT
Petr Machatabc373262012-02-07 23:31:15 +010067extern void arch_disable_breakpoint(pid_t, const struct breakpoint *sbp);
Petr Machataf789c9c2011-07-09 10:54:27 +020068#else /* ARCH_HAVE_DISABLE_BREAKPOINT */
Juan Cespedesf1350522008-12-16 18:19:58 +010069void
Petr Machatabc373262012-02-07 23:31:15 +010070arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
Petr Machataf789c9c2011-07-09 10:54:27 +020071{
Paul Gilliam3f1219f2006-04-24 18:25:38 +020072 unsigned int i, j;
Juan Cespedesa4850832002-03-03 02:37:50 +010073
Petr Machataf0f90ed2012-04-13 18:44:12 +020074 debug(DEBUG_PROCESS,
75 "arch_disable_breakpoint: pid=%d, addr=%p, symbol=%s",
Petr Machata050b0a62012-04-03 01:30:30 +020076 pid, sbp->addr, breakpoint_name(sbp));
Juan Cespedesa4850832002-03-03 02:37:50 +010077
Ian Wienand2d45b1a2006-02-20 22:48:07 +010078 for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
Petr Machata949a56a2012-04-03 00:32:03 +020079 long a = ptrace(PTRACE_PEEKTEXT, pid,
80 sbp->addr + i * sizeof(long), 0);
81 if (a == -1 && errno) {
Petr Machatacc0e1e42012-04-25 13:42:07 +020082 fprintf(stderr,
83 "disable_breakpoint pid=%d, addr=%p: %s\n",
84 pid, sbp->addr, strerror(errno));
Petr Machata949a56a2012-04-03 00:32:03 +020085 return;
86 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010087 for (j = 0;
88 j < sizeof(long)
89 && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
90 unsigned char *bytes = (unsigned char *)&a;
Juan Cespedesa4850832002-03-03 02:37:50 +010091
Ian Wienand2d45b1a2006-02-20 22:48:07 +010092 bytes[j] = sbp->orig_value[i * sizeof(long) + j];
Juan Cespedesa4850832002-03-03 02:37:50 +010093 }
Petr Machata949a56a2012-04-03 00:32:03 +020094 a = ptrace(PTRACE_POKETEXT, pid,
95 sbp->addr + i * sizeof(long), a);
96 if (a == -1 && errno) {
Petr Machatacc0e1e42012-04-25 13:42:07 +020097 fprintf(stderr,
98 "disable_breakpoint pid=%d, addr=%p: %s\n",
99 pid, sbp->addr, strerror(errno));
Petr Machata949a56a2012-04-03 00:32:03 +0200100 return;
101 }
Juan Cespedesa4850832002-03-03 02:37:50 +0100102 }
103}
Ian Wienand2d45b1a2006-02-20 22:48:07 +0100104#endif /* ARCH_HAVE_DISABLE_BREAKPOINT */
Petr Machataf789c9c2011-07-09 10:54:27 +0200105
106void
Petr Machatabc373262012-02-07 23:31:15 +0100107disable_breakpoint(Process *proc, struct breakpoint *sbp)
108{
Petr Machata050b0a62012-04-03 01:30:30 +0200109 debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s",
110 proc->pid, sbp->addr, breakpoint_name(sbp));
Petr Machataf789c9c2011-07-09 10:54:27 +0200111 arch_disable_breakpoint(proc->pid, sbp);
112}