how to set watchpoint in Workshop for C++

J

John Black

Hi,
I am using Workshop in Forte Development 6 on Solaris as my C++
debugger. I want to set a breakpoint such that it will stop when some
specific heap address, say, 0x12345678, is allocated or freed. Is there
any way to do this?

In breakpoint setting panel, I see "On Access...", from the word it
can do the job, then I input "0x12345678" on the condition field, but it
says some dbx error. I wonder what is the correct way to do this.

Thanks.
 
S

Seongbae Park

John Black said:
Hi,
I am using Workshop in Forte Development 6 on Solaris as my C++
debugger. I want to set a breakpoint such that it will stop when some
specific heap address, say, 0x12345678, is allocated or freed. Is there
any way to do this?

In breakpoint setting panel, I see "On Access...", from the word it
can do the job, then I input "0x12345678" on the condition field, but it
says some dbx error. I wonder what is the correct way to do this.

Thanks.

An interesting question.
One possible solution is to set the breakpoint
at just before returning from malloc, and right after free is called.

Following is an example:

$ cat t.c
#include <stdio.h>
#include <stdlib.h>

int main(void) {
void * p = malloc(100);

printf("%x\n", p);

free(p);
return 0;
}
$ cc -g t.c
$ dbx ./a.out
Reading a.out
Reading ld.so.1
Reading libc.so.1
Reading libdl.so.1
Reading libc_psr.so.1
(dbx 1) stop in main
(2) stop in main
(dbx 2) run
Running: a.out
(process id 14122)
stopped in main at line 5 in file "t.c"
5 void * p = malloc(100);
(dbx 3) dis malloc
0x7fac1cb8: malloc : save %sp, -96, %sp
0x7fac1cbc: malloc+0x0004: call malloc+0xc ! 0x7fac1cc4
0x7fac1cc0: malloc+0x0008: sethi %hi(0x7a000), %o1
0x7fac1cc4: malloc+0x000c: inc 844, %o1
0x7fac1cc8: malloc+0x0010: add %o1, %o7, %o3
0x7fac1ccc: malloc+0x0014: ld [%o3 + 3788], %l0
0x7fac1cd0: malloc+0x0018: call _PROCEDURE_LINKAGE_TABLE_+0x3c
0x7fac1cd4: malloc+0x001c: mov %l0, %o0
0x7fac1cd8: malloc+0x0020: call _malloc_unlocked ! 0x7fac1cf4
0x7fac1cdc: malloc+0x0024: mov %i0, %o0
(dbx 4) dis
0x7fac1ce0: malloc+0x0028: mov %o0, %i0
0x7fac1ce4: malloc+0x002c: call _PROCEDURE_LINKAGE_TABLE_+0x48
0x7fac1ce8: malloc+0x0030: mov %l0, %o0
0x7fac1cec: malloc+0x0034: ret
0x7fac1cf0: malloc+0x0038: restore
0x7fac1cf4: _malloc_unlocked : save %sp, -96, %sp
0x7fac1cf8: _malloc_unlocked+0x0004: sethi %hi(0xffffdc00), %o0
0x7fac1cfc: _malloc_unlocked+0x0008: call _malloc_unlocked+0x10
0x7fac1d00: _malloc_unlocked+0x000c: sethi %hi(0x7a000), %o1
0x7fac1d04: _malloc_unlocked+0x0010: inc 999, %o0
(dbx 5) stopi at 0x7fac1cec -if $i0 == 0x20e38
(3) stopi at &malloc+0x34 -if $i0 == 0x20e38
(dbx 6) stop in free -if $o0 == 0x20e38
dbx: warning: 'free' has no debugger info -- will trigger on first instruction
(4) stop in free -if $o0 == 0x20e38
(dbx 7) cont
stopped in malloc at 0x7fac1cec
0x7fac1cec: malloc+0x0034: ret
(dbx 8) up
Current function is main
5 void * p = malloc(100);
(dbx 9) cont
20e38
stopped in free at 0x7fac2b4c
0x7fac2b4c: free : save %sp, -96, %sp
Current function is main
9 free(p);
(dbx 10) cont

execution completed, exit code is 0
(dbx 11)


The first stopi point is at the "ret" instruction of malloc,
and stops only when $i0 (the return value, %i0 in disassembly)
is the value you want (in this case, 0x20e38).
The second stop point is at the first instruction of free (stop in free)
and only if $o0 (the first parameter) is the value you want.
(dbx 8) promt caught malloc() from returning 0x20e38,
and (dbx 10) caught free() being passed 0x20e38.

Depending on what you want to do, apptrace might be useful also.
with the same a.out:

$ apptrace ./a.out
apptrace: unexpected version: 3
a.out -> libc.so.1:atexit(func = 0x7fbaeaa8) = 0x0
a.out -> libc.so.1:atexit(func = 0x10c98) = 0x0
a.out -> libc.so.1:malloc(size = 0x64) = 0x20e38
a.out -> libc.so.1:printf(20e38
format = 0x10cb0, ...) = 6
a.out -> libc.so.1:free(ptr = 0x20e38)
a.out -> libc.so.1:exit(status = 0)
$

And of course, Dtrace in Solaris 10 can do what apptrace can do (and more).

Another useful tool is dbx's rtc checking (if that's what you're trying to do).
Just do:

(dbx 1) check -access

And it will do bunch of different runtime error checkings for memory allocation.
Type "help check" on dbx command line to see more detail.
 
S

Seongbae Park

John Black said:
Hi,
I am using Workshop in Forte Development 6 on Solaris as my C++
debugger. I want to set a breakpoint such that it will stop when some
specific heap address, say, 0x12345678, is allocated or freed. Is there
any way to do this?

In breakpoint setting panel, I see "On Access...", from the word it
can do the job, then I input "0x12345678" on the condition field, but it
says some dbx error. I wonder what is the correct way to do this.

Thanks.

Just talked to our dbx engineer, and there's an easier alternative
than setting a breakpoint at the return instruction,
using "stop returns".

On SPARC:

(dbx) stop returns malloc -if $o0 == 0x12345678
(dbx) stop in free -if $o0 == 0x12345678

On x86:

(dbx) stop returns malloc -if $eax == 0x12345678
(dbx) stop in free -if *(void**)($sp + 1) == 0x12345678

This would do the trick nicely,
although the runtime overhead is somewhat more expensive
than the technique described in my previous posting
due to the way "returns" is implemented.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top