Re: Broken prologue skipping with non-returning function

Daniel Jacobowitz
2008-09-22T14:57:06Z

On Fri, Sep 19, 2008 at 08:00:37PM +0100, Jonathan Larmour wrote:
> I can check in your change too. If so, presumably you already have a
> ChangeLog entry you'd like me to use to ease your merges?
>
> Jifl
>
> 2008-09-19 Jonathan Larmour <jifl@eCosCentric.com>
>
> * arm-tdep.c (arm_skip_prologue): Call skip_prologue_using_sal
> instead of determining symbol and line info directly.

This patch is OK. Here's mine again, with changelog; I committed it.

Both patches, in essentially the same form, have been in
CodeSourcery's tree for two years. So I'm quite confident in them,
as far as GCC goes, and it's clearly an improvement from the ad-hoc
line check in arm-tdep.c. skip_prologue_using_sal does have some
limitations; it's risky with incorrect debug info, and it's a problem
for non-GCC compilers that do not emit the duplicate line note.
More on that, some other time.

--
Daniel Jacobowitz
CodeSourcery

2008-09-22 Daniel Jacobowitz <dan@codesourcery.com>

* symtab.c (skip_prologue_using_sal): Treat two consecutive lines
at the same address as a prologue marker. Do not skip an entire
function.

--- 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