2002-05-02 Pierre Muller <muller@ics.u-strasbg.fr>
[deliverable/binutils-gdb.git] / gdb / alpha-tdep.c
index ef0b2cd5ef54ddb1280d0192e121ce1284ee0b09..6f5209782faf68dbc5ed3da2b97c093189e27a23 100644 (file)
@@ -59,6 +59,8 @@ static gdbarch_extract_struct_value_address_ftype
     alpha_extract_struct_value_address;
 static gdbarch_use_struct_convention_ftype alpha_use_struct_convention;
 
+static gdbarch_breakpoint_from_pc_ftype alpha_breakpoint_from_pc;
+
 static gdbarch_frame_args_address_ftype alpha_frame_args_address;
 static gdbarch_frame_locals_address_ftype alpha_frame_locals_address;
 
@@ -76,6 +78,8 @@ static gdbarch_fix_call_dummy_ftype alpha_fix_call_dummy;
 static gdbarch_init_frame_pc_first_ftype alpha_init_frame_pc_first;
 static gdbarch_init_extra_frame_info_ftype alpha_init_extra_frame_info;
 
+static gdbarch_get_longjmp_target_ftype alpha_get_longjmp_target;
+
 struct frame_extra_info
   {
     alpha_extra_func_info_t proc_desc;
@@ -193,12 +197,6 @@ struct linked_proc_info
   }
  *linked_proc_desc_table = NULL;
 \f
-int
-alpha_osf_in_sigtramp (CORE_ADDR pc, char *func_name)
-{
-  return (func_name != NULL && STREQ ("__sigtramp", func_name));
-}
-
 static CORE_ADDR
 alpha_frame_past_sigtramp_frame (struct frame_info *frame, CORE_ADDR pc)
 {
@@ -346,6 +344,17 @@ alpha_register_virtual_size (int regno)
 }
 \f
 
+static CORE_ADDR
+alpha_sigcontext_addr (struct frame_info *fi)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+  if (tdep->sigcontext_addr)
+    return (tdep->sigcontext_addr (fi));
+
+  return (0);
+}
+
 /* Guaranteed to set frame->saved_regs to some values (it never leaves it
    NULL).  */
 
@@ -374,7 +383,12 @@ alpha_find_saved_regs (struct frame_info *frame)
     {
       CORE_ADDR sigcontext_addr;
 
-      sigcontext_addr = SIGCONTEXT_ADDR (frame);
+      sigcontext_addr = alpha_sigcontext_addr (frame);
+      if (sigcontext_addr == 0)
+       {
+         /* Don't know where the sigcontext is; just bail.  */
+         return;
+       }
       for (ireg = 0; ireg < 32; ireg++)
        {
          reg_position = sigcontext_addr + SIGFRAME_REGSAVE_OFF + ireg * 8;
@@ -1358,16 +1372,15 @@ alpha_skip_prologue_internal (CORE_ADDR pc, int lenient)
   CORE_ADDR post_prologue_pc;
   char buf[4];
 
-#ifdef GDB_TARGET_HAS_SHARED_LIBS
   /* Silently return the unaltered pc upon memory errors.
      This could happen on OSF/1 if decode_line_1 tries to skip the
      prologue for quickstarted shared library functions when the
      shared library is not yet mapped in.
      Reading target memory is slow over serial lines, so we perform
-     this check only if the target has shared libraries.  */
+     this check only if the target has shared libraries (which all
+     Alpha targets do).  */
   if (target_read_memory (pc, buf, 4))
     return pc;
-#endif
 
   /* See if we can determine the end of the prologue via the symbol table.
      If so, then return either PC, or the PC after the prologue, whichever
@@ -1502,6 +1515,16 @@ alpha_register_convert_to_raw (struct type *valtype, int regnum,
     error ("Cannot store value in floating point register");
 }
 
+static const unsigned char *
+alpha_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+{
+  static const unsigned char alpha_breakpoint[] =
+    { 0x80, 0, 0, 0 }; /* call_pal bpt */
+
+  *lenptr = sizeof(alpha_breakpoint);
+  return (alpha_breakpoint);
+}
+
 /* Given a return value in `regbuf' with a type `valtype', 
    extract and copy its value into `valbuf'.  */
 
@@ -1611,6 +1634,28 @@ alpha_extract_struct_value_address (char *regbuf)
                           REGISTER_RAW_SIZE (ALPHA_V0_REGNUM)));
 }
 
+/* Figure out where the longjmp will land.
+   We expect the first arg to be a pointer to the jmp_buf structure from
+   which we extract the PC (JB_PC) that we will land at.  The PC is copied
+   into the "pc".  This routine returns true on success.  */
+
+static int
+alpha_get_longjmp_target (CORE_ADDR *pc)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  CORE_ADDR jb_addr;
+  char raw_buffer[ALPHA_MAX_REGISTER_RAW_SIZE];
+
+  jb_addr = read_register (ALPHA_A0_REGNUM);
+
+  if (target_read_memory (jb_addr + (tdep->jb_pc * tdep->jb_elt_size),
+                         raw_buffer, tdep->jb_elt_size))
+    return 0;
+
+  *pc = extract_address (raw_buffer, tdep->jb_elt_size);
+  return 1;
+}
+
 /* alpha_software_single_step() is called just before we want to resume
    the inferior, if we want to single-step it but there is no hardware
    or kernel single-step support (NetBSD on Alpha, for example).  We find
@@ -1968,6 +2013,9 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   tdep->dynamic_sigtramp_offset = NULL;
   tdep->skip_sigtramp_frame = NULL;
+  tdep->sigcontext_addr = NULL;
+
+  tdep->jb_pc = -1;    /* longjmp support not enabled by default  */
 
   /* Type sizes */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -2067,7 +2115,10 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_coerce_float_to_double (gdbarch,
                                       standard_coerce_float_to_double);
 
+  set_gdbarch_breakpoint_from_pc (gdbarch, alpha_breakpoint_from_pc);
   set_gdbarch_decr_pc_after_break (gdbarch, 4);
+
+  set_gdbarch_function_start_offset (gdbarch, 0);
   set_gdbarch_frame_args_skip (gdbarch, 0);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
@@ -2104,6 +2155,12 @@ alpha_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        }
     }
 
+  /* Now that we have tuned the configuration, set a few final things
+     based on what the OS ABI has told us.  */
+
+  if (tdep->jb_pc >= 0)
+    set_gdbarch_get_longjmp_target (gdbarch, alpha_get_longjmp_target);
+
   return gdbarch;
 }
 
@@ -2125,6 +2182,13 @@ alpha_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "alpha_dump_tdep: vm_min_address = 0x%lx\n",
                      (long) tdep->vm_min_address);
+
+  fprintf_unfiltered (file,
+                     "alpha_dump_tdep: jb_pc = %d\n",
+                     tdep->jb_pc);
+  fprintf_unfiltered (file,
+                     "alpha_dump_tdep: jb_elt_size = %ld\n",
+                     (long) tdep->jb_elt_size);
 }
 
 void
This page took 0.026421 seconds and 4 git commands to generate.