[2/2] Improve arm_skip_prologue by using arm_analyze_prologue

Message ID 1417318831-1522-3-git-send-email-yao@codesourcery.com
State New, archived
Headers

Commit Message

Yao Qi Nov. 30, 2014, 3:40 a.m. UTC
  Hi,
I see many fails in dw2-dir-file-name.exp on arm target when test
case is compiled with -marm, however, these fails are disappeared when
test case is compiled with -mthumb.

The difference of pass and fail shown below is that "0x000085d4 in" isn't
printed out, but test case expects to see it.

-Breakpoint 2, compdir_missing__ldir_missing__file_basename () at tmp-dw2-dir-file-name.c:999^M
-(gdb) FAIL: gdb.dwarf2/dw2-dir-file-name.exp: compdir_missing__ldir_missing__file_basename: continue to breakpoint: compdir_missing__ldir_missing__file_basename
+Breakpoint 2, 0x000085d4 in compdir_missing__ldir_missing__file_basename () at tmp-dw2-dir-file-name.c:999^M
+(gdb) PASS: gdb.dwarf2/dw2-dir-file-name.exp: compdir_missing__ldir_missing__file_basename: continue to breakpoint: compdir_missing__ldir_missing__file_basename

This difference is caused by setting breakpoint at the first instruction
in the function (actually, the first instruction in prologue, at [1]),
so that frame_show_address returns false, and print_frame doesn't print the
address.

   0x00008620 <+0>:     push    {r11}           ; (str r11, [sp, #-4]!)  <--[1]
   0x00008624 <+4>:     add     r11, sp, #0
   0x00008628 <+8>:     ldr     r3, [pc, #24]   ; 0x8648 <compdir_missing__ldir_missing__file_basename+40>
   0x0000862c <+12>:    ldr     r3, [r3]
   0x00008630 <+16>:    add     r3, r3, #1
   0x00008634 <+20>:    ldr     r2, [pc, #12]   ; 0x8648 <compdir_missing__ldir_missing__file_basename+40>

Then, it must be the arm_skip_prologue's fault that unable to skip
instructions in prologue.  At the end of arm_skip_prologue, it matches
several instructions, such as "str  r(0123),[r11,#-nn]" and
"str  r(0123),[sp,#nn]", but "push {r11}" isn't handled.

These instruction matching code in arm_skip_prologue, which can be regarded
as leftover of development for many years, should be merged to
arm_analyze_prologue and use arm_analyze_prologue in arm_skip_prologue.
Here is the something like the history of arm_{skip,scan,analyze}_prologue.
Around 2002, there are arm_skip_prologue and arm_scan_prologue, but code are
duplicated to some extent.  When match an instruction, both functions should
be modified, for example in Michael Snyder's patch
https://sourceware.org/ml/gdb-patches/2002-05/msg00205.html and Michael
expressed the willingness to merge both into one.  Daniel added code call
thumb_analyze_prologue in arm_skip_prologue in 2006, but didn't handle its
counterpart arm_analyze_prologue, which is added in 2010
<https://sourceware.org/ml/gdb-patches/2010-03/msg00820.html>
however, the instructions matching at the bottom of arm_skip_prologue wasn't
cleaned up.  This patch is to merge them into arm_analyze_prologue.

Note 1: I recall some one opened a PR for these fails, but I can't find
it in bugzilla.
Note 2: This patch should also fix PR 14261, but I don't have a CLANG to
test it.

gdb:

2014-11-30  Yao Qi  <yao@codesourcery.com>

	* arm-tdep.c (arm_skip_prologue): Remove unused local variable
	'skip_pc'.  Remove code skipping prologue instructions, use
	arm_analyze_prologue instead.
	(arm_analyze_prologue): Stop the scanning for unrecognized
	instruction when skipping prologue.
---
 gdb/arm-tdep.c | 75 ++++++++++------------------------------------------------
 1 file changed, 12 insertions(+), 63 deletions(-)
  

Patch

diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 3407045..a4f99c5 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -1388,7 +1388,6 @@  arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   unsigned long inst;
-  CORE_ADDR skip_pc;
   CORE_ADDR func_addr, limit_pc;
 
   /* See if we can determine the end of the prologue via the symbol table.
@@ -1462,65 +1461,8 @@  arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   /* Check if this is Thumb code.  */
   if (arm_pc_is_thumb (gdbarch, pc))
     return thumb_analyze_prologue (gdbarch, pc, limit_pc, NULL);
-
-  for (skip_pc = pc; skip_pc < limit_pc; skip_pc += 4)
-    {
-      inst = read_memory_unsigned_integer (skip_pc, 4, byte_order_for_code);
-
-      /* "mov ip, sp" is no longer a required part of the prologue.  */
-      if (inst == 0xe1a0c00d)			/* mov ip, sp */
-	continue;
-
-      if ((inst & 0xfffff000) == 0xe28dc000)    /* add ip, sp #n */
-	continue;
-
-      if ((inst & 0xfffff000) == 0xe24dc000)    /* sub ip, sp #n */
-	continue;
-
-      /* Some prologues begin with "str lr, [sp, #-4]!".  */
-      if (inst == 0xe52de004)			/* str lr, [sp, #-4]! */
-	continue;
-
-      if ((inst & 0xfffffff0) == 0xe92d0000)	/* stmfd sp!,{a1,a2,a3,a4} */
-	continue;
-
-      if ((inst & 0xfffff800) == 0xe92dd800)	/* stmfd sp!,{fp,ip,lr,pc} */
-	continue;
-
-      /* Any insns after this point may float into the code, if it makes
-	 for better instruction scheduling, so we skip them only if we
-	 find them, but still consider the function to be frame-ful.  */
-
-      /* We may have either one sfmfd instruction here, or several stfe
-	 insns, depending on the version of floating point code we
-	 support.  */
-      if ((inst & 0xffbf0fff) == 0xec2d0200)	/* sfmfd fn, <cnt>, [sp]! */
-	continue;
-
-      if ((inst & 0xffff8fff) == 0xed6d0103)	/* stfe fn, [sp, #-12]! */
-	continue;
-
-      if ((inst & 0xfffff000) == 0xe24cb000)	/* sub fp, ip, #nn */
-	continue;
-
-      if ((inst & 0xfffff000) == 0xe24dd000)	/* sub sp, sp, #nn */
-	continue;
-
-      if ((inst & 0xffffc000) == 0xe54b0000	/* strb r(0123),[r11,#-nn] */
-	  || (inst & 0xffffc0f0) == 0xe14b00b0	/* strh r(0123),[r11,#-nn] */
-	  || (inst & 0xffffc000) == 0xe50b0000)	/* str  r(0123),[r11,#-nn] */
-	continue;
-
-      if ((inst & 0xffffc000) == 0xe5cd0000	/* strb r(0123),[sp,#nn] */
-	  || (inst & 0xffffc0f0) == 0xe1cd00b0	/* strh r(0123),[sp,#nn] */
-	  || (inst & 0xffffc000) == 0xe58d0000)	/* str  r(0123),[sp,#nn] */
-	continue;
-
-      /* Un-recognized instruction; stop scanning.  */
-      break;
-    }
-
-  return skip_pc;		/* End of prologue.  */
+  else
+    return arm_analyze_prologue (gdbarch, pc, limit_pc, NULL);
 }
 
 /* *INDENT-OFF* */
@@ -1905,10 +1847,17 @@  arm_analyze_prologue (struct gdbarch *gdbarch,
 	continue;
       else
 	{
-	  /* The optimizer might shove anything into the prologue,
-	     so we just skip what we don't recognize.  */
+	  /* The optimizer might shove anything into the prologue, if
+	     we build up cache (cache != NULL) from scanning prologue,
+	     we just skip what we don't recognize and scan further to
+	     make cache as complete as possible.  However, if we skip
+	     prologue, we'll stop immediately on unrecognized
+	     instruction.  */
 	  unrecognized_pc = current_pc;
-	  continue;
+	  if (cache != NULL)
+	    continue;
+	  else
+	    break;
 	}
     }