Improve arm_skip_prologue by using arm_analyze_prologue

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.
This commit is contained in:
Yao Qi 2014-11-27 11:37:54 +08:00
parent f303bc3e6c
commit 21daaaaffc
2 changed files with 21 additions and 63 deletions

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

View 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;
}
}