Re: [RFA] Fix "break foo" when `foo's prologue ends before line table

Eli Zaretskii
2009-05-16T11:18:58Z

> Date: Mon, 11 May 2009 23:49:10 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: gdb-patches@sourceware.org
>
> > Date: Mon, 11 May 2009 21:27:09 +0200
> > From: Joel Brobecker <brobecker@adacore.com>
> > Cc: gdb-patches@sourceware.org
> >
> > I'm always reluctant to introduce code I don't understand, and usually
> > leave it out until I see a bug - that's why I was asking. Have you
> > tried without this part?
>
> No, but I will.

OK, I tried it, and it does work, at least in the 2 test cases I could
try.

Here's an updated patch, which incorporates the comments in this
thread:

. It uses a single symtab for the function's symbol
. It stops looking as soon as it finds the first linetable entry
whose PC is in the range of the function's PC values

OK to commit?

2009-05-09 Eli Zaretskii <eliz@gnu.org>

* symtab.c (skip_prologue_using_lineinfo): New function.
(find_function_start_sal): Use it to get to the first line of
function's body that has an entry in the lineinfo table.

--- symtab.c~0 2009-04-01 02:21:07.000000000 +0300
+++ symtab.c 2009-05-16 13:49:42.296906500 +0300
@@ -2599,6 +2599,46 @@
return pc;
}

+/* Given a function start address FUNC_ADDR and SYMTAB, find the first
+ address for that function that has an entry in SYMTAB's line info
+ table. If such an entry cannot be found, return FUNC_ADDR
+ unaltered. */
+CORE_ADDR
+skip_prologue_using_lineinfo (CORE_ADDR func_addr, struct symtab *symtab)
+{
+ CORE_ADDR func_start, func_end;
+ struct linetable *l;
+ int ind, i, len;
+ int best_lineno = 0;
+ CORE_ADDR best_pc = func_addr;
+
+ /* Get the range for the function's PC values, or give up if we
+ cannot, for some reason. */
+ if (!find_pc_partial_function (func_addr, NULL, &func_start, &func_end))
+ return func_addr;
+
+ l = LINETABLE (symtab);
+ if (l == NULL)
+ return func_addr;
+
+ /* Linetable entries are ordered by PC values, see the commentary in
+ symtab.h where `struct linetable' is defined. Thus, the first
+ entry whose PC is in the range [FUNC_START..FUNC_END] is the
+ address we are looking for. */
+ for (i = 0; i < l->nitems; i++)
+ {
+ struct linetable_entry *item = &(l->item[i]);
+
+ /* Don't use line numbers of zero, they mark special entries in
+ the table. See the commentary on symtab.h before the
+ definition of struct linetable. */
+ if (item->line > 0 && func_start <= item->pc && item->pc <= func_end)
+ return item->pc;
+ }
+
+ return func_addr;
+}
+
/* Given a function symbol SYM, find the symtab and line for the start
of the function.
If the argument FUNFIRSTLINE is nonzero, we want the first line
@@ -2649,6 +2689,15 @@
sal = find_pc_sect_line (pc, SYMBOL_OBJ_SECTION (sym), 0);
}

+ /* If we still don't have a valid source line, try to find the first
+ PC in the lineinfo table that belongs to the same function. */
+ if (funfirstline && sal.symtab == NULL)
+ {
+ pc = skip_prologue_using_lineinfo (pc, SYMBOL_SYMTAB (sym));
+ /* Recalculate the line number. */
+ sal = find_pc_sect_line (pc, SYMBOL_OBJ_SECTION (sym), 0);
+ }
+
sal.pc = pc;

return sal;