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