#if HAVE_CONFIG_H
#include "config.h"
#endif

#include <sys/ptrace.h>
#include "arch.h"
#include "options.h"
#include "output.h"

static unsigned char break_insn[] = BREAKPOINT_VALUE;

void
enable_breakpoint(pid_t pid, struct breakpoint * sbp) {
	int i,j;

	if (opt_d>1) {
		output_line(0, "enable_breakpoint(%d,%p)", pid, sbp->addr);
	}

	for(i=0; i < 1+((BREAKPOINT_LENGTH-1)/sizeof(long)); i++) {
		long a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i*sizeof(long), 0);
		for(j=0; j<sizeof(long) && i*sizeof(long)+j < BREAKPOINT_LENGTH; j++) {
			unsigned char * bytes = (unsigned char *)&a;

			sbp->orig_value[i*sizeof(long)+j] = bytes[+j];
			bytes[j] = break_insn[i*sizeof(long)+j];
		}
		ptrace(PTRACE_POKETEXT, pid, sbp->addr + i*sizeof(long), a);
	}
}

void
disable_breakpoint(pid_t pid, const struct breakpoint * sbp) {
	int i,j;

	if (opt_d>1) {
		output_line(0, "disable_breakpoint(%d,%p)", pid, sbp->addr);
	}

	for(i=0; i < 1+((BREAKPOINT_LENGTH-1)/sizeof(long)); i++) {
		long a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i*sizeof(long), 0);
		for(j=0; j<sizeof(long) && i*sizeof(long)+j < BREAKPOINT_LENGTH; j++) {
			unsigned char * bytes = (unsigned char *)&a;

			bytes[j] = sbp->orig_value[i*sizeof(long)+j];
		}
		ptrace(PTRACE_POKETEXT, pid, sbp->addr + i*sizeof(long), a);
	}
}
