gdb.ada/info_exc.exp: Adjust expected output in "info exception" test.
[deliverable/binutils-gdb.git] / gdb / ppc-linux-tdep.c
index dcfd3bb9f9746377499bf8edf03601ddbcca46f1..4bdd13e2b0b11c6095ea71fcc01439cff6bce641 100644 (file)
@@ -51,6 +51,7 @@
 #include "linux-tdep.h"
 #include "linux-record.h"
 #include "record-full.h"
+#include "infrun.h"
 
 #include "stap-probe.h"
 #include "ax.h"
@@ -304,7 +305,12 @@ powerpc_linux_in_dynsym_resolve_code (CORE_ADDR pc)
   return 0;
 }
 
-/* Follow PLT stub to actual routine.  */
+/* Follow PLT stub to actual routine.
+
+   When the execution direction is EXEC_REVERSE, scan backward to
+   check whether we are in the middle of a PLT stub.  Currently,
+   we only look-behind at most 4 instructions (the max length of PLT
+   stub sequence.  */
 
 static CORE_ADDR
 ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
@@ -314,31 +320,50 @@ ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR target = 0;
+  int scan_limit, i;
 
-  if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
-    {
-      /* Insn pattern is
-               lis   r11, xxxx
-               lwz   r11, xxxx(r11)
-        Branch target is in r11.  */
-
-      target = (ppc_insn_d_field (insnbuf[0]) << 16)
-       | ppc_insn_d_field (insnbuf[1]);
-      target = read_memory_unsigned_integer (target, 4, byte_order);
-    }
+  scan_limit = 1;
+  /* When reverse-debugging, scan backward to check whether we are
+     in the middle of trampoline code.  */
+  if (execution_direction == EXEC_REVERSE)
+    scan_limit = 4;    /* At more 4 instructions.  */
 
-  if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so, insnbuf))
+  for (i = 0; i < scan_limit; i++)
     {
-      /* Insn pattern is
-               lwz   r11, xxxx(r30)
-        Branch target is in r11.  */
+      if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
+       {
+         /* Insn pattern is
+            lis   r11, xxxx
+            lwz   r11, xxxx(r11)
+            Branch target is in r11.  */
+
+         target = (ppc_insn_d_field (insnbuf[0]) << 16)
+                  | ppc_insn_d_field (insnbuf[1]);
+         target = read_memory_unsigned_integer (target, 4, byte_order);
+       }
+      else if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so,
+                                       insnbuf))
+       {
+         /* Insn pattern is
+            lwz   r11, xxxx(r30)
+            Branch target is in r11.  */
+
+         target = get_frame_register_unsigned (frame,
+                                               tdep->ppc_gp0_regnum + 30)
+                  + ppc_insn_d_field (insnbuf[0]);
+         target = read_memory_unsigned_integer (target, 4, byte_order);
+       }
+      else
+       {
+         /* Scan backward one more instructions if doesn't match.  */
+         pc -= 4;
+         continue;
+       }
 
-      target = get_frame_register_unsigned (frame, tdep->ppc_gp0_regnum + 30)
-              + ppc_insn_d_field (insnbuf[0]);
-      target = read_memory_unsigned_integer (target, 4, byte_order);
+      return target;
     }
 
-  return target;
+  return 0;
 }
 
 /* Wrappers to handle Linux-only registers.  */
@@ -678,47 +703,6 @@ static struct tramp_frame ppc64_linux_sighandler_tramp_frame = {
   ppc64_linux_sighandler_cache_init
 };
 
-
-/* Address to use for displaced stepping.  When debugging a stand-alone
-   SPU executable, entry_point_address () will point to an SPU local-store
-   address and is thus not usable as displaced stepping location.  We use
-   the auxiliary vector to determine the PowerPC-side entry point address
-   instead.  */
-
-static CORE_ADDR ppc_linux_entry_point_addr = 0;
-
-static void
-ppc_linux_inferior_created (struct target_ops *target, int from_tty)
-{
-  ppc_linux_entry_point_addr = 0;
-}
-
-static CORE_ADDR
-ppc_linux_displaced_step_location (struct gdbarch *gdbarch)
-{
-  if (ppc_linux_entry_point_addr == 0)
-    {
-      CORE_ADDR addr;
-
-      /* Determine entry point from target auxiliary vector.  */
-      if (target_auxv_search (&current_target, AT_ENTRY, &addr) <= 0)
-       error (_("Cannot find AT_ENTRY auxiliary vector entry."));
-
-      /* Make certain that the address points at real code, and not a
-        function descriptor.  */
-      addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
-                                                &current_target);
-
-      /* Inferior calls also use the entry point as a breakpoint location.
-        We don't want displaced stepping to interfere with those
-        breakpoints, so leave space.  */
-      ppc_linux_entry_point_addr = addr + 2 * PPC_INSN_SIZE;
-    }
-
-  return ppc_linux_entry_point_addr;
-}
-
-
 /* Return 1 if PPC_ORIG_R3_REGNUM and PPC_TRAP_REGNUM are usable.  */
 int
 ppc_linux_trap_reg_p (struct gdbarch *gdbarch)
@@ -771,11 +755,16 @@ ppc_linux_get_syscall_number (struct gdbarch *gdbarch,
 static struct linux_record_tdep ppc_linux_record_tdep;
 static struct linux_record_tdep ppc64_linux_record_tdep;
 
+/* ppc_canonicalize_syscall maps from the native PowerPC Linux set of
+   syscall ids into a canonical set of syscall ids used by process
+   record.  (See arch/powerpc/include/uapi/asm/unistd.h in kernel tree.)
+   Return -1 if this system call is not supported by process record.
+   Otherwise, return the syscall number for preocess reocrd of given
+   SYSCALL.  */
+
 static enum gdb_syscall
 ppc_canonicalize_syscall (int syscall)
 {
-  /* See arch/powerpc/include/uapi/asm/unistd.h */
-
   if (syscall <= 165)
     return syscall;
   else if (syscall >= 167 && syscall <= 190)   /* Skip query_module 166 */
@@ -801,6 +790,9 @@ ppc_canonicalize_syscall (int syscall)
   return -1;
 }
 
+/* Record registers which might be clobbered during system call.
+   Return 0 if successful.  */
+
 static int
 ppc_linux_syscall_record (struct regcache *regcache)
 {
@@ -881,6 +873,9 @@ ppc_linux_syscall_record (struct regcache *regcache)
   return 0;
 }
 
+/* Record registers which might be clobbered during signal handling.
+   Return 0 if successful.  */
+
 static int
 ppc_linux_record_signal (struct gdbarch *gdbarch, struct regcache *regcache,
                         enum gdb_signal signal)
@@ -949,7 +944,7 @@ ppc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
 static int
 ppc_linux_spu_section (bfd *abfd, asection *asect, void *user_data)
 {
-  return strncmp (bfd_section_name (abfd, asect), "SPU/", 4) == 0;
+  return startswith (bfd_section_name (abfd, asect), "SPU/");
 }
 
 static const struct target_desc *
@@ -1195,9 +1190,8 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order,
   if (!ptid_equal (spe_context_cache_ptid, inferior_ptid))
     {
       struct target_ops *target = &current_target;
-      volatile struct gdb_exception ex;
 
-      TRY_CATCH (ex, RETURN_MASK_ERROR)
+      TRY
        {
          /* We do not call target_translate_tls_address here, because
             svr4_fetch_objfile_link_map may invalidate the frame chain,
@@ -1212,8 +1206,11 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order,
          spe_context_cache_ptid = inferior_ptid;
        }
 
-      if (ex.reason < 0)
-       return 0;
+      CATCH (ex, RETURN_MASK_ERROR)
+       {
+         return 0;
+       }
+      END_CATCH
     }
 
   /* Read variable value.  */
@@ -1397,7 +1394,9 @@ static const struct frame_unwind ppu2spu_unwind = {
   ppu2spu_prev_arch,
 };
 
-/* Initialize linux_record_tdep if not initialized yet.  */
+/* Initialize linux_record_tdep if not initialized yet.
+   WORDSIZE is 4 or 8 for 32- or 64-bit PowerPC Linux respectively.
+   Sizes of data structures are initialized accordingly.  */
 
 static void
 ppc_init_linux_record_tdep (struct linux_record_tdep *record_tdep,
@@ -1797,14 +1796,10 @@ ppc_linux_init_abi (struct gdbarch_info info,
 
       /* Cell/B.E. cross-architecture unwinder support.  */
       frame_unwind_prepend_unwinder (gdbarch, &ppu2spu_unwind);
-
-      /* The default displaced_step_at_entry_point doesn't work for
-        SPU stand-alone executables.  */
-      set_gdbarch_displaced_step_location (gdbarch,
-                                          ppc_linux_displaced_step_location);
     }
 
-  set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
+  set_gdbarch_displaced_step_location (gdbarch,
+                                      linux_displaced_step_location);
 
   /* Support reverse debugging.  */
   set_gdbarch_process_record (gdbarch, ppc_process_record);
@@ -1830,9 +1825,6 @@ _initialize_ppc_linux_tdep (void)
   gdbarch_register_osabi (bfd_arch_rs6000, bfd_mach_rs6k, GDB_OSABI_LINUX,
                          ppc_linux_init_abi);
 
-  /* Attach to inferior_created observer.  */
-  observer_attach_inferior_created (ppc_linux_inferior_created);
-
   /* Attach to observers to track __spe_current_active_context.  */
   observer_attach_inferior_created (ppc_linux_spe_context_inferior_created);
   observer_attach_solib_loaded (ppc_linux_spe_context_solib_loaded);
This page took 0.032122 seconds and 4 git commands to generate.