This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
Breakpoints in constructors
- From: Amit Kale <amitkale at linsyssoft dot com>
- To: gdb at sourceware dot org
- Date: Thu, 15 Dec 2005 19:35:54 +0530
- Subject: Breakpoints in constructors
Hi,
I am posting this on behalf of TimeSys Corporation. We had developed a fix
(read hack) to enable gdb to place breakpoints in C++ constructors. This work
was done on gdb 6.2 (patch attached).
I was planning to post this patch after rebasing to current gdb, but then
found that there was some communication on this earlier. I would like to know
gdb guru's opinion on this patch. Does this appear to much of a hack? Someone
else working on a better solution?
Any help on this patch and/or directions for making this right will be highly
appreciated.
Thanks.
-Amit
Index: gdb-6.2/gdb/breakpoint.c
===================================================================
--- gdb-6.2.orig/gdb/breakpoint.c 2004-09-21 16:12:25.000000000 +0530
+++ gdb-6.2/gdb/breakpoint.c 2004-09-21 19:05:52.000000000 +0530
@@ -4463,7 +4463,8 @@
make_cleanup (xfree, canonical[0]);
}
- resolve_sal_pc (&sals.sals[0]);
+ /* solib hook doesn't have multiple instances */
+ resolve_sal_pc (&sals, NULL, NULL);
/* Remove the canonical strings from the cleanup, they are needed below. */
if (canonical != (char **) NULL)
@@ -5018,36 +5019,41 @@
static void
breakpoint_sals_to_pc (struct symtabs_and_lines *sals,
- char *address)
+ char *address, char ***addr_string)
{
- int i;
+ int i, j;
for (i = 0; i < sals->nelts; i++)
{
- resolve_sal_pc (&sals->sals[i]);
-
- /* It's possible for the PC to be nonzero, but still an illegal
- value on some targets.
+ j = i;
+ resolve_sal_pc (sals, &i, addr_string);
- For example, on HP-UX if you start gdb, and before running the
- inferior you try to set a breakpoint on a shared library function
- "foo" where the inferior doesn't call "foo" directly but does
- pass its address to another function call, then we do find a
- minimal symbol for the "foo", but it's address is invalid.
- (Appears to be an index into a table that the loader sets up
- when the inferior is run.)
+ while (j <= i)
+ {
+ /* It's possible for the PC to be nonzero, but still an illegal
+ value on some targets.
+
+ For example, on HP-UX if you start gdb, and before running the
+ inferior you try to set a breakpoint on a shared library function
+ "foo" where the inferior doesn't call "foo" directly but does
+ pass its address to another function call, then we do find a
+ minimal symbol for the "foo", but it's address is invalid.
+ (Appears to be an index into a table that the loader sets up
+ when the inferior is run.)
- Give the target a chance to bless sals.sals[i].pc before we
- try to make a breakpoint for it. */
+ Give the target a chance to bless sals.sals[i].pc before we
+ try to make a breakpoint for it. */
#ifdef DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE
- if (DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc))
- {
- if (address == NULL)
- error ("Cannot break without a running program.");
- else
- error ("Cannot break on %s without a running program.",
- address);
- }
+ if (DEPRECATED_PC_REQUIRES_RUN_BEFORE_USE (sals->sals[i].pc))
+ {
+ if (address == NULL)
+ error ("Cannot break without a running program.");
+ else
+ error ("Cannot break on %s without a running program.",
+ address);
+ }
#endif
+ j++;
+ }
}
}
@@ -5148,6 +5154,12 @@
else if (!sals.nelts)
return GDB_RC_FAIL;
+ /* Resolve all line numbers to PC's and verify that the addresses
+ are ok for the target. This function call can result in an increase in
+ the number of nelts */
+ if (!pending)
+ breakpoint_sals_to_pc (&sals, addr_start, &addr_string);
+
/* Create a chain of things that always need to be cleaned up. */
old_chain = make_cleanup (null_cleanup, 0);
@@ -5183,11 +5195,6 @@
make_cleanup (xfree, addr_string[i]);
}
- /* Resolve all line numbers to PC's and verify that the addresses
- are ok for the target. */
- if (!pending)
- breakpoint_sals_to_pc (&sals, addr_start);
-
/* Verify that condition can be parsed, before setting any
breakpoints. Allocate a separate condition expression for each
breakpoint. */
@@ -5326,6 +5333,11 @@
if (!sals.nelts)
return GDB_RC_NONE;
+ /* Resolve all line numbers to PC's and verify that the addresses
+ are ok for the target. This function call can result in an increase in
+ the number of nelts */
+ breakpoint_sals_to_pc (&sals, args->address, &addr_string);
+
/* Create a chain of things at always need to be cleaned up. */
old_chain = make_cleanup (null_cleanup, 0);
@@ -5364,9 +5376,6 @@
if (*address_end != '\0')
error ("Garbage %s following breakpoint address", address_end);
- /* Resolve all line numbers to PC's. */
- breakpoint_sals_to_pc (&sals, args->address);
-
/* Verify that conditions can be parsed, before setting any
breakpoints. */
for (i = 0; i < sals.nelts; i++)
@@ -5576,16 +5585,34 @@
}
-/* Helper function for break_command_1 and disassemble_command. */
+/* Helper function for break_command_1 and disassemble_command.
+ If index is NULL doesn't extend sals. Assumes that there is only one sals
+ entry. Otherwise extends sals if more than one
+ entry is found for given line number.
+ */
void
-resolve_sal_pc (struct symtab_and_line *sal)
+resolve_sal_pc (struct symtabs_and_lines *sals, int *index, char
+ ***addr_string)
{
CORE_ADDR pc;
+ struct symtab_and_line *sal;
+ int ind = 0;
+ int i;
+ CORE_ADDR origpc;
+ extern int debugkernel;
+
+ /* Multiple breakpoints feature conflicts with assembly code in kernel */
+ if (debugkernel)
+ index = NULL;
+ if (index)
+ sal = &sals->sals[*index];
+ else
+ sal = &sals->sals[0];
if (sal->pc == 0 && sal->symtab != NULL)
{
- if (!find_line_pc (sal->symtab, sal->line, &pc))
+ if ((ind = find_line_pc (sal->symtab, sal->line, &pc, ind)) == 0)
error ("No line %d in file \"%s\".",
sal->line, sal->symtab->filename);
sal->pc = pc;
@@ -5623,6 +5650,54 @@
}
}
}
+ if (index && sal->pc)
+ {
+ struct symbol *psym;
+ struct symbol *nsym;
+ struct block *bl;
+ origpc = sal->pc;
+ bl = block_for_pc(pc);
+ psym = bl ? block_function(bl): NULL;
+ while ((ind = find_line_pc (sal->symtab, sal->line, &pc, ind)) != 0)
+ {
+ /* Insert this entry into sals if it isn't the duplicate of the
+ * first entry and if it doesn't appear in the same function as the
+ * previous entry */
+ bl = block_for_pc(pc);
+ nsym = bl ? block_function(bl): NULL;
+ if (pc != origpc && psym != nsym)
+ {
+ psym = nsym;
+ sals->sals = xrealloc(sals->sals, sizeof (struct symtab_and_line) *
+ (sals->nelts + 1));
+ if (addr_string)
+ *addr_string = xrealloc(*addr_string, sizeof (char **) *
+ (sals->nelts + 1));
+
+ for (i = sals->nelts; i > *index; i--)
+ {
+ sals->sals[i] = sals->sals[i - 1];
+ if (addr_string)
+ (*addr_string)[i] = (*addr_string)[i - 1];
+ }
+ sals->nelts++;
+ (*index)++;
+ sals->sals[*index].pc = pc;
+ if (addr_string)
+ {
+ if ((*addr_string)[*index - 1])
+ {
+ (*addr_string)[*index] =
+ savestring((*addr_string)[*index - 1],
+ strlen((*addr_string)[*index - 1]));
+ }
+ else
+ (*addr_string)[*index] = NULL;
+ }
+ sal = &sals->sals[*index];
+ }
+ }
+ }
}
void
@@ -6068,12 +6143,15 @@
error ("Couldn't get information on specified line.");
sal = sals.sals[0];
- xfree (sals.sals); /* malloc'd, so freed */
if (*arg)
- error ("Junk at end of arguments.");
+ {
+ xfree (sals.sals); /* malloc'd, so freed */
+ error ("Junk at end of arguments.");
+ }
- resolve_sal_pc (&sal);
+ resolve_sal_pc (&sals, NULL, NULL);
+ xfree (sals.sals); /* malloc'd, so freed */
if (anywhere)
/* If the user told us to continue until a specified location,
@@ -7162,7 +7240,36 @@
sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, (char ***) NULL, NULL);
for (i = 0; i < sals.nelts; i++)
{
- resolve_sal_pc (&sals.sals[i]);
+ int j = i;
+ int thisbpt = i;
+ struct breakpoint *bpt;
+
+ resolve_sal_pc (&sals, &i, NULL);
+
+ /* If there are multiple breakpoints for this address. We need to
+ * find out which one of them corresponds to this breakpoint. If any
+ * of them correspond to some other breakpoints, they'll be handled
+ * later when we try to insert them. */
+
+ while (j <= i)
+ {
+ ALL_BREAKPOINTS(bpt)
+ if (bpt->loc->address == sals.sals[j].pc)
+ break;
+ if (!bpt)
+ {
+ if (j < i)
+ /* There is no breakpoint corresponding to this
+ * address. We'll have to create one. FIXME: can't
+ * handle that for multiple breakpoints yet */
+ error("New breakpoint found while reserting "
+ "breakpoints");
+ }
+ else
+ if (bpt == b)
+ thisbpt = j;
+ j++;
+ }
/* Reparse conditions, they might contain references to the
old symtab. */
@@ -7176,33 +7283,33 @@
to parse_exp_1. */
b->cond = NULL;
}
- b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
+ b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[thisbpt].pc), 0);
}
/* We need to re-set the breakpoint if the address changes... */
- if (b->loc->address != sals.sals[i].pc
+ if (b->loc->address != sals.sals[thisbpt].pc
/* ...or new and old breakpoints both have source files, and
the source file name or the line number changes... */
|| (b->source_file != NULL
- && sals.sals[i].symtab != NULL
- && (strcmp (b->source_file, sals.sals[i].symtab->filename) != 0
- || b->line_number != sals.sals[i].line)
+ && sals.sals[thisbpt].symtab != NULL
+ && (strcmp (b->source_file, sals.sals[thisbpt].symtab->filename) != 0
+ || b->line_number != sals.sals[thisbpt].line)
)
/* ...or we switch between having a source file and not having
one. */
- || ((b->source_file == NULL) != (sals.sals[i].symtab == NULL))
+ || ((b->source_file == NULL) != (sals.sals[thisbpt].symtab == NULL))
)
{
if (b->source_file != NULL)
xfree (b->source_file);
- if (sals.sals[i].symtab == NULL)
+ if (sals.sals[thisbpt].symtab == NULL)
b->source_file = NULL;
else
b->source_file =
- savestring (sals.sals[i].symtab->filename,
- strlen (sals.sals[i].symtab->filename));
- b->line_number = sals.sals[i].line;
- b->loc->requested_address = sals.sals[i].pc;
+ savestring (sals.sals[thisbpt].symtab->filename,
+ strlen (sals.sals[thisbpt].symtab->filename));
+ b->line_number = sals.sals[thisbpt].line;
+ b->loc->requested_address = sals.sals[thisbpt].pc;
b->loc->address
= adjust_breakpoint_address (b->loc->requested_address,
b->type);
@@ -7217,13 +7324,14 @@
rather than once for every breakpoint. */
breakpoints_changed ();
}
- b->loc->section = sals.sals[i].section;
+ b->loc->section = sals.sals[thisbpt].section;
b->enable_state = save_enable; /* Restore it, this worked. */
/* Now that this is re-enabled, check_duplicates
can be used. */
check_duplicates (b);
+ i = j;
}
xfree (sals.sals);
Index: gdb-6.2/gdb/dwarf2read.c
===================================================================
--- gdb-6.2.orig/gdb/dwarf2read.c 2004-09-21 16:12:07.000000000 +0530
+++ gdb-6.2/gdb/dwarf2read.c 2004-09-21 19:05:52.000000000 +0530
@@ -3111,6 +3111,11 @@
else
return;
+ /* Check for artificial methods. */
+ attr = dwarf2_attr (die, DW_AT_artificial, cu);
+ if (attr && DW_UNSND (attr) != 0)
+ return;
+
/* Get the mangled name. */
physname = dwarf2_linkage_name (die, cu);
@@ -3204,11 +3209,6 @@
}
}
- /* Check for artificial methods. */
- attr = dwarf2_attr (die, DW_AT_artificial, cu);
- if (attr && DW_UNSND (attr) != 0)
- fnp->is_artificial = 1;
-
/* Get index in virtual function table if it is a virtual member function. */
attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu);
if (attr)
@@ -5610,25 +5610,25 @@
{
unsigned int i;
struct attribute *spec = NULL;
+ unsigned int level = 0;
- for (i = 0; i < die->num_attrs; ++i)
+ do
{
- if (die->attrs[i].name == name)
+ for (i = 0; i < die->num_attrs; ++i)
{
- return &die->attrs[i];
- }
- if (die->attrs[i].name == DW_AT_specification
- || die->attrs[i].name == DW_AT_abstract_origin)
- spec = &die->attrs[i];
- }
- if (spec)
- {
- struct die_info *ref_die =
- follow_die_ref (dwarf2_get_ref_die_offset (spec, cu));
-
- if (ref_die)
- return dwarf2_attr (ref_die, name, cu);
+ if (die->attrs[i].name == name)
+ {
+ return &die->attrs[i];
+ }
+ if (die->attrs[i].name == DW_AT_specification
+ || die->attrs[i].name == DW_AT_abstract_origin)
+ spec = &die->attrs[i];
+ }
+ if (spec)
+ die = follow_die_ref (dwarf2_get_ref_die_offset (spec, cu));
+ level++;
}
+ while (die && level < 3);
return NULL;
}
Index: gdb-6.2/gdb/infcmd.c
===================================================================
--- gdb-6.2.orig/gdb/infcmd.c 2004-06-29 12:09:06.000000000 +0530
+++ gdb-6.2/gdb/infcmd.c 2004-09-21 19:05:52.000000000 +0530
@@ -849,12 +849,15 @@
}
sal = sals.sals[0];
- xfree (sals.sals);
if (sal.symtab == 0 && sal.pc == 0)
- error ("No source file has been specified.");
+ {
+ xfree (sals.sals);
+ error ("No source file has been specified.");
+ }
- resolve_sal_pc (&sal); /* May error out */
+ resolve_sal_pc (&sals, NULL, NULL); /* May error out */
+ xfree (sals.sals);
/* See if we are trying to jump to another function. */
fn = get_frame_function (get_current_frame ());
Index: gdb-6.2/gdb/symtab.c
===================================================================
--- gdb-6.2.orig/gdb/symtab.c 2004-07-08 16:48:27.000000000 +0530
+++ gdb-6.2/gdb/symtab.c 2004-09-21 19:05:52.000000000 +0530
@@ -71,7 +71,7 @@
static void output_source_filename (char *, int *);
-static int find_line_common (struct linetable *, int, int *);
+static int find_line_common (struct linetable *, int, int *, int, int);
/* This one is used by linespec.c */
@@ -2197,18 +2197,34 @@
find_line_symtab (struct symtab *symtab, int line, int *index, int *exact_match)
{
int exact;
+ int find_exact = 0;
/* BEST_INDEX and BEST_LINETABLE identify the smallest linenumber > LINE
so far seen. */
int best_index;
+ int start_index = 0;
struct linetable *best_linetable;
struct symtab *best_symtab;
/* First try looking it up in the given symtab. */
best_linetable = LINETABLE (symtab);
+
+ /* Check whether we are continuing a previous search */
+ if (best_linetable && index && *index)
+ {
+ if (*index >= best_linetable->nitems)
+ return NULL;
+ if (best_linetable->item[(*index) - 1].line != line)
+ /* We are continuing an approximate search. Continue with the line
+ * numbers that exactly match previous hit */
+ line = best_linetable->item[(*index) - 1].line;
+ find_exact = 1;
+ start_index = *index;
+ }
best_symtab = symtab;
- best_index = find_line_common (best_linetable, line, &exact);
+ best_index = find_line_common (best_linetable, line, &exact, find_exact,
+ start_index);
if (best_index < 0 || !exact)
{
/* Didn't find an exact match. So we better keep looking for
@@ -2239,7 +2255,7 @@
if (strcmp (symtab->filename, s->filename) != 0)
continue;
l = LINETABLE (s);
- ind = find_line_common (l, line, &exact);
+ ind = find_line_common (l, line, &exact, find_exact, start_index);
if (ind >= 0)
{
if (exact)
@@ -2271,15 +2287,16 @@
return best_symtab;
}
-/* Set the PC value for a given source file and line number and return true.
- Returns zero for invalid line number (and sets the PC to 0).
- The source file is specified with a struct symtab. */
+/* Set the PC value for a given source file and line number and return index
+ into the line table for the symbol table;
+ Returns 0 for if doesn't find an entry (and sets the PC to 0).
+ The source file is specified with a struct symtab.
+ Begins the search at index ind */
int
-find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc)
+find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc, int ind)
{
struct linetable *l;
- int ind;
*pc = 0;
if (symtab == 0)
@@ -2290,7 +2307,7 @@
{
l = LINETABLE (symtab);
*pc = l->item[ind].pc;
- return 1;
+ return ind + 1;
}
else
return 0;
@@ -2310,7 +2327,7 @@
struct symtab_and_line found_sal;
startaddr = sal.pc;
- if (startaddr == 0 && !find_line_pc (sal.symtab, sal.line, &startaddr))
+ if (startaddr == 0 && !find_line_pc (sal.symtab, sal.line, &startaddr, 0))
return 0;
/* This whole function is based on address. For example, if line 10 has
@@ -2339,11 +2356,13 @@
table for the pc of the nearest line whose number is >= the specified one.
Return -1 if none is found. The value is >= 0 if it is an index.
- Set *EXACT_MATCH nonzero if the value returned is an exact match. */
+ Set *EXACT_MATCH nonzero if the value returned is an exact match.
+ If find_exact is non-zero, it forces an exact match
+ start_index is the index to start searching from */
static int
find_line_common (struct linetable *l, int lineno,
- int *exact_match)
+ int *exact_match, int find_exact, int start_index)
{
int i;
int len;
@@ -2361,7 +2380,7 @@
return -1;
len = l->nitems;
- for (i = 0; i < len; i++)
+ for (i = start_index; i < len; i++)
{
struct linetable_entry *item = &(l->item[i]);
@@ -2371,6 +2390,8 @@
*exact_match = 1;
return i;
}
+ if (find_exact)
+ continue;
if (item->line > lineno && (best == 0 || item->line < best))
{
Index: gdb-6.2/gdb/symtab.h
===================================================================
--- gdb-6.2.orig/gdb/symtab.h 2004-06-11 01:35:44.000000000 +0530
+++ gdb-6.2/gdb/symtab.h 2004-09-21 19:05:52.000000000 +0530
@@ -1256,12 +1256,12 @@
/* Given a symtab and line number, return the pc there. */
-extern int find_line_pc (struct symtab *, int, CORE_ADDR *);
+extern int find_line_pc (struct symtab *, int, CORE_ADDR *, int);
extern int find_line_pc_range (struct symtab_and_line, CORE_ADDR *,
CORE_ADDR *);
-extern void resolve_sal_pc (struct symtab_and_line *);
+extern void resolve_sal_pc (struct symtabs_and_lines *, int *, char ***);
/* Given a string, return the line specified by it. For commands like "list"
and "breakpoint". */
Index: gdb-6.2/gdb/tracepoint.c
===================================================================
--- gdb-6.2.orig/gdb/tracepoint.c 2004-06-15 06:34:20.000000000 +0530
+++ gdb-6.2/gdb/tracepoint.c 2004-09-21 19:05:52.000000000 +0530
@@ -384,6 +384,7 @@
struct tracepoint *t;
char *addr_start = 0, *addr_end = 0;
int i;
+ int j;
if (!arg || !*arg)
error ("trace command requires an argument");
@@ -399,7 +400,11 @@
/* Resolve all line numbers to PC's */
for (i = 0; i < sals.nelts; i++)
- resolve_sal_pc (&sals.sals[i]);
+ {
+ /* Let resolve_sal_pc insert sals if required */
+ j = i;
+ resolve_sal_pc (&sals, &j, NULL);
+ }
/* Now set all the tracepoints. */
for (i = 0; i < sals.nelts; i++)
@@ -2348,7 +2353,7 @@
return; /* presumably decode_line_1 has already warned */
/* Resolve line numbers to PC */
- resolve_sal_pc (&sals.sals[0]);
+ resolve_sal_pc (&sals, NULL, NULL);
block = block_for_pc (sals.sals[0].pc);
while (block != 0)
Index: gdb-6.2/gdb/mi/mi-cmd-disas.c
===================================================================
--- gdb-6.2.orig/gdb/mi/mi-cmd-disas.c 2002-09-30 21:27:26.000000000 +0530
+++ gdb-6.2/gdb/mi/mi-cmd-disas.c 2004-09-21 19:05:52.000000000 +0530
@@ -148,7 +148,7 @@
s = lookup_symtab (file_string);
if (s == NULL)
error ("mi_cmd_disassemble: Invalid filename.");
- if (!find_line_pc (s, line_num, &start))
+ if (!find_line_pc (s, line_num, &start, 0))
error ("mi_cmd_disassemble: Invalid line number");
if (find_pc_partial_function (start, NULL, &low, &high) == 0)
error ("mi_cmd_disassemble: No function contains specified address");
Index: gdb-6.2/gdb/tui/tui-layout.c
===================================================================
--- gdb-6.2.orig/gdb/tui/tui-layout.c 2004-09-21 19:17:08.000000000 +0530
+++ gdb-6.2/gdb/tui/tui-layout.c 2004-09-21 19:19:42.000000000 +0530
@@ -520,7 +520,7 @@
case SRC_DATA_COMMAND:
find_line_pc (cursal.symtab,
TUI_SRC_WIN->detail.source_info.start_line_or_addr.line_no,
- &pc);
+ &pc, 0);
addr = pc;
break;
case DISASSEM_COMMAND:
Index: gdb-6.2/gdb/tui/tui-win.c
===================================================================
--- gdb-6.2.orig/gdb/tui/tui-win.c 2004-09-21 19:25:44.000000000 +0530
+++ gdb-6.2/gdb/tui/tui-win.c 2004-09-21 19:26:41.000000000 +0530
@@ -1313,7 +1313,7 @@
line.line_no = cursal.line;
else
{
- find_line_pc (s, cursal.line, &line.addr);
+ find_line_pc (s, cursal.line, &line.addr, 0);
}
tui_update_source_window (win_info, s, line, TRUE);
}
Index: gdb-6.2/gdb/tui/tui-winsource.c
===================================================================
--- gdb-6.2.orig/gdb/tui/tui-winsource.c 2004-09-21 19:31:59.000000000 +0530
+++ gdb-6.2/gdb/tui/tui-winsource.c 2004-09-21 19:32:43.000000000 +0530
@@ -178,7 +178,7 @@
{
case DISASSEM_COMMAND:
case DISASSEM_DATA_COMMAND:
- find_line_pc (s, line, &pc);
+ find_line_pc (s, line, &pc, 0);
tui_update_source_windows_with_addr (pc);
break;
default:
@@ -186,7 +186,7 @@
tui_show_symtab_source (s, l, FALSE);
if (tui_current_layout () == SRC_DISASSEM_COMMAND)
{
- find_line_pc (s, line, &pc);
+ find_line_pc (s, line, &pc, 0);
tui_show_disassem (pc);
}
break;