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