Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

x86 hardware breakpoints with ptrace

1,347 views
Skip to first unread message

Patrick Doyle

unread,
May 3, 2002, 2:52:56 PM5/3/02
to

Hi all,

I'm trying to set a hardware breakpoint by using ptrace to set the x86
debug registers, and I just can't seem to get it to work.

I have attached my code below, and it compiles with -Wall without any
warnings. The output is also shown below, and it appears that the
breakpoint has no effect. From what I have read of the Linux kernel
source code, I would have expected the child process to get a SIGTRAP,
which would cause the parent to awaken from the waidpid call.
However, this doesn't happen.

Can someone tell me what I'm doing wrong? Or, if there's a newsgroup
that would be better-suited to this kind of question, please let me
know.

Thanks in advance!

---- output ----

P: Attaching
C: Waiting
P: Waiting
P: Setting debug regs
setup_control_reg before: 00000000
setup_control_reg after: 00f0000c
Confirm: dr1 is 08049c9c
Confirm: dr7 is 00f0000c
P: Continuing the child
P: Waiting
P: Continuing the child
P: Waiting
C: Firing the watchpoint on 0x8049c9c
C: Done
P: Done

---- code ----

/* Note that this DOES NOT WORK */

#include <sys/ptrace.h> /* ptrace */
#include <asm/user.h> /* struct user */
#include <unistd.h> /* getpid */
#include <errno.h> /* errno */
#include <stddef.h> /* offsetof */
#include <stdio.h> /* perror */
#include <signal.h> /* kill */
#include <wait.h> /* waitpid */
#include <assert.h> /* assert */

int safe_ptrace(int request, int pid, int addr, void * data){
int result;
errno = 0;
result = ptrace(request, pid, addr, data);
if(errno != 0){
perror("ptrace");
exit(1);
}else{
return result;
}
}

static int debug_reg(int pid, int regnum){
return safe_ptrace(
PTRACE_PEEKUSER, pid,
offsetof(struct user, u_debugreg[regnum]), 0
);
}

static void set_debug_reg(int pid, int regnum, int value){
safe_ptrace(
PTRACE_POKEUSER, pid,
offsetof(struct user, u_debugreg[regnum]), (void*)value
);
}

static int bit_replace(int old_val, int lsb, int size, int new_val){
int mask = (-1 << (size+lsb)) | ((1 << lsb) - 1);
return (old_val & mask) | (new_val << lsb);
}

static void setup_control_reg(int pid, int regnum, int len, int when){
int dr7 = debug_reg(pid, 7);
printf("setup_control_reg before: %8.8x\n", dr7);
dr7 = bit_replace(dr7, 18 + 4*regnum, 2, len-1);
dr7 = bit_replace(dr7, 16 + 4*regnum, 2, when);
dr7 |= 3 << (2*regnum);
printf("setup_control_reg after: %8.8x\n", dr7);
set_debug_reg(pid, 7, dr7);
}

enum { EXECUTE=0, WRITE=1, READ_WRITE=3 };

int x;

int main(){
int child;
if((child=fork())){
/* Parent */
int reg_idx, len, when;
int returned_pid, status;
/* Attach to child */
printf("P: Attaching\n");
safe_ptrace(PTRACE_ATTACH, child, 0, 0);
printf("P: Waiting\n");
returned_pid = waitpid(child, &status, WUNTRACED);
assert(returned_pid == child);
/* Set the parameters */
reg_idx = 1;
len = sizeof(x);
when = READ_WRITE;
/* Set the hardware breakpoint */
printf("P: Setting debug regs\n");
set_debug_reg(child, reg_idx, (int)&x);
setup_control_reg(child, reg_idx, len, when);
printf("Confirm: dr%d is %8.8x\n", reg_idx, debug_reg(child, reg_idx));
printf("Confirm: dr7 is %8.8x\n", debug_reg(child, 7));
/* Let the child continue */
while(!WIFEXITED(status)){
printf("P: Continuing the child\n");
safe_ptrace(PTRACE_CONT, child, 0, (void*)SIGCONT);
printf("P: Waiting\n");
returned_pid = waitpid(child, &status, WUNTRACED);
assert(returned_pid == child);
}
printf("P: Done\n");
}else{
/* Child */
/* Wait for parent to set things up */
printf("C: Waiting\n");
kill(getpid(), SIGSTOP);
/* Now fire the watchpoint */
printf("C: Firing the watchpoint on %p\n", &x);
x = 5;
printf("C: Done\n");
}
return 0;
}

--
--
Patrick Doyle
doy...@eecg.toronto.edu

Patrick Doyle

unread,
May 6, 2002, 11:14:20 AM5/6/02
to
Alright, I suppose it's a bit much to ask people to debug my code.
So...

Does anyone have a hardware breakpoint example that works?

BTW, I have already looked at the gdb source, and I think I am doing
exactly what they do. I have done an strace and the system calls seem
to be the same.

Thanks in advance. (My original code is included below.)

--
Patrick Doyle
doy...@eecg.toronto.edu


In article <GvJts...@ecf.utoronto.ca>,

Patrick Doyle

unread,
May 7, 2002, 11:30:58 PM5/7/02
to
Nobody here has any idea how hardware breakpoints work??

--
Patrick Doyle
doy...@eecg.toronto.edu


In article <Gvp3n...@ecf.utoronto.ca>,

Kasper Dupont

unread,
May 8, 2002, 2:55:39 AM5/8/02
to
Patrick Doyle wrote:
>
> Nobody here has any idea how hardware breakpoints work??

I don't.

--
Kasper Dupont -- der bruger for meget tid på usenet.
For sending spam use mailto:razor-...@daimi.au.dk

GoogleFox

unread,
May 8, 2002, 8:50:18 AM5/8/02
to
doy...@eecg.toronto.edu (Patrick Doyle) wrote in message news:<GvrwF...@ecf.utoronto.ca>...

> Nobody here has any idea how hardware breakpoints work??
>

I did some work a _long_ time ago adding hw bkpt functionality to an
Interactive Unix kernel way back. Off the top of my head I cannot see
the fault in your code.

Since gdb supports this just fine, why dont you strace it to see if
what it does agrees with what your app does. Pretty sure its going to
be something silly that you have omitted to do.

Patrick Doyle

unread,
May 8, 2002, 9:51:07 AM5/8/02
to
Well, it turns out that the example code included below actually
works. It seems I had been working on some brain-dead machine where
these breakpoints don't work. (My first clue should have been that
gdb didn't work either.)

Once I moved to another machine, the code below produced the results I
had expected.

--
Patrick Doyle
doy...@eecg.toronto.edu

0 new messages