Broken prologue skipping with non-returning function

Daniel Jacobowitz drow@false.org
Fri Sep 19 15:00:00 GMT 2008


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;
 }
 
 struct symtabs_and_lines



More information about the Gdb mailing list