From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eli Zaretskii To: jimb@cygnus.com Cc: hjl@lucon.org, gdb@sourceware.cygnus.com Subject: Re: Hardware watchpoints Date: Sat, 23 Oct 1999 03:48:00 -0000 Message-id: <199910231048.GAA31392@mescaline.gnu.org> References: <19991019235249.917DC1B494@ocean.lucon.org> <199910201401.KAA28719@mescaline.gnu.org> <199910221200.IAA24556@mescaline.gnu.org> X-SW-Source: 1999-q4/msg00149.html > What expressions did you try to watch? What chains of values did they > produce? Which ones are lazy, and which ones aren't? Thanks for the explanations. A simple test program is attached at the end of this message. (It's a program I used for testing several different aspects of watchpoints, so not everything it includes is relevant to the issue at hand.) An abridged script of a GDB session follows. As you see, I watched two different members of a struct variable `foo_var': `foo_var.iv' and `foo_var.jv'. GDB produced two value chains, each one including the struct member and the struct itself--all of them marked as lazy. Perhaps we could use v->type.code in the decision whether to watch any values but the first one on the value chain? One question that I still can't figure out is why does GDB at all _need_ to have the parent struct on the value chain? Where is that information used? Also, the v->type member for the parent struct has a NULL type.name member. Unless I misunderstood gdbtypes.h, it seems to imply that name should be "struct" or "struct foo". Here's the GDB session: e:/src/gnu/gdb-4.18/gdb> gdb gdb.exe ... (top-gdb) b breakpoint.c:781 Breakpoint 3 at 0x2c61: file breakpoint.c, line 781 (top-gdb) r fptest4 Starting program: e:/src/gnu/gdb-4.18/gdb/gdb.exe fptest4 ... (gdb) b main Breakpoint 1 at 0x15bf: file fptest.c, line 7 (gdb) r Starting program: e:/src/gnu/gdb-4.18/gdb/fptest4 Breakpoint 1, main (argv=1, argv=0x911c4) at fptest.c:7 7 volatile double a = M_SQRT2; (gdb) l 21,24 21 argc = a * a; 22 foo_var.iv = argc + 2; 23 foo_var.jv = argc + 3; 24 if (foo_var.iv < 0) (gdb) watch foo_var.iv Hardware watchpoint 2: foo_var.iv (gdb) watch foo_var.jv Hardware watchpoint 3: foo_var.jv (gdb) c Continuing. Breakpoint 3, insert_breakpoints () at breakpoint.c:781 781 v = evaluate_expression (b->exp); (top-gdb) p b->exp_string $1 = 0x1eabe8 "foo_var.iv" (top-gdb) p *b->exp $2 = {language_defn = During symbol reading, stub type has NULL name. 0xc188, nelts = 9, elts = {{opcode = STRUCTOP_STRUCT, symbol = 0x56, ...}}} (top-gdb) n 782 value_release_to_mark (mark); (top-gdb) p *v $3 = {lval = lval_memory, modifiable = 1, location = {address = 0x90904, ...}, offset = 0, bitsize = 0, bitpos = 0, frame_addr = 0, type = 0x1e7710, enclosing_type = 0x1e7710, next = 0x1ea6f8, substring_addr = {memaddr = 0xea890, ...}, regno = -1, lazy = 1 '\001', optimized_out = 0 '\000', embedded_offset = 0, pointed_to_offset = 0, bfd_section = 0x0, aligner = {...}} (top-gdb)p *(struct type *)v->type $4 = {code = TYPE_CODE_INT, name = 0x1e7754 "int", tag_name = 0x0, length = 4, upper_bound_type = 0, lower_bound_type = 0, ..., cv_type = 0x1e7710, flags = 0, nfields = 0, fields = 0x0, ..., type_specific = { arg_types = 0x0, cplus_stuff = 0x0}} (top-gdb)p *v->next $5 = {lval = lval_memory, modifiable = 1, location = {address = 0x90904, ...}, offset = 0, bitsize = 0, bitpos = 0, frame_addr = 0, type = 0x1e7a3c, enclosing_type = 0x1e7a3c, next = 0x0, substring_addr = {memaddr = 0xea890, ...}, regno = -1, lazy = 1 '\001', optimized_out = 0 '\000', embedded_offset = 0, pointed_to_offset = 0, bfd_section = 0x0, aligner = {...}} (top-gdb) p *(struct type *)v->next->type $6 = {code = TYPE_CODE_STRUCT, name = 0x0, tag_name = 0x1ea390 "foo", length = 20, upper_bound_type = 0, lower_bound_type = 0, ..., cv_type = 0x1e7a3c, flags = 0, nfields = 5, fields = 0x0x1e7ad4, vptr_basetype = 0x0, vptr_fieldno = -1, type_specific = { arg_types = 0x13c120, cplus_stuff = 0x13c120}} (top-gdb) c Continuing. Breakpoint 3, insert_breakpoints () at breakpoint.c:781 781 v = evaluate_expression (b->exp); (top-gdb) p b->exp_string $7 = 0x1eabe8 "foo_var.jv" (top-gdb) n 782 value_release_to_mark (mark); (top-gdb) p *v $8 = {lval = lval_memory, modifiable = 1, location = {address = 0x90904, ...}, offset = 16, bitsize = 0, bitpos = 0, frame_addr = 0, type = 0x1e7710, enclosing_type = 0x1e7710, next = 0x1ea6f8, substring_addr = {memaddr = 0xea890, ...}, regno = -1, lazy = 1 '\001', optimized_out = 0 '\000', embedded_offset = 0, pointed_to_offset = 0, bfd_section = 0x0, aligner = {...}} (top-gdb)p *(struct type *)v->type $9 = {code = TYPE_CODE_INT, name = 0x1e7754 "int", tag_name = 0x0, length = 4, upper_bound_type = 0, lower_bound_type = 0, ..., cv_type = 0x1e7710, flags = 0, nfields = 0, fields = 0x0, ..., type_specific = { arg_types = 0x0, cplus_stuff = 0x0}} (top-gdb)p *v->next $10 = {lval = lval_memory, modifiable = 1, location = {address = 0x90904, ...}, offset = 0, bitsize = 0, bitpos = 0, frame_addr = 0, type = 0x1e7a3c, enclosing_type = 0x1e7a3c, next = 0x0, substring_addr = {memaddr = 0xea890, ...}, regno = -1, lazy = 1 '\001', optimized_out = 0 '\000', embedded_offset = 0, pointed_to_offset = 0, bfd_section = 0x0, aligner = {...}} (top-gdb) p *(struct type *)v->next->type $11 = {code = TYPE_CODE_STRUCT, name = 0x0, tag_name = 0x1ea390 "foo", length = 20, upper_bound_type = 0, lower_bound_type = 0, ..., cv_type = 0x1e7a3c, flags = 0, nfields = 5, fields = 0x0x1e7ad4, vptr_basetype = 0x0, vptr_fieldno = -1, type_specific = { arg_types = 0x13c120, cplus_stuff = 0x13c120}} (top-gdb) Here's teh source of the test program (the DOS-specific function getch() reads a single character from the console device in binary mode): #include #include #include int main (int argc, char *argv[]) { volatile double a = M_SQRT2; struct foo { int iv; double dv; unsigned flag1:1; unsigned flag2:2; int jv; } foo_var; printf ("a squared = %f (should be 2.0)\n", a * a); a *= argc + 1; getch (); printf ("10 log10 (0.5) returns %f (should be -3)\n", 10 * log10 (1.0/(a*a))); argc = a * a; foo_var.iv = argc + 2; foo_var.jv = argc + 3; if (foo_var.iv < 10) foo_var.flag1 = 1; if (foo_var.jv < 100) foo_var.flag2 = 2; return 0; }