breakpoint.c revision 366c2f46d844f040458df9b7e35fc3b8527ed2d3
1#include "config.h"
2
3#include <sys/ptrace.h>
4#include <string.h>
5
6#include "common.h"
7#include "arch.h"
8#include "breakpoint.h"
9#include "proc.h"
10
11#ifdef ARCH_HAVE_ENABLE_BREAKPOINT
12extern void arch_enable_breakpoint(pid_t, struct breakpoint *);
13#else				/* ARCH_HAVE_ENABLE_BREAKPOINT */
14void
15arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
16{
17	static unsigned char break_insn[] = BREAKPOINT_VALUE;
18	unsigned int i, j;
19
20	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	}
25
26	for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
27		long a = ptrace(PTRACE_PEEKTEXT, pid,
28				sbp->addr + i * sizeof(long), 0);
29		for (j = 0;
30		     j < sizeof(long)
31		     && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
32			unsigned char *bytes = (unsigned char *)&a;
33
34			sbp->orig_value[i * sizeof(long) + j] = bytes[j];
35			bytes[j] = break_insn[i * sizeof(long) + j];
36		}
37		ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
38	}
39}
40#endif				/* ARCH_HAVE_ENABLE_BREAKPOINT */
41
42void
43enable_breakpoint(Process *proc, struct breakpoint *sbp)
44{
45	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
53#ifdef ARCH_HAVE_DISABLE_BREAKPOINT
54extern void arch_disable_breakpoint(pid_t, const struct breakpoint *sbp);
55#else				/* ARCH_HAVE_DISABLE_BREAKPOINT */
56void
57arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
58{
59	unsigned int i, j;
60
61	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	}
66
67	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;
75
76			bytes[j] = sbp->orig_value[i * sizeof(long) + j];
77		}
78		ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
79	}
80}
81#endif				/* ARCH_HAVE_DISABLE_BREAKPOINT */
82
83void
84disable_breakpoint(Process *proc, struct breakpoint *sbp)
85{
86	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}
93