diff -Nur gdb-6.3/gdb/ChangeLog gdb-6.3.1/gdb/ChangeLog --- gdb-6.3/gdb/ChangeLog 2004-11-08 17:21:20.000000000 +0100 +++ gdb-6.3.1/gdb/ChangeLog 2005-04-30 22:03:12.382049280 +0200 @@ -1,3 +1,33 @@ +2005-04-30 Thomas Maier + + * breakpoint.c linespec.c symtab.c symtab.h + Add better support for breakpoints in C++ constructors + and destructors. + NOTE: this is only a simple hack. + This modification is only made for commands like + "break [source]:". It creates more than one + breakpoint at the source at lineno, but each + generated breakpoint will have another address! + + See also: (taken from PROBLEMS file) + gdb/1091: Constructor breakpoints ignored + gdb/1193: g++ 3.3 creates multiple constructors: gdb 5.3 can't set breakpoints + + When gcc 3.x compiles a C++ constructor or C++ destructor, it generates + 2 or 3 different versions of the object code. These versions have + unique mangled names (they have to, in order for linking to work), but + they have identical source code names, which leads to a great deal of + confusion. Specifically, if you set a breakpoint in a constructor or a + destructor, gdb will put a breakpoint in one of the versions, but your + program may execute the other version. This makes it impossible to set + breakpoints reliably in constructors or destructors. + + gcc 3.x generates these multiple object code functions in order to + implement virtual base classes. gcc 2.x generated just one object code + function with a hidden parameter, but gcc 3.x conforms to a multi-vendor + ABI for C++ which requires multiple object code functions. + + 2004-11-08 Andrew Cagney GDB 6.3 released. diff -Nur gdb-6.3/gdb/breakpoint.c gdb-6.3.1/gdb/breakpoint.c --- gdb-6.3/gdb/breakpoint.c 2004-10-08 19:30:46.000000000 +0200 +++ gdb-6.3.1/gdb/breakpoint.c 2005-04-30 20:58:10.000000000 +0200 @@ -5309,10 +5309,26 @@ mention (b); } - if (sals.nelts > 1) + /* balagi 04/30/2005 only warn it this is not a multipc */ + if (sals.nelts > 1 ) { - warning ("Multiple breakpoints were set."); - warning ("Use the \"delete\" command to delete unwanted breakpoints."); + if ( sals.sals[0].multipc ) + { + if ( sals.sals[0].symtab->language == language_cplus ) + { + warning("Multiple breakpoints were set, maybe in a C++ de/constructor."); + } + else + { + warning ("Multiple breakpoints were set at the same line,"); + warning ("but at different addresses!"); + } + } + else + { + warning ("Multiple breakpoints were set."); + warning ("Use the \"delete\" command to delete unwanted breakpoints."); + } } /* That's it. Discard the cleanups for data inserted into the breakpoint. */ @@ -7206,6 +7222,37 @@ s = b->addr_string; sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL, not_found_ptr); + /* balagi 04/30/2005 + if sal->multipc is not 0, the sals was returned from + decode_all_digits() and marks that the same source + line have multiple pc's (e.g. GNU g++ >3.x constructors). + In this case, find the sal that matches this breakpoint + and check only this sal against other breakpoints. + NOTE: is sal->multipc not 0, then sal->pc is + already resolved! + */ + if ( sals.nelts > 1 && sals.sals[0].multipc ) + { + for ( i = 0; i < sals.nelts; i++ ) + { + if ( b->loc->address == sals.sals[i].pc ) + break; + } + if ( i == sals.nelts ) /* ups, not found */ + { + /* TODO: what should we do here??? + if we do nothing, gdb generates + several warnings etc.... + */ + } + else + { + /* modify sals to only represent the found sal */ + sals.nelts = 1; + if ( i > 0 ) + sals.sals[0] = sals.sals[i]; + } + } for (i = 0; i < sals.nelts; i++) { resolve_sal_pc (&sals.sals[i]); diff -Nur gdb-6.3/gdb/linespec.c gdb-6.3.1/gdb/linespec.c --- gdb-6.3/gdb/linespec.c 2004-06-18 23:36:15.000000000 +0200 +++ gdb-6.3.1/gdb/linespec.c 2005-04-30 19:19:40.000000000 +0200 @@ -90,7 +90,7 @@ struct symbol **sym_arr); static void build_canonical_line_spec (struct symtab_and_line *, - char *, char ***); + char *, char ***, int); static char *find_toplevel_char (char *s, char c); @@ -376,23 +376,27 @@ the SAL has a symtab. If SYMNAME is non-NULL the canonical line spec is `filename:symname'. If SYMNAME is NULL the line number from SAL is used and the canonical - line spec is `filename:linenum'. */ + line spec is `filename:linenum'. + balagi 04/30/2005 NUMDUPS duplicates the canonical name n times */ static void build_canonical_line_spec (struct symtab_and_line *sal, char *symname, - char ***canonical) + char ***canonical, int numdups) { char **canonical_arr; char *canonical_name; char *filename; struct symtab *s = sal->symtab; + int i; if (s == (struct symtab *) NULL || s->filename == (char *) NULL || canonical == (char ***) NULL) return; - canonical_arr = (char **) xmalloc (sizeof (char *)); + if ( numdups < 1 ) + numdups = 1; + canonical_arr = (char **) xmalloc (sizeof (char *) * numdups); *canonical = canonical_arr; filename = s->filename; @@ -407,6 +411,11 @@ sprintf (canonical_name, "%s:%d", filename, sal->line); } canonical_arr[0] = canonical_name; + for ( i = 1; i < numdups; i++ ) + { + canonical_arr[i] = xmalloc(strlen(canonical_name) + 2); + strcpy(canonical_arr[i], canonical_name); + } } @@ -1129,7 +1138,7 @@ { /* Canonicalize this, so it remains resolved for dylib loads. */ values.sals[0] = find_function_start_sal (sym, funfirstline); - build_canonical_line_spec (values.sals, SYMBOL_NATURAL_NAME (sym), canonical); + build_canonical_line_spec (values.sals, SYMBOL_NATURAL_NAME (sym), canonical, 1); } else { @@ -1561,8 +1570,7 @@ struct symtab *file_symtab, char *q) { - struct symtabs_and_lines values; - struct symtab_and_line val; + int line; enum sign { @@ -1573,8 +1581,6 @@ /* We might need a canonical line spec if no file was specified. */ int need_canonical = (file_symtab == 0) ? 1 : 0; - init_sal (&val); - /* This is where we need to make sure that we have good defaults. We must guarantee that this section of code is never executed when we are called with just a function name, since @@ -1592,22 +1598,22 @@ sign = plus, (*argptr)++; else if (**argptr == '-') sign = minus, (*argptr)++; - val.line = atoi (*argptr); + line = atoi (*argptr); switch (sign) { case plus: if (q == *argptr) - val.line = 5; + line = 5; if (file_symtab == 0) - val.line = default_line + val.line; + line = default_line + line; break; case minus: if (q == *argptr) - val.line = 15; + line = 15; if (file_symtab == 0) - val.line = default_line - val.line; + line = default_line - line; else - val.line = 1; + line = 1; break; case none: break; /* No need to adjust val.line. */ @@ -1622,18 +1628,61 @@ /* It is possible that this source file has more than one symtab, and that the new line number specification has moved us from the default (in file_symtab) to a new one. */ - val.symtab = find_line_symtab (file_symtab, val.line, NULL, NULL); - if (val.symtab == 0) - val.symtab = file_symtab; - - val.pc = 0; - values.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); - values.sals[0] = val; - values.nelts = 1; - if (need_canonical) - build_canonical_line_spec (values.sals, NULL, canonical); - return values; + { + /* balagi 04/30/2005 + in case language == language_cplus, we try to find other + entries in the linetable with the same line number + to be able to set breakpoints in C++ constructors/ + destructors (for GNU C++ >3.x) */ + const int maxlti = 128; + int ltindices[maxlti]; + int num = 0; + int idx = -1; + struct symtabs_and_lines values; + struct linetable* lt; + struct symtab* st = find_line_symtab(file_symtab, line, &idx, NULL); + if ( st != NULL && idx >= 0 ) + { + lt = LINETABLE(st); + ltindices[num++] = idx; + if ( st->language == language_cplus ) + { + /* search for more entries */ + for ( idx++; idx < lt->nitems; idx++ ) + { + if ( lt->item[idx].line == line ) + { + ltindices[num++] = idx; + if ( num >= maxlti ) + break; + } + } + } + } + else + { + st = file_symtab; + lt = LINETABLE(st); + ltindices[num++] = -1; + } + + values.sals = (struct symtab_and_line*) + xmalloc(sizeof(struct symtab_and_line) * num); + values.nelts = num; + for ( idx = 0; idx < num; idx++ ) + { + struct symtab_and_line* val = &values.sals[idx]; + init_sal(val); + /* set the pc here if available ! */ + val->pc = (ltindices[idx] >= 0 ? lt->item[ltindices[idx]].pc : 0); + val->line = line; + val->symtab = st; + val->multipc = (num > 1 ? 1 : 0); + } + if (need_canonical) + build_canonical_line_spec (&values.sals[0], NULL, canonical, num); + return values; + } } @@ -1705,7 +1754,7 @@ values.nelts = 1; if (need_canonical) - build_canonical_line_spec (values.sals, NULL, canonical); + build_canonical_line_spec (values.sals, NULL, canonical, 1); return values; } @@ -1798,7 +1847,7 @@ struct blockvector *bv = BLOCKVECTOR (sym_symtab); struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL) - build_canonical_line_spec (values.sals, copy, canonical); + build_canonical_line_spec (values.sals, copy, canonical, 1); } return values; } diff -Nur gdb-6.3/gdb/symtab.c gdb-6.3.1/gdb/symtab.c --- gdb-6.3/gdb/symtab.c 2004-10-02 11:55:15.000000000 +0200 +++ gdb-6.3.1/gdb/symtab.c 2005-04-30 21:23:15.000000000 +0200 @@ -700,6 +700,7 @@ sal->line = 0; sal->pc = 0; sal->end = 0; + sal->multipc = 0; /* balagi 04/30/2005 */ } diff -Nur gdb-6.3/gdb/symtab.h gdb-6.3.1/gdb/symtab.h --- gdb-6.3/gdb/symtab.h 2004-06-10 22:05:44.000000000 +0200 +++ gdb-6.3.1/gdb/symtab.h 2005-04-30 19:19:40.000000000 +0200 @@ -1198,6 +1198,11 @@ CORE_ADDR pc; CORE_ADDR end; + + /* balagi 04/30/2005 + if not 0, it exists another symtab_and_line with the same + symtab and line, but a different pc */ + int multipc; }; extern void init_sal (struct symtab_and_line *sal);