Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "Thomas Maier" <balagi@justmail.de>
To: gdb-patches@sources.redhat.com
Subject: gdb 6.3 C++ breakpoint in constructor/destructor patch
Date: Sun, 01 May 2005 18:33:00 -0000	[thread overview]
Message-ID: <opsp30fyk1iudtyh@aee20.a.pppool.de> (raw)

[-- Attachment #1: Type: text/plain, Size: 1752 bytes --]

Hello,

I want to supply a patch for the released gdb 6.3, that fixes partially  
the gdb bugs

gdb/1091: Constructor breakpoints ignored
gdb/1193: g++ 3.3 creates multiple constructors: gdb 5.3 can't set  
breakpoints

I was really confused, why my programs to not stop at the breakpoint in  
constructor/destructors. Now i know, it is not the fault of my programs ;)  
Since this anoying problem seems to be in gdb since the gcc 3.x release, i  
guess, no one else a) has this problem (i don't believe so) or b) will not  
fix it. So i did it ;)

This modification is only made for commands like "break  
[source]:<lineno>". For C++ constructors and destructors, the patch  
creates more than one breakpoint at the source at lineno, but each  
generated breakpoint will have another address!

NOTE: this is only a simple "hack". I have spent only one day to get into  
gdb source code and do the modification.
It would be better, to create only one breakpoint in such C++ constructors  
and destructors and assign multiple addresses to it. But this needs a huge  
modification of gdb, i guess ;)

ChangeLog:
2005-04-30  Thomas Maier   <balagi@justmail.de>

	* 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]:<lineno>". It creates more than one
	  breakpoint at the source at lineno, but each
	  generated breakpoint will have another address!



For more information see also
http://people.freenet.de/BalaGi

I hope this patch is helpful, maybe some of you can do it into gdb or even  
use it as a base for a better patch fixing 1091 and 1193 ;)

Greetings

Thomas Maier

[-- Attachment #2: patch-gdb-6.3-c++-bpconstr --]
[-- Type: application/octet-stream, Size: 10716 bytes --]

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   <balagi@justmail.de>
+
+	* 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]:<lineno>". 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  <cagney@gnu.org>
 
 	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;
+  }
 }
 
 \f
@@ -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 */
 }
 \f
 
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);

             reply	other threads:[~2005-05-01 18:33 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-05-01 18:33 Thomas Maier [this message]
2005-05-01 19:05 ` Daniel Jacobowitz
2005-05-01 20:54   ` Thomas Maier
2005-05-01 21:56     ` Daniel Jacobowitz
2005-05-03 17:46       ` Thomas Maier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=opsp30fyk1iudtyh@aee20.a.pppool.de \
    --to=balagi@justmail.de \
    --cc=gdb-patches@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox