blob: 58eac8d45027de710a91c745931a0c09234b17bf [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"
Juan Cespedes2a61d192009-07-04 11:29:27 +02007#include "arch.h"
Petr Machata9294d822012-02-07 12:35:58 +01008#include "breakpoint.h"
Petr Machata366c2f42012-02-09 19:34:36 +01009#include "proc.h"
Juan Cespedesa4850832002-03-03 02:37:50 +010010
Petr Machataf789c9c2011-07-09 10:54:27 +020011#ifdef ARCH_HAVE_ENABLE_BREAKPOINT
Petr Machatabc373262012-02-07 23:31:15 +010012extern void arch_enable_breakpoint(pid_t, struct breakpoint *);
Petr Machataf789c9c2011-07-09 10:54:27 +020013#else /* ARCH_HAVE_ENABLE_BREAKPOINT */
Juan Cespedesf1350522008-12-16 18:19:58 +010014void
Petr Machatabc373262012-02-07 23:31:15 +010015arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
Petr Machataf789c9c2011-07-09 10:54:27 +020016{
Petr Machata28e80f62011-08-09 23:33:52 +020017 static unsigned char break_insn[] = BREAKPOINT_VALUE;
Paul Gilliam3f1219f2006-04-24 18:25:38 +020018 unsigned int i, j;
Juan Cespedesa4850832002-03-03 02:37:50 +010019
Juan Cespedescd8976d2009-05-14 13:47:58 +020020 if (sbp->libsym) {
21 debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
22 } else {
23 debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
24 }
Juan Cespedesa4850832002-03-03 02:37:50 +010025
Ian Wienand2d45b1a2006-02-20 22:48:07 +010026 for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
Petr Machata26627682011-07-08 18:15:32 +020027 long a = ptrace(PTRACE_PEEKTEXT, pid,
28 sbp->addr + i * sizeof(long), 0);
Ian Wienand2d45b1a2006-02-20 22:48:07 +010029 for (j = 0;
30 j < sizeof(long)
31 && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
32 unsigned char *bytes = (unsigned char *)&a;
Juan Cespedesa4850832002-03-03 02:37:50 +010033
Paul Gilliam76c61f12006-06-14 06:55:21 +020034 sbp->orig_value[i * sizeof(long) + j] = bytes[j];
Ian Wienand2d45b1a2006-02-20 22:48:07 +010035 bytes[j] = break_insn[i * sizeof(long) + j];
Juan Cespedesa4850832002-03-03 02:37:50 +010036 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010037 ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
Juan Cespedesa4850832002-03-03 02:37:50 +010038 }
39}
Ian Wienand2d45b1a2006-02-20 22:48:07 +010040#endif /* ARCH_HAVE_ENABLE_BREAKPOINT */
Juan Cespedesa4850832002-03-03 02:37:50 +010041
Petr Machataf789c9c2011-07-09 10:54:27 +020042void
Petr Machatabc373262012-02-07 23:31:15 +010043enable_breakpoint(Process *proc, struct breakpoint *sbp)
44{
Petr Machataf789c9c2011-07-09 10:54:27 +020045 if (sbp->libsym) {
46 debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", proc->pid, sbp->addr, sbp->libsym->name);
47 } else {
48 debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
49 }
50 arch_enable_breakpoint(proc->pid, sbp);
51}
52
Ian Wienand5570a772006-02-17 02:00:00 +010053#ifdef ARCH_HAVE_DISABLE_BREAKPOINT
Petr Machatabc373262012-02-07 23:31:15 +010054extern void arch_disable_breakpoint(pid_t, const struct breakpoint *sbp);
Petr Machataf789c9c2011-07-09 10:54:27 +020055#else /* ARCH_HAVE_DISABLE_BREAKPOINT */
Juan Cespedesf1350522008-12-16 18:19:58 +010056void
Petr Machatabc373262012-02-07 23:31:15 +010057arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
Petr Machataf789c9c2011-07-09 10:54:27 +020058{
Paul Gilliam3f1219f2006-04-24 18:25:38 +020059 unsigned int i, j;
Juan Cespedesa4850832002-03-03 02:37:50 +010060
Juan Cespedescd8976d2009-05-14 13:47:58 +020061 if (sbp->libsym) {
62 debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
63 } else {
64 debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
65 }
Juan Cespedesa4850832002-03-03 02:37:50 +010066
Ian Wienand2d45b1a2006-02-20 22:48:07 +010067 for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
68 long a =
69 ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long),
70 0);
71 for (j = 0;
72 j < sizeof(long)
73 && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
74 unsigned char *bytes = (unsigned char *)&a;
Juan Cespedesa4850832002-03-03 02:37:50 +010075
Ian Wienand2d45b1a2006-02-20 22:48:07 +010076 bytes[j] = sbp->orig_value[i * sizeof(long) + j];
Juan Cespedesa4850832002-03-03 02:37:50 +010077 }
Ian Wienand2d45b1a2006-02-20 22:48:07 +010078 ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
Juan Cespedesa4850832002-03-03 02:37:50 +010079 }
80}
Ian Wienand2d45b1a2006-02-20 22:48:07 +010081#endif /* ARCH_HAVE_DISABLE_BREAKPOINT */
Petr Machataf789c9c2011-07-09 10:54:27 +020082
83void
Petr Machatabc373262012-02-07 23:31:15 +010084disable_breakpoint(Process *proc, struct breakpoint *sbp)
85{
Petr Machataf789c9c2011-07-09 10:54:27 +020086 if (sbp->libsym) {
87 debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", proc->pid, sbp->addr, sbp->libsym->name);
88 } else {
89 debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
90 }
91 arch_disable_breakpoint(proc->pid, sbp);
92}