Improve arm_skip_prologue by using arm_analyze_prologue
authorYao Qi <yao@codesourcery.com>
Thu, 27 Nov 2014 03:37:54 +0000 (11:37 +0800)
committerYao Qi <yao@codesourcery.com>
Fri, 12 Dec 2014 00:46:34 +0000 (08:46 +0800)
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.

gdb:

2014-12-12  Yao Qi  <yao@codesourcery.com>

PR tdep/14261
* 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/ChangeLog
gdb/arm-tdep.c

index c444ce77c07d21deb88a2291deff5668839b00b0..bf1f80b58b6887a11faabee22f422cba2978f9e7 100644 (file)
@@ -1,3 +1,12 @@
+2014-12-12  Yao Qi  <yao@codesourcery.com>
+
+       PR tdep/14261
+       * 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.
+
 2014-12-12  Yao Qi  <yao@codesourcery.com>
 
        * arm-tdep.c (arm_instruction_restores_sp): New function.
index 34070452e1731be227b4af81011933a3643fcb5a..a4f99c58fb5c6b4b2fc26e149b2ced6d46fe88a9 100644 (file)
@@ -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;
        }
     }