breakpoint.c revision 81c65272697a63d81e6baece69bef6ba8f55932e
1#include "config.h"
2
3#include <sys/ptrace.h>
4#include <string.h>
5#include <errno.h>
6#include <error.h>
7
8#include "common.h"
9#include "sysdep.h"
10#include "breakpoint.h"
11#include "proc.h"
12#include "library.h"
13
14#ifdef ARCH_HAVE_ENABLE_BREAKPOINT
15extern void arch_enable_breakpoint(pid_t, struct breakpoint *);
16#else				/* ARCH_HAVE_ENABLE_BREAKPOINT */
17void
18arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
19{
20	static unsigned char break_insn[] = BREAKPOINT_VALUE;
21	unsigned int i, j;
22
23	if (sbp->libsym) {
24		debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
25	} else {
26		debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
27	}
28
29	for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
30		long a = ptrace(PTRACE_PEEKTEXT, pid,
31				sbp->addr + i * sizeof(long), 0);
32		if (a == -1 && errno) {
33			error(0, errno, "enable_breakpoint pid=%d, addr=%p", pid, sbp->addr);
34			return;
35		}
36		for (j = 0;
37		     j < sizeof(long)
38		     && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
39			unsigned char *bytes = (unsigned char *)&a;
40
41			sbp->orig_value[i * sizeof(long) + j] = bytes[j];
42			bytes[j] = break_insn[i * sizeof(long) + j];
43		}
44		a = ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
45		if (a == -1) {
46			error(0, errno, "enable_breakpoint pid=%d, addr=%p", pid, sbp->addr);
47			return;
48		}
49	}
50}
51#endif				/* ARCH_HAVE_ENABLE_BREAKPOINT */
52
53void
54enable_breakpoint(Process *proc, struct breakpoint *sbp)
55{
56	if (sbp->libsym) {
57		debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", proc->pid, sbp->addr, sbp->libsym->name);
58	} else {
59		debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
60	}
61	arch_enable_breakpoint(proc->pid, sbp);
62}
63
64#ifdef ARCH_HAVE_DISABLE_BREAKPOINT
65extern void arch_disable_breakpoint(pid_t, const struct breakpoint *sbp);
66#else				/* ARCH_HAVE_DISABLE_BREAKPOINT */
67void
68arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
69{
70	unsigned int i, j;
71
72	if (sbp->libsym) {
73		debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
74	} else {
75		debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
76	}
77
78	for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
79		long a =
80		    ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long),
81			   0);
82		for (j = 0;
83		     j < sizeof(long)
84		     && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
85			unsigned char *bytes = (unsigned char *)&a;
86
87			bytes[j] = sbp->orig_value[i * sizeof(long) + j];
88		}
89		ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
90	}
91}
92#endif				/* ARCH_HAVE_DISABLE_BREAKPOINT */
93
94void
95disable_breakpoint(Process *proc, struct breakpoint *sbp)
96{
97	if (sbp->libsym) {
98		debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", proc->pid, sbp->addr, sbp->libsym->name);
99	} else {
100		debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
101	}
102	arch_disable_breakpoint(proc->pid, sbp);
103}
104