Re: Broken prologue skipping with non-returning function

Daniel Jacobowitz
2008-09-19T15:00:21Z

On Fri, Sep 19, 2008 at 03:32:59PM +0100, Jonathan Larmour wrote:
> We end up with a .loc for both lines 6 and 7 with no intervening
> instructions. gdb's symtab.c:find_pc_sect_line() looks for when the pc
> changes to something different and thus ends up returning a symtab_and_line
> indicating that the line at that pc is at the 'if' and runs from the start
> of the function to the ldr after the .loc 1 9 0.

skip_prologue_using_sal is supposed to detect this. We have a
patch to improve it in our internal tree that we haven't gotten round
to yet. Here it is; I do not remember what the language_asm check was
really about, except that I'm sure it came up running the gdb
testsuite, so removing it and running asm-source.exp would probably
explain it.

--
Daniel Jacobowitz
CodeSourcery

--- symtab.c 2008-09-05 10:11:13.000000000 -0400
+++ symtab.c 2008-09-19 10:46:03.000000000 -0400
@@ -4198,6 +4235,7 @@ skip_prologue_using_sal (CORE_ADDR func_
struct symtab_and_line prologue_sal;
CORE_ADDR start_pc;
CORE_ADDR end_pc;
+ struct block *bl;

/* Get an initial range for the function. */
find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc);
@@ -4206,11 +4244,35 @@ skip_prologue_using_sal (CORE_ADDR func_
prologue_sal = find_pc_line (start_pc, 0);
if (prologue_sal.line != 0)
{
+ /* For langauges other than assembly, treat two consecutive line
+ entries at the same address as a zero-instruction prologue.
+ The GNU assembler emits separate line notes for each instruction
+ in a multi-instruction macro, but compilers generally will not
+ do this. */
+ if (prologue_sal.symtab->language != language_asm)
+ {
+ struct linetable *linetable = LINETABLE (prologue_sal.symtab);
+ int exact;
+ int idx = 0;
+
+ /* Skip any earlier lines, and any end-of-sequence marker
+ from a previous function. */
+ while (linetable->item[idx].pc != prologue_sal.pc
+ || linetable->item[idx].line == 0)
+ idx++;
+
+ if (idx+1 < linetable->nitems
+ && linetable->item[idx+1].line != 0
+ && linetable->item[idx+1].pc == start_pc)
+ return start_pc;
+ }
+
/* If there is only one sal that covers the entire function,
then it is probably a single line function, like
"foo(){}". */
if (prologue_sal.end >= end_pc)
return 0;
+
while (prologue_sal.end < end_pc)
{
struct symtab_and_line sal;
@@ -4232,7 +4313,14 @@ skip_prologue_using_sal (CORE_ADDR func_
prologue_sal = sal;
}
}
- return prologue_sal.end;
+
+ if (prologue_sal.end < end_pc)
+ /* Return the end of this line, or zero if we could not find a
+ line. */
+ return prologue_sal.end;
+ else
+ /* Don't return END_PC, which is past the end of the function. */
+ return prologue_sal.pc;
}
\f
struct symtabs_and_lines