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