aboutsummaryrefslogtreecommitdiff
path: root/gdb/symtab.c
diff options
context:
space:
mode:
authorVladimir Prus <vladimir@codesourcery.com>2007-09-24 07:40:32 +0000
committerVladimir Prus <vladimir@codesourcery.com>2007-09-24 07:40:32 +0000
commited0616c6b78a0966e24cdcecf48ebe8e581a0448 (patch)
tree08b6c9c86853d2274b0179e8e333e02ae53f767c /gdb/symtab.c
parentfad9eaf0deff64167032634213f1070193d929f7 (diff)
downloadgdb-ed0616c6b78a0966e24cdcecf48ebe8e581a0448.zip
gdb-ed0616c6b78a0966e24cdcecf48ebe8e581a0448.tar.gz
gdb-ed0616c6b78a0966e24cdcecf48ebe8e581a0448.tar.bz2
* breakpoint.c (remove_sal): New.
(expand_line_sal_maybe): New. (create_breakpoints): Call expand_line_sal_maybe. (clear_command): Add comment. (breakpoint_re_set_one): Call expand_line_sal_maybe. * linespec.c (decode_indirect): Set explicit_pc to 1. (decode_all_digits): Set explicit_line to 1. (append_expanded_sal): New. (expand_line_sal): New. * linespec.h (expand_line_sal): Declare. * symtab.c (init_sal): Initialize explicit_pc and explicit_line. * symtab.h (struct symtab_and_line): New fields explicit_pc and explicit_line.
Diffstat (limited to 'gdb/symtab.c')
-rw-r--r--gdb/symtab.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/gdb/symtab.c b/gdb/symtab.c
index b4743fa..c2726d4 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -691,6 +691,8 @@ init_sal (struct symtab_and_line *sal)
sal->line = 0;
sal->pc = 0;
sal->end = 0;
+ sal->explicit_pc = 0;
+ sal->explicit_line = 0;
}
@@ -4172,6 +4174,166 @@ symtab_observer_executable_changed (void *unused)
set_main_name (NULL);
}
+/* Helper to expand_line_sal below. Appends new sal to SAL,
+ initializing it from SYMTAB, LINENO and PC. */
+static void
+append_expanded_sal (struct symtabs_and_lines *sal,
+ struct symtab *symtab,
+ int lineno, CORE_ADDR pc)
+{
+ CORE_ADDR func_addr, func_end;
+
+ sal->sals = xrealloc (sal->sals,
+ sizeof (sal->sals[0])
+ * (sal->nelts + 1));
+ init_sal (sal->sals + sal->nelts);
+ sal->sals[sal->nelts].symtab = symtab;
+ sal->sals[sal->nelts].section = NULL;
+ sal->sals[sal->nelts].end = 0;
+ sal->sals[sal->nelts].line = lineno;
+ sal->sals[sal->nelts].pc = pc;
+ ++sal->nelts;
+}
+
+/* Compute a set of all sals in
+ the entire program that correspond to same file
+ and line as SAL and return those. If there
+ are several sals that belong to the same block,
+ only one sal for the block is included in results. */
+
+struct symtabs_and_lines
+expand_line_sal (struct symtab_and_line sal)
+{
+ struct symtabs_and_lines ret, this_line;
+ int i, j;
+ struct objfile *objfile;
+ struct partial_symtab *psymtab;
+ struct symtab *symtab;
+ int lineno;
+ int deleted = 0;
+ struct block **blocks = NULL;
+ int *filter;
+
+ ret.nelts = 0;
+ ret.sals = NULL;
+
+ if (sal.symtab == NULL || sal.line == 0 || sal.pc != 0)
+ {
+ ret.sals = xmalloc (sizeof (struct symtab_and_line));
+ ret.sals[0] = sal;
+ ret.nelts = 1;
+ return ret;
+ }
+ else
+ {
+ struct linetable_entry *best_item = 0;
+ struct symtab *best_symtab = 0;
+ int exact = 0;
+
+ lineno = sal.line;
+
+ /* We meed to find all symtabs for a file which name
+ is described by sal. We cannot just directly
+ iterate over symtabs, since a symtab might not be
+ yet created. We also cannot iterate over psymtabs,
+ calling PSYMTAB_TO_SYMTAB and working on that symtab,
+ since PSYMTAB_TO_SYMTAB will return NULL for psymtab
+ corresponding to an included file. Therefore, we do
+ first pass over psymtabs, reading in those with
+ the right name. Then, we iterate over symtabs, knowing
+ that all symtabs we're interested in are loaded. */
+
+ ALL_PSYMTABS (objfile, psymtab)
+ {
+ if (strcmp (sal.symtab->filename,
+ psymtab->filename) == 0)
+ PSYMTAB_TO_SYMTAB (psymtab);
+ }
+
+
+ /* For each symtab, we add all pcs to ret.sals. I'm actually
+ not sure what to do if we have exact match in one symtab,
+ and non-exact match on another symtab.
+ */
+ ALL_SYMTABS (objfile, symtab)
+ {
+ if (strcmp (sal.symtab->filename,
+ symtab->filename) == 0)
+ {
+ struct linetable *l;
+ int len;
+ l = LINETABLE (symtab);
+ if (!l)
+ continue;
+ len = l->nitems;
+
+ for (j = 0; j < len; j++)
+ {
+ struct linetable_entry *item = &(l->item[j]);
+
+ if (item->line == lineno)
+ {
+ exact = 1;
+ append_expanded_sal (&ret, symtab, lineno, item->pc);
+ }
+ else if (!exact && item->line > lineno
+ && (best_item == NULL || item->line < best_item->line))
+
+ {
+ best_item = item;
+ best_symtab = symtab;
+ }
+ }
+ }
+ }
+ if (!exact && best_item)
+ append_expanded_sal (&ret, best_symtab, lineno, best_item->pc);
+ }
+
+ /* For optimized code, compiler can scatter one source line accross
+ disjoint ranges of PC values, even when no duplicate functions
+ or inline functions are involved. For example, 'for (;;)' inside
+ non-template non-inline non-ctor-or-dtor function can result
+ in two PC ranges. In this case, we don't want to set breakpoint
+ on first PC of each range. To filter such cases, we use containing
+ blocks -- for each PC found above we see if there are other PCs
+ that are in the same block. If yes, the other PCs are filtered out. */
+
+ filter = xmalloc (ret.nelts * sizeof (int));
+ blocks = xmalloc (ret.nelts * sizeof (struct block *));
+ for (i = 0; i < ret.nelts; ++i)
+ {
+ filter[i] = 1;
+ blocks[i] = block_for_pc (ret.sals[i].pc);
+ }
+
+ for (i = 0; i < ret.nelts; ++i)
+ if (blocks[i] != NULL)
+ for (j = i+1; j < ret.nelts; ++j)
+ if (blocks[j] == blocks[i])
+ {
+ filter[j] = 0;
+ ++deleted;
+ break;
+ }
+
+ {
+ struct symtab_and_line *final =
+ xmalloc (sizeof (struct symtab_and_line) * (ret.nelts-deleted));
+
+ for (i = 0, j = 0; i < ret.nelts; ++i)
+ if (filter[i])
+ final[j++] = ret.sals[i];
+
+ ret.nelts -= deleted;
+ xfree (ret.sals);
+ ret.sals = final;
+ }
+
+ return ret;
+}
+
+
void
_initialize_symtab (void)
{