S390: Recognize special jumps in prologue parser

Message ID m3wppe1tdj.fsf@oc1027705133.ibm.com
State New, archived
Headers

Commit Message

Andreas Arnez March 7, 2016, 10:20 a.m. UTC
  Functions compiled with the gcc option `-mhotpatch' may start with a
branch-never BRCL instruction as a 6-byte NOP.  And functions compiled
with `-mstack-size' contain a BRC instruction in their prologue that is
actually a conditional trap.  Both of these special jumps cause the
prologue parser to stop and yield bad unwinding results.

This change makes the prologue analyzer recognize such special jumps and
ignore them.

gdb/ChangeLog:

	* s390-linux-tdep.c (s390_analyze_prologue): Ignore BRC and BRCL
	instructions that do nothing or are conditional traps.
---
 gdb/s390-linux-tdep.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
  

Comments

Andreas Arnez March 9, 2016, 4:16 p.m. UTC | #1
Pushed.

On Mon, Mar 07 2016, Andreas Arnez wrote:

> Functions compiled with the gcc option `-mhotpatch' may start with a
> branch-never BRCL instruction as a 6-byte NOP.  And functions compiled
> with `-mstack-size' contain a BRC instruction in their prologue that is
> actually a conditional trap.  Both of these special jumps cause the
> prologue parser to stop and yield bad unwinding results.
>
> This change makes the prologue analyzer recognize such special jumps and
> ignore them.
>
> gdb/ChangeLog:
>
> 	* s390-linux-tdep.c (s390_analyze_prologue): Ignore BRC and BRCL
> 	instructions that do nothing or are conditional traps.
  

Patch

diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index 155bc66..950696e 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -1567,13 +1567,25 @@  s390_analyze_prologue (struct gdbarch *gdbarch,
 	    break;
 	}
 
+      /* BRC/BRCL -- branch relative on condition.  Ignore "branch
+	 never", branch to following instruction, and "conditional
+	 trap" (BRC +2).  Otherwise terminate search.  */
+      else if (is_ri (insn, op1_brc, op2_brc, &r1, &i2))
+	{
+	  if (r1 != 0 && i2 != 1 && i2 != 2)
+	    break;
+	}
+      else if (is_ril (insn, op1_brcl, op2_brcl, &r1, &i2))
+	{
+	  if (r1 != 0 && i2 != 3)
+	    break;
+	}
+
       /* Terminate search when hitting any other branch instruction.  */
       else if (is_rr (insn, op_basr, &r1, &r2)
 	       || is_rx (insn, op_bas, &r1, &d2, &x2, &b2)
 	       || is_rr (insn, op_bcr, &r1, &r2)
 	       || is_rx (insn, op_bc, &r1, &d2, &x2, &b2)
-	       || is_ri (insn, op1_brc, op2_brc, &r1, &i2)
-	       || is_ril (insn, op1_brcl, op2_brcl, &r1, &i2)
 	       || is_ril (insn, op1_brasl, op2_brasl, &r2, &i2))
 	break;