Blame SOURCES/gdb-rhbz1125820-ppc64le-enablement-17of37.patch

2c2fa1
commit ef1bc9e72fd2f0310ac3113acc41e1c115e3ac79
2c2fa1
Author: Alan Modra <amodra@gmail.com>
2c2fa1
Date:   Mon Nov 11 14:14:40 2013 +1030
2c2fa1
2c2fa1
    PowerPC64 ELFv2 trampoline match
2c2fa1
    
2c2fa1
    ELFv2 needs different plt call stubs to ELFv1, register usage differs
2c2fa1
    too.  When I added these to ld I changed register usage in the ELFv1
2c2fa1
    stubs as well, simplifying the linker code and (perhaps) future
2c2fa1
    maintenance.  All well and good, but this means gdb needs to cope with
2c2fa1
    more stub variants.  This patch also handles skipping over addis/addi
2c2fa1
    setting up r2 in ELFv2 global entry code.  We want breakpoints to be
2c2fa1
    set past this point to catch calls via the local entry point.
2c2fa1
    
2c2fa1
    	* ppc64-tdep.c (ppc64_plt_entry_point): Renamed from..
2c2fa1
    	(ppc64_desc_entry_point): ..this.  Update comments here and at
2c2fa1
    	call points.
2c2fa1
    	(ppc64_standard_linkage1, ppc64_standard_linkage2,
2c2fa1
    	ppc64_standard_linkage3): Update comments.
2c2fa1
    	(ppc64_standard_linkage4, ppc64_standard_linkage5,
2c2fa1
    	(ppc64_standard_linkage6, ppc64_standard_linkage7): New insn
2c2fa1
    	patterns.
2c2fa1
    	(ppc64_standard_linkage4_target): New function.
2c2fa1
    	(ppc64_skip_trampoline_code): Skip ELFv2 patterns too.
2c2fa1
    	* rs6000-tdep.c (skip_prologue): Skip ELFv2 r2 setup.  Correct
2c2fa1
    	nop match.  Fix comment wrap.
2c2fa1
2c2fa1
Index: gdb-7.6.1/gdb/ppc64-tdep.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/ppc64-tdep.c
2c2fa1
+++ gdb-7.6.1/gdb/ppc64-tdep.c
2c2fa1
@@ -48,21 +48,21 @@
2c2fa1
    | (((spr) & 0x3e0) << 6)                     \
2c2fa1
    | (((xo) & 0x3ff) << 1))
2c2fa1
 
2c2fa1
-/* If DESC is the address of a 64-bit PowerPC FreeBSD function
2c2fa1
-   descriptor, return the descriptor's entry point.  */
2c2fa1
+/* If PLT is the address of a 64-bit PowerPC PLT entry,
2c2fa1
+   return the function's entry point.  */
2c2fa1
 
2c2fa1
 static CORE_ADDR
2c2fa1
-ppc64_desc_entry_point (struct gdbarch *gdbarch, CORE_ADDR desc)
2c2fa1
+ppc64_plt_entry_point (struct gdbarch *gdbarch, CORE_ADDR plt)
2c2fa1
 {
2c2fa1
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
2c2fa1
-  /* The first word of the descriptor is the entry point.  */
2c2fa1
-  return (CORE_ADDR) read_memory_unsigned_integer (desc, 8, byte_order);
2c2fa1
+  /* The first word of the PLT entry is the function entry point.  */
2c2fa1
+  return (CORE_ADDR) read_memory_unsigned_integer (plt, 8, byte_order);
2c2fa1
 }
2c2fa1
 
2c2fa1
 /* Patterns for the standard linkage functions.  These are built by
2c2fa1
    build_plt_stub in bfd/elf64-ppc.c.  */
2c2fa1
 
2c2fa1
-/* Old PLT call stub.  */
2c2fa1
+/* Old ELFv1 PLT call stub.  */
2c2fa1
 
2c2fa1
 static struct ppc_insn_pattern ppc64_standard_linkage1[] =
2c2fa1
   {
2c2fa1
@@ -96,7 +96,7 @@ static struct ppc_insn_pattern ppc64_sta
2c2fa1
     { 0, 0, 0 }
2c2fa1
   };
2c2fa1
 
2c2fa1
-/* Current PLT call stub to access PLT entries more than +/- 32k from r2.
2c2fa1
+/* ELFv1 PLT call stub to access PLT entries more than +/- 32k from r2.
2c2fa1
    Also supports older stub with different placement of std 2,40(1),
2c2fa1
    a stub that omits the std 2,40(1), and both versions of power7
2c2fa1
    thread safety read barriers.  Note that there are actually two more
2c2fa1
@@ -144,7 +144,7 @@ static struct ppc_insn_pattern ppc64_sta
2c2fa1
     { 0, 0, 0 }
2c2fa1
   };
2c2fa1
 
2c2fa1
-/* Current PLT call stub to access PLT entries within +/- 32k of r2.  */
2c2fa1
+/* ELFv1 PLT call stub to access PLT entries within +/- 32k of r2.  */
2c2fa1
 
2c2fa1
 static struct ppc_insn_pattern ppc64_standard_linkage3[] =
2c2fa1
   {
2c2fa1
@@ -181,6 +181,128 @@ static struct ppc_insn_pattern ppc64_sta
2c2fa1
     { 0, 0, 0 }
2c2fa1
   };
2c2fa1
 
2c2fa1
+/* ELFv1 PLT call stub to access PLT entries more than +/- 32k from r2.
2c2fa1
+   A more modern variant of ppc64_standard_linkage2 differing in
2c2fa1
+   register usage.  */
2c2fa1
+
2c2fa1
+static struct ppc_insn_pattern ppc64_standard_linkage4[] =
2c2fa1
+  {
2c2fa1
+    /* std r2, 40(r1) <optional> */
2c2fa1
+    { -1, insn_ds (62, 2, 1, 40, 0), 1 },
2c2fa1
+
2c2fa1
+    /* addis r11, r2, <any> */
2c2fa1
+    { insn_d (-1, -1, -1, 0), insn_d (15, 11, 2, 0), 0 },
2c2fa1
+
2c2fa1
+    /* ld r12, <any>(r11) */
2c2fa1
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 11, 0, 0), 0 },
2c2fa1
+
2c2fa1
+    /* addi r11, r11, <any> <optional> */
2c2fa1
+    { insn_d (-1, -1, -1, 0), insn_d (14, 11, 11, 0), 1 },
2c2fa1
+
2c2fa1
+    /* mtctr r12 */
2c2fa1
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
2c2fa1
+
2c2fa1
+    /* xor r2, r12, r12 <optional> */
2c2fa1
+    { -1, 0x7d826278, 1 },
2c2fa1
+
2c2fa1
+    /* add r11, r11, r2 <optional> */
2c2fa1
+    { -1, 0x7d6b1214, 1 },
2c2fa1
+
2c2fa1
+    /* ld r2, <any>(r11) */
2c2fa1
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 11, 0, 0), 0 },
2c2fa1
+
2c2fa1
+    /* ld r11, <any>(r11) <optional> */
2c2fa1
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 11, 0, 0), 1 },
2c2fa1
+
2c2fa1
+    /* bctr <optional> */
2c2fa1
+    { -1, 0x4e800420, 1 },
2c2fa1
+
2c2fa1
+    /* cmpldi r2, 0 <optional> */
2c2fa1
+    { -1, 0x28220000, 1 },
2c2fa1
+
2c2fa1
+    { 0, 0, 0 }
2c2fa1
+  };
2c2fa1
+
2c2fa1
+/* ELFv1 PLT call stub to access PLT entries within +/- 32k of r2.
2c2fa1
+   A more modern variant of ppc64_standard_linkage3 differing in
2c2fa1
+   register usage.  */
2c2fa1
+
2c2fa1
+static struct ppc_insn_pattern ppc64_standard_linkage5[] =
2c2fa1
+  {
2c2fa1
+    /* std r2, 40(r1) <optional> */
2c2fa1
+    { -1, insn_ds (62, 2, 1, 40, 0), 1 },
2c2fa1
+
2c2fa1
+    /* ld r12, <any>(r2) */
2c2fa1
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 2, 0, 0), 0 },
2c2fa1
+
2c2fa1
+    /* addi r2, r2, <any> <optional> */
2c2fa1
+    { insn_d (-1, -1, -1, 0), insn_d (14, 2, 2, 0), 1 },
2c2fa1
+
2c2fa1
+    /* mtctr r12 */
2c2fa1
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
2c2fa1
+
2c2fa1
+    /* xor r11, r12, r12 <optional> */
2c2fa1
+    { -1, 0x7d8b6278, 1 },
2c2fa1
+
2c2fa1
+    /* add r2, r2, r11 <optional> */
2c2fa1
+    { -1, 0x7c425a14, 1 },
2c2fa1
+
2c2fa1
+    /* ld r11, <any>(r2) <optional> */
2c2fa1
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 11, 2, 0, 0), 1 },
2c2fa1
+
2c2fa1
+    /* ld r2, <any>(r2) */
2c2fa1
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 2, 2, 0, 0), 0 },
2c2fa1
+
2c2fa1
+    /* bctr <optional> */
2c2fa1
+    { -1, 0x4e800420, 1 },
2c2fa1
+
2c2fa1
+    /* cmpldi r2, 0 <optional> */
2c2fa1
+    { -1, 0x28220000, 1 },
2c2fa1
+
2c2fa1
+    { 0, 0, 0 }
2c2fa1
+  };
2c2fa1
+
2c2fa1
+/* ELFv2 PLT call stub to access PLT entries more than +/- 32k from r2.  */
2c2fa1
+
2c2fa1
+static struct ppc_insn_pattern ppc64_standard_linkage6[] =
2c2fa1
+  {
2c2fa1
+    /* std r2, 24(r1) <optional> */
2c2fa1
+    { -1, insn_ds (62, 2, 1, 24, 0), 1 },
2c2fa1
+
2c2fa1
+    /* addis r11, r2, <any> */
2c2fa1
+    { insn_d (-1, -1, -1, 0), insn_d (15, 11, 2, 0), 0 },
2c2fa1
+
2c2fa1
+    /* ld r12, <any>(r11) */
2c2fa1
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 11, 0, 0), 0 },
2c2fa1
+
2c2fa1
+    /* mtctr r12 */
2c2fa1
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
2c2fa1
+
2c2fa1
+    /* bctr */
2c2fa1
+    { -1, 0x4e800420, 0 },
2c2fa1
+
2c2fa1
+    { 0, 0, 0 }
2c2fa1
+  };
2c2fa1
+
2c2fa1
+/* ELFv2 PLT call stub to access PLT entries within +/- 32k of r2.  */
2c2fa1
+
2c2fa1
+static struct ppc_insn_pattern ppc64_standard_linkage7[] =
2c2fa1
+  {
2c2fa1
+    /* std r2, 24(r1) <optional> */
2c2fa1
+    { -1, insn_ds (62, 2, 1, 40, 0), 1 },
2c2fa1
+
2c2fa1
+    /* ld r12, <any>(r2) */
2c2fa1
+    { insn_ds (-1, -1, -1, 0, -1), insn_ds (58, 12, 2, 0, 0), 0 },
2c2fa1
+
2c2fa1
+    /* mtctr r12 */
2c2fa1
+    { insn_xfx (-1, -1, -1, -1), insn_xfx (31, 12, 9, 467), 0 },
2c2fa1
+
2c2fa1
+    /* bctr */
2c2fa1
+    { -1, 0x4e800420, 0 },
2c2fa1
+
2c2fa1
+    { 0, 0, 0 }
2c2fa1
+  };
2c2fa1
+
2c2fa1
 /* When the dynamic linker is doing lazy symbol resolution, the first
2c2fa1
    call to a function in another object will go like this:
2c2fa1
 
2c2fa1
@@ -243,16 +365,14 @@ ppc64_standard_linkage1_target (struct f
2c2fa1
   struct gdbarch *gdbarch = get_frame_arch (frame);
2c2fa1
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2c2fa1
 
2c2fa1
-  /* The address of the function descriptor this linkage function
2c2fa1
-     references.  */
2c2fa1
-  CORE_ADDR desc
2c2fa1
+  /* The address of the PLT entry this linkage function references.  */
2c2fa1
+  CORE_ADDR plt
2c2fa1
     = ((CORE_ADDR) get_frame_register_unsigned (frame,
2c2fa1
 						tdep->ppc_gp0_regnum + 2)
2c2fa1
        + (ppc_insn_d_field (insn[0]) << 16)
2c2fa1
        + ppc_insn_ds_field (insn[2]));
2c2fa1
 
2c2fa1
-  /* The first word of the descriptor is the entry point.  Return that.  */
2c2fa1
-  return ppc64_desc_entry_point (gdbarch, desc);
2c2fa1
+  return ppc64_plt_entry_point (gdbarch, plt);
2c2fa1
 }
2c2fa1
 
2c2fa1
 static CORE_ADDR
2c2fa1
@@ -262,16 +382,14 @@ ppc64_standard_linkage2_target (struct f
2c2fa1
   struct gdbarch *gdbarch = get_frame_arch (frame);
2c2fa1
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2c2fa1
 
2c2fa1
-  /* The address of the function descriptor this linkage function
2c2fa1
-     references.  */
2c2fa1
-  CORE_ADDR desc
2c2fa1
+  /* The address of the PLT entry this linkage function references.  */
2c2fa1
+  CORE_ADDR plt
2c2fa1
     = ((CORE_ADDR) get_frame_register_unsigned (frame,
2c2fa1
 						tdep->ppc_gp0_regnum + 2)
2c2fa1
        + (ppc_insn_d_field (insn[1]) << 16)
2c2fa1
        + ppc_insn_ds_field (insn[3]));
2c2fa1
 
2c2fa1
-  /* The first word of the descriptor is the entry point.  Return that.  */
2c2fa1
-  return ppc64_desc_entry_point (gdbarch, desc);
2c2fa1
+  return ppc64_plt_entry_point (gdbarch, plt);
2c2fa1
 }
2c2fa1
 
2c2fa1
 static CORE_ADDR
2c2fa1
@@ -281,15 +399,28 @@ ppc64_standard_linkage3_target (struct f
2c2fa1
   struct gdbarch *gdbarch = get_frame_arch (frame);
2c2fa1
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2c2fa1
 
2c2fa1
-  /* The address of the function descriptor this linkage function
2c2fa1
-     references.  */
2c2fa1
-  CORE_ADDR desc
2c2fa1
+  /* The address of the PLT entry this linkage function references.  */
2c2fa1
+  CORE_ADDR plt
2c2fa1
     = ((CORE_ADDR) get_frame_register_unsigned (frame,
2c2fa1
 						tdep->ppc_gp0_regnum + 2)
2c2fa1
        + ppc_insn_ds_field (insn[1]));
2c2fa1
 
2c2fa1
-  /* The first word of the descriptor is the entry point.  Return that.  */
2c2fa1
-  return ppc64_desc_entry_point (gdbarch, desc);
2c2fa1
+  return ppc64_plt_entry_point (gdbarch, plt);
2c2fa1
+}
2c2fa1
+
2c2fa1
+static CORE_ADDR
2c2fa1
+ppc64_standard_linkage4_target (struct frame_info *frame,
2c2fa1
+				CORE_ADDR pc, unsigned int *insn)
2c2fa1
+{
2c2fa1
+  struct gdbarch *gdbarch = get_frame_arch (frame);
2c2fa1
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
2c2fa1
+
2c2fa1
+  CORE_ADDR plt
2c2fa1
+    = ((CORE_ADDR) get_frame_register_unsigned (frame, tdep->ppc_gp0_regnum + 2)
2c2fa1
+       + (ppc_insn_d_field (insn[1]) << 16)
2c2fa1
+       + ppc_insn_ds_field (insn[2]));
2c2fa1
+
2c2fa1
+  return ppc64_plt_entry_point (gdbarch, plt);
2c2fa1
 }
2c2fa1
 
2c2fa1
 
2c2fa1
@@ -300,13 +431,27 @@ CORE_ADDR
2c2fa1
 ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
2c2fa1
 {
2c2fa1
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
2c2fa1
-  unsigned int insns[MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage1),
2c2fa1
-			       ARRAY_SIZE (ppc64_standard_linkage2)),
2c2fa1
-			  ARRAY_SIZE (ppc64_standard_linkage3)) - 1];
2c2fa1
+  unsigned int insns[MAX (MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage1),
2c2fa1
+				    ARRAY_SIZE (ppc64_standard_linkage2)),
2c2fa1
+			       MAX (ARRAY_SIZE (ppc64_standard_linkage3),
2c2fa1
+				    ARRAY_SIZE (ppc64_standard_linkage4))),
2c2fa1
+			  MAX (MAX (ARRAY_SIZE (ppc64_standard_linkage5),
2c2fa1
+				    ARRAY_SIZE (ppc64_standard_linkage6)),
2c2fa1
+			       ARRAY_SIZE (ppc64_standard_linkage7))) - 1];
2c2fa1
   CORE_ADDR target;
2c2fa1
 
2c2fa1
-  if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3, insns)
2c2fa1
-      && (insns[8] != 0 || insns[9] != 0))
2c2fa1
+  if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage7, insns))
2c2fa1
+    pc = ppc64_standard_linkage3_target (frame, pc, insns);
2c2fa1
+  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage6, insns))
2c2fa1
+    pc = ppc64_standard_linkage4_target (frame, pc, insns);
2c2fa1
+  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage5, insns)
2c2fa1
+	   && (insns[8] != 0 || insns[9] != 0))
2c2fa1
+    pc = ppc64_standard_linkage3_target (frame, pc, insns);
2c2fa1
+  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage4, insns)
2c2fa1
+	   && (insns[9] != 0 || insns[10] != 0))
2c2fa1
+    pc = ppc64_standard_linkage4_target (frame, pc, insns);
2c2fa1
+  else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage3, insns)
2c2fa1
+	   && (insns[8] != 0 || insns[9] != 0))
2c2fa1
     pc = ppc64_standard_linkage3_target (frame, pc, insns);
2c2fa1
   else if (ppc_insns_match_pattern (frame, pc, ppc64_standard_linkage2, insns)
2c2fa1
 	   && (insns[10] != 0 || insns[11] != 0))
2c2fa1
Index: gdb-7.6.1/gdb/rs6000-tdep.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/rs6000-tdep.c
2c2fa1
+++ gdb-7.6.1/gdb/rs6000-tdep.c
2c2fa1
@@ -1667,7 +1667,19 @@ skip_prologue (struct gdbarch *gdbarch,
2c2fa1
 	  continue;
2c2fa1
 
2c2fa1
 	}
2c2fa1
-      else if ((op & 0xffff0000) == 0x60000000)
2c2fa1
+      else if ((op & 0xffff0000) == 0x3c4c0000
2c2fa1
+	       || (op & 0xffff0000) == 0x3c400000
2c2fa1
+	       || (op & 0xffff0000) == 0x38420000)
2c2fa1
+	{
2c2fa1
+	  /* .	0:	addis 2,12,.TOC.-0b@ha
2c2fa1
+	     .		addi 2,2,.TOC.-0b@l
2c2fa1
+	     or
2c2fa1
+	     .		lis 2,.TOC.@ha
2c2fa1
+	     .		addi 2,2,.TOC.@l
2c2fa1
+	     used by ELFv2 global entry points to set up r2.  */
2c2fa1
+	  continue;
2c2fa1
+	}
2c2fa1
+      else if (op == 0x60000000)
2c2fa1
         {
2c2fa1
 	  /* nop */
2c2fa1
 	  /* Allow nops in the prologue, but do not consider them to
2c2fa1
@@ -1678,8 +1690,7 @@ skip_prologue (struct gdbarch *gdbarch,
2c2fa1
 
2c2fa1
 	}
2c2fa1
       else if ((op & 0xffff0000) == 0x3c000000)
2c2fa1
-	{			/* addis 0,0,NUM, used
2c2fa1
-				   for >= 32k frames */
2c2fa1
+	{			/* addis 0,0,NUM, used for >= 32k frames */
2c2fa1
 	  fdata->offset = (op & 0x0000ffff) << 16;
2c2fa1
 	  fdata->frameless = 0;
2c2fa1
           r0_contains_arg = 0;
2c2fa1
@@ -1687,8 +1698,7 @@ skip_prologue (struct gdbarch *gdbarch,
2c2fa1
 
2c2fa1
 	}
2c2fa1
       else if ((op & 0xffff0000) == 0x60000000)
2c2fa1
-	{			/* ori 0,0,NUM, 2nd ha
2c2fa1
-				   lf of >= 32k frames */
2c2fa1
+	{			/* ori 0,0,NUM, 2nd half of >= 32k frames */
2c2fa1
 	  fdata->offset |= (op & 0x0000ffff);
2c2fa1
 	  fdata->frameless = 0;
2c2fa1
           r0_contains_arg = 0;