4c2ad1
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
4c2ad1
From: Andrew Cagney <cagney@gnu.org>
4c2ad1
Date: Fri, 27 Oct 2017 21:07:50 +0200
4c2ad1
Subject: gdb-6.3-ppc64syscall-20040622.patch
4c2ad1
4c2ad1
;; Better parse 64-bit PPC system call prologues.
4c2ad1
;;=push: Write new testcase.
4c2ad1
4c2ad1
2004-06-22  Andrew Cagney  <cagney@gnu.org>
4c2ad1
4c2ad1
	* rs6000-tdep.c (struct rs6000_framedata): Add field "func_start".
4c2ad1
	(skip_prologue): Delete local variable "orig_pc", use
4c2ad1
	"func_start".  Add local variable "num_skip_linux_syscall_insn",
4c2ad1
	use to skip over first half of a GNU/Linux syscall and update
4c2ad1
	"func_start".
4c2ad1
4c2ad1
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
4c2ad1
--- a/gdb/rs6000-tdep.c
4c2ad1
+++ b/gdb/rs6000-tdep.c
4c2ad1
@@ -134,6 +134,7 @@ static const char *powerpc_vector_abi_string = "auto";
4c2ad1
 
4c2ad1
 struct rs6000_framedata
4c2ad1
   {
4c2ad1
+    CORE_ADDR func_start;	/* True function start.  */
4c2ad1
     int offset;			/* total size of frame --- the distance
4c2ad1
 				   by which we decrement sp to allocate
4c2ad1
 				   the frame */
4c2ad1
@@ -1426,7 +1427,6 @@ static CORE_ADDR
4c2ad1
 skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
4c2ad1
 	       struct rs6000_framedata *fdata)
4c2ad1
 {
4c2ad1
-  CORE_ADDR orig_pc = pc;
4c2ad1
   CORE_ADDR last_prologue_pc = pc;
4c2ad1
   CORE_ADDR li_found_pc = 0;
4c2ad1
   gdb_byte buf[4];
4c2ad1
@@ -1445,12 +1445,14 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
4c2ad1
   int minimal_toc_loaded = 0;
4c2ad1
   int prev_insn_was_prologue_insn = 1;
4c2ad1
   int num_skip_non_prologue_insns = 0;
4c2ad1
+  int num_skip_ppc64_gnu_linux_syscall_insn = 0;
4c2ad1
   int r0_contains_arg = 0;
4c2ad1
   const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch);
4c2ad1
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
4c2ad1
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
4c2ad1
 
4c2ad1
   memset (fdata, 0, sizeof (struct rs6000_framedata));
4c2ad1
+  fdata->func_start = pc;
4c2ad1
   fdata->saved_gpr = -1;
4c2ad1
   fdata->saved_fpr = -1;
4c2ad1
   fdata->saved_vr = -1;
4c2ad1
@@ -1484,6 +1486,55 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
4c2ad1
 	break;
4c2ad1
       op = extract_unsigned_integer (buf, 4, byte_order);
4c2ad1
 
4c2ad1
+      /* A PPC64 GNU/Linux system call function is split into two
4c2ad1
+	 sub-functions: a non-threaded fast-path (__NAME_nocancel)
4c2ad1
+	 which does not use a frame; and a threaded slow-path
4c2ad1
+	 (Lpseudo_cancel) that does create a frame.  Ref:
4c2ad1
+	 nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h
4c2ad1
+
4c2ad1
+	 *INDENT-OFF*
4c2ad1
+	 NAME:
4c2ad1
+	 	SINGLE_THREAD_P
4c2ad1
+	 	bne- .Lpseudo_cancel
4c2ad1
+	 __NAME_nocancel:
4c2ad1
+	 	li r0,162
4c2ad1
+	 	sc
4c2ad1
+	 	bnslr+
4c2ad1
+	 	b 0x7fe014ef64 <.__syscall_error>
4c2ad1
+	 Lpseudo_cancel:
4c2ad1
+	 	stdu r1,-128(r1)
4c2ad1
+	 	...
4c2ad1
+	 *INDENT-ON*
4c2ad1
+
4c2ad1
+	 Unfortunatly, because the latter case uses a local label (not
4c2ad1
+	 in the symbol table) a PC in "Lpseudo_cancel" appears to be
4c2ad1
+	 in "__NAME_nocancel".  The following code recognizes this,
4c2ad1
+	 adjusting FUNC_START to point to where "Lpseudo_cancel"
4c2ad1
+	 should be, and parsing the prologue sequence as if
4c2ad1
+	 "Lpseudo_cancel" was the entry point.  */
4c2ad1
+
4c2ad1
+      if (((op & 0xffff0000) == 0x38000000 /* li r0,N */
4c2ad1
+	   && pc == fdata->func_start + 0
4c2ad1
+	   && num_skip_ppc64_gnu_linux_syscall_insn == 0)
4c2ad1
+	  || (op == 0x44000002 /* sc */
4c2ad1
+	      && pc == fdata->func_start + 4
4c2ad1
+	      && num_skip_ppc64_gnu_linux_syscall_insn == 1)
4c2ad1
+	  || (op == 0x4ca30020 /* bnslr+ */
4c2ad1
+	      && pc == fdata->func_start + 8
4c2ad1
+	      && num_skip_ppc64_gnu_linux_syscall_insn == 2))
4c2ad1
+	{
4c2ad1
+	  num_skip_ppc64_gnu_linux_syscall_insn++;
4c2ad1
+	  continue;
4c2ad1
+	}
4c2ad1
+      else if ((op & 0xfc000003) == 0x48000000 /* b __syscall_error */
4c2ad1
+	       && pc == fdata->func_start + 12
4c2ad1
+	       && num_skip_ppc64_gnu_linux_syscall_insn == 3)
4c2ad1
+	{
4c2ad1
+	  num_skip_ppc64_gnu_linux_syscall_insn = -1;
4c2ad1
+	  fdata->func_start = pc;
4c2ad1
+	  continue;
4c2ad1
+	}
4c2ad1
+
4c2ad1
       if ((op & 0xfc1fffff) == 0x7c0802a6)
4c2ad1
 	{			/* mflr Rx */
4c2ad1
 	  /* Since shared library / PIC code, which needs to get its
4c2ad1
@@ -1673,9 +1724,9 @@ skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR lim_pc,
4c2ad1
 	     we have no line table information or the line info tells
4c2ad1
 	     us that the subroutine call is not part of the line
4c2ad1
 	     associated with the prologue.  */
4c2ad1
-	  if ((pc - orig_pc) > 8)
4c2ad1
+	  if ((pc - fdata->func_start) > 8)
4c2ad1
 	    {
4c2ad1
-	      struct symtab_and_line prologue_sal = find_pc_line (orig_pc, 0);
4c2ad1
+	      struct symtab_and_line prologue_sal = find_pc_line (fdata->func_start, 0);
4c2ad1
 	      struct symtab_and_line this_sal = find_pc_line (pc, 0);
4c2ad1
 
4c2ad1
 	      if ((prologue_sal.line == 0)