2004-04-22 Randolph Chung <tausq@debian.org>
[deliverable/binutils-gdb.git] / gdb / hppa-tdep.c
index 3d4a4d123a9f636892e30ba34a4db2d62c59aa59..26b73dc551c3fd0fe2f606001c5ad59bc772e64a 100644 (file)
 #include "objfiles.h"
 #include "hppa-tdep.h"
 
+static int hppa_debug = 0;
+
 /* Some local constants.  */
 static const int hppa32_num_regs = 128;
 static const int hppa64_num_regs = 96;
 
+/* hppa-specific object data -- unwind and solib info.
+   TODO/maybe: think about splitting this into two parts; the unwind data is 
+   common to all hppa targets, but is only used in this file; we can register 
+   that separately and make this static. The solib data is probably hpux-
+   specific, so we can create a separate extern objfile_data that is registered
+   by hppa-hpux-tdep.c and shared with pa64solib.c and somsolib.c.  */
+const struct objfile_data *hppa_objfile_priv_data = NULL;
+
 /* Get at various relevent fields of an instruction word. */
 #define MASK_5 0x1f
 #define MASK_11 0x7ff
@@ -66,8 +76,8 @@ static const int hppa64_num_regs = 96;
 
 /* Define offsets into the call dummy for the _sr4export address.
    See comments related to CALL_DUMMY for more info.  */
-#define SR4EXPORT_LDIL_OFFSET (INSTRUCTION_SIZE * 12)
-#define SR4EXPORT_LDO_OFFSET (INSTRUCTION_SIZE * 13)
+#define SR4EXPORT_LDIL_OFFSET (HPPA_INSTRUCTION_SIZE * 12)
+#define SR4EXPORT_LDO_OFFSET (HPPA_INSTRUCTION_SIZE * 13)
 
 /* To support detection of the pseudo-initial frame
    that threads have. */
@@ -121,17 +131,8 @@ static void internalize_unwinds (struct objfile *,
 static void record_text_segment_lowaddr (bfd *, asection *, void *);
 /* FIXME: brobecker 2002-11-07: We will likely be able to make the
    following functions static, once we hppa is partially multiarched.  */
-int hppa_reg_struct_has_addr (int gcc_p, struct type *type);
-CORE_ADDR hppa_skip_prologue (CORE_ADDR pc);
-CORE_ADDR hppa_skip_trampoline_code (CORE_ADDR pc);
-int hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name);
-int hppa_in_solib_return_trampoline (CORE_ADDR pc, char *name);
 int hppa_pc_requires_run_before_use (CORE_ADDR pc);
 int hppa_instruction_nullified (void);
-int hppa_cannot_store_register (int regnum);
-CORE_ADDR hppa_smash_text_address (CORE_ADDR addr);
-CORE_ADDR hppa_target_read_pc (ptid_t ptid);
-void hppa_target_write_pc (CORE_ADDR v, ptid_t ptid);
 
 /* Handle 32/64-bit struct return conventions.  */
 
@@ -352,15 +353,18 @@ compare_unwind_entries (const void *arg1, const void *arg2)
     return 0;
 }
 
-static CORE_ADDR low_text_segment_address;
-
 static void
-record_text_segment_lowaddr (bfd *abfd, asection *section, void *ignored)
+record_text_segment_lowaddr (bfd *abfd, asection *section, void *data)
 {
-  if (((section->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
+  if ((section->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
        == (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
-      && section->vma < low_text_segment_address)
-    low_text_segment_address = section->vma;
+    {
+      bfd_vma value = section->vma - section->filepos;
+      CORE_ADDR *low_text_segment_address = (CORE_ADDR *)data;
+
+      if (value < *low_text_segment_address)
+          *low_text_segment_address = value;
+    }
 }
 
 static void
@@ -370,30 +374,29 @@ internalize_unwinds (struct objfile *objfile, struct unwind_table_entry *table,
 {
   /* We will read the unwind entries into temporary memory, then
      fill in the actual unwind table.  */
+
   if (size > 0)
     {
       unsigned long tmp;
       unsigned i;
       char *buf = alloca (size);
+      CORE_ADDR low_text_segment_address;
 
-      low_text_segment_address = -1;
-
-      /* If addresses are 64 bits wide, then unwinds are supposed to
+      /* For ELF targets, then unwinds are supposed to
         be segment relative offsets instead of absolute addresses. 
 
         Note that when loading a shared library (text_offset != 0) the
         unwinds are already relative to the text_offset that will be
         passed in.  */
-      if (TARGET_PTR_BIT == 64 && text_offset == 0)
+      if (gdbarch_tdep (current_gdbarch)->is_elf && text_offset == 0)
        {
+          low_text_segment_address = -1;
+
          bfd_map_over_sections (objfile->obfd,
-                                record_text_segment_lowaddr, NULL);
+                                record_text_segment_lowaddr, 
+                                &low_text_segment_address);
 
-         /* ?!? Mask off some low bits.  Should this instead subtract
-            out the lowest section's filepos or something like that?
-            This looks very hokey to me.  */
-         low_text_segment_address &= ~0xfff;
-         text_offset += low_text_segment_address;
+         text_offset = low_text_segment_address;
        }
 
       bfd_get_section_contents (objfile->obfd, section, buf, 0, size);
@@ -465,12 +468,12 @@ read_unwind_info (struct objfile *objfile)
   unsigned index, unwind_entries;
   unsigned stub_entries, total_entries;
   CORE_ADDR text_offset;
-  struct obj_unwind_info *ui;
-  obj_private_data_t *obj_private;
+  struct hppa_unwind_info *ui;
+  struct hppa_objfile_private *obj_private;
 
   text_offset = ANOFFSET (objfile->section_offsets, 0);
-  ui = (struct obj_unwind_info *) obstack_alloc (&objfile->objfile_obstack,
-                                          sizeof (struct obj_unwind_info));
+  ui = (struct hppa_unwind_info *) obstack_alloc (&objfile->objfile_obstack,
+                                          sizeof (struct hppa_unwind_info));
 
   ui->table = NULL;
   ui->cache = NULL;
@@ -579,18 +582,18 @@ read_unwind_info (struct objfile *objfile)
         compare_unwind_entries);
 
   /* Keep a pointer to the unwind information.  */
-  if (objfile->obj_private == NULL)
+  obj_private = (struct hppa_objfile_private *) 
+               objfile_data (objfile, hppa_objfile_priv_data);
+  if (obj_private == NULL)
     {
-      obj_private = (obj_private_data_t *)
-       obstack_alloc (&objfile->objfile_obstack,
-                      sizeof (obj_private_data_t));
+      obj_private = (struct hppa_objfile_private *)
+       obstack_alloc (&objfile->objfile_obstack, 
+                       sizeof (struct hppa_objfile_private));
+      set_objfile_data (objfile, hppa_objfile_priv_data, obj_private);
       obj_private->unwind_info = NULL;
       obj_private->so_info = NULL;
       obj_private->dp = 0;
-
-      objfile->obj_private = obj_private;
     }
-  obj_private = (obj_private_data_t *) objfile->obj_private;
   obj_private->unwind_info = ui;
 }
 
@@ -604,24 +607,35 @@ find_unwind_entry (CORE_ADDR pc)
 {
   int first, middle, last;
   struct objfile *objfile;
+  struct hppa_objfile_private *priv;
+
+  if (hppa_debug)
+    fprintf_unfiltered (gdb_stdlog, "{ find_unwind_entry 0x%s -> ",
+                       paddr_nz (pc));
 
   /* A function at address 0?  Not in HP-UX! */
   if (pc == (CORE_ADDR) 0)
-    return NULL;
+    {
+      if (hppa_debug)
+       fprintf_unfiltered (gdb_stdlog, "NULL }\n");
+      return NULL;
+    }
 
   ALL_OBJFILES (objfile)
   {
-    struct obj_unwind_info *ui;
+    struct hppa_unwind_info *ui;
     ui = NULL;
-    if (objfile->obj_private)
-      ui = ((obj_private_data_t *) (objfile->obj_private))->unwind_info;
+    priv = objfile_data (objfile, hppa_objfile_priv_data);
+    if (priv)
+      ui = ((struct hppa_objfile_private *) priv)->unwind_info;
 
     if (!ui)
       {
        read_unwind_info (objfile);
-       if (objfile->obj_private == NULL)
+        priv = objfile_data (objfile, hppa_objfile_priv_data);
+       if (priv == NULL)
          error ("Internal error reading unwind information.");
-       ui = ((obj_private_data_t *) (objfile->obj_private))->unwind_info;
+        ui = ((struct hppa_objfile_private *) priv)->unwind_info;
       }
 
     /* First, check the cache */
@@ -629,7 +643,12 @@ find_unwind_entry (CORE_ADDR pc)
     if (ui->cache
        && pc >= ui->cache->region_start
        && pc <= ui->cache->region_end)
-      return ui->cache;
+      {
+       if (hppa_debug)
+         fprintf_unfiltered (gdb_stdlog, "0x%s (cached) }\n",
+            paddr_nz ((CORE_ADDR) ui->cache));
+        return ui->cache;
+      }
 
     /* Not in the cache, do a binary search */
 
@@ -643,6 +662,9 @@ find_unwind_entry (CORE_ADDR pc)
            && pc <= ui->table[middle].region_end)
          {
            ui->cache = &ui->table[middle];
+           if (hppa_debug)
+             fprintf_unfiltered (gdb_stdlog, "0x%s }\n",
+                paddr_nz ((CORE_ADDR) ui->cache));
            return &ui->table[middle];
          }
 
@@ -652,6 +674,10 @@ find_unwind_entry (CORE_ADDR pc)
          first = middle + 1;
       }
   }                            /* ALL_OBJFILES() */
+
+  if (hppa_debug)
+    fprintf_unfiltered (gdb_stdlog, "NULL (not found) }\n");
+
   return NULL;
 }
 
@@ -743,26 +769,6 @@ hppa64_register_name (int i)
     return names[i];
 }
 
-
-
-/* Return the adjustment necessary to make for addresses on the stack
-   as presented by hpread.c.
-
-   This is necessary because of the stack direction on the PA and the
-   bizarre way in which someone (?) decided they wanted to handle
-   frame pointerless code in GDB.  */
-int
-hpread_adjust_stack_address (CORE_ADDR func_addr)
-{
-  struct unwind_table_entry *u;
-
-  u = find_unwind_entry (func_addr);
-  if (!u)
-    return 0;
-  else
-    return u->Total_frame_size << 3;
-}
-
 /* This function pushes a stack frame with arguments as part of the
    inferior function calling mechanism.
 
@@ -1024,7 +1030,7 @@ hppa64_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
 /* Get the PC from %r31 if currently in a syscall.  Also mask out privilege
    bits.  */
 
-CORE_ADDR
+static CORE_ADDR
 hppa_target_read_pc (ptid_t ptid)
 {
   int flags = read_register_pid (FLAGS_REGNUM, ptid);
@@ -1041,7 +1047,7 @@ hppa_target_read_pc (ptid_t ptid)
 /* Write out the PC.  If currently in a syscall, then also write the new
    PC value into %r31.  */
 
-void
+static void
 hppa_target_write_pc (CORE_ADDR v, ptid_t ptid)
 {
   int flags = read_register_pid (FLAGS_REGNUM, ptid);
@@ -1098,7 +1104,7 @@ hppa_alignof (struct type *type)
    Note we return one for *any* call trampoline (long-call, arg-reloc), not
    just shared library trampolines (import, export).  */
 
-int
+static int
 hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name)
 {
   struct minimal_symbol *minsym;
@@ -1259,7 +1265,7 @@ hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name)
    Note we return one for *any* call trampoline (long-call, arg-reloc), not
    just shared library trampolines (import, export).  */
 
-int
+static int
 hppa_in_solib_return_trampoline (CORE_ADDR pc, char *name)
 {
   struct unwind_table_entry *u;
@@ -1332,7 +1338,7 @@ hppa_in_solib_return_trampoline (CORE_ADDR pc, char *name)
    calling an argument relocation stub.  It even handles some stubs
    used in dynamic executables.  */
 
-CORE_ADDR
+static CORE_ADDR
 hppa_skip_trampoline_code (CORE_ADDR pc)
 {
   long orig_pc = pc;
@@ -2014,7 +2020,7 @@ after_prologue (CORE_ADDR pc)
    Currently we must not skip more on the alpha, but we might the lenient
    stuff some day.  */
 
-CORE_ADDR
+static CORE_ADDR
 hppa_skip_prologue (CORE_ADDR pc)
 {
   unsigned long inst;
@@ -2057,8 +2063,17 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
   struct unwind_table_entry *u;
   int i;
 
+  if (hppa_debug)
+    fprintf_unfiltered (gdb_stdlog, "{ hppa_frame_cache (frame=%d) -> ",
+      frame_relative_level(next_frame));
+
   if ((*this_cache) != NULL)
-    return (*this_cache);
+    {
+      if (hppa_debug)
+        fprintf_unfiltered (gdb_stdlog, "base=0x%s (cached) }", 
+          paddr_nz (((struct hppa_frame_cache *)*this_cache)->base));
+      return (*this_cache);
+    }
   cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache);
   (*this_cache) = cache;
   cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
@@ -2066,7 +2081,11 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
   /* Yow! */
   u = find_unwind_entry (frame_func_unwind (next_frame));
   if (!u)
-    return (*this_cache);
+    {
+      if (hppa_debug)
+        fprintf_unfiltered (gdb_stdlog, "base=NULL (no unwind entry) }");
+      return (*this_cache);
+    }
 
   /* Turn the Entry_GR field into a bitmask.  */
   saved_gr_mask = 0;
@@ -2261,6 +2280,9 @@ hppa_frame_cache (struct frame_info *next_frame, void **this_cache)
       }
   }
 
+  if (hppa_debug)
+    fprintf_unfiltered (gdb_stdlog, "base=0x%s }", 
+      paddr_nz (((struct hppa_frame_cache *)*this_cache)->base));
   return (*this_cache);
 }
 
@@ -2458,14 +2480,6 @@ hppa_skip_permanent_breakpoint (void)
   /* We can leave the tail's space the same, since there's no jump.  */
 }
 
-int
-hppa_reg_struct_has_addr (int gcc_p, struct type *type)
-{
-  /* On the PA, any pass-by-value structure > 8 bytes is actually passed
-     via a pointer regardless of its type or the compiler used.  */
-  return (TYPE_LENGTH (type) > 8);
-}
-
 int
 hppa_pc_requires_run_before_use (CORE_ADDR pc)
 {
@@ -2533,7 +2547,7 @@ hppa64_register_type (struct gdbarch *gdbarch, int reg_nr)
 /* Return True if REGNUM is not a register available to the user
    through ptrace().  */
 
-int
+static int
 hppa_cannot_store_register (int regnum)
 {
   return (regnum == 0
@@ -2543,7 +2557,7 @@ hppa_cannot_store_register (int regnum)
 
 }
 
-CORE_ADDR
+static CORE_ADDR
 hppa_smash_text_address (CORE_ADDR addr)
 {
   /* The low two bits of the PC on the PA contain the privilege level.
@@ -2566,6 +2580,18 @@ hppa_fetch_pointer_argument (struct frame_info *frame, int argi,
   return addr;
 }
 
+static void
+hppa_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+                          int regnum, void *buf)
+{
+    ULONGEST tmp;
+
+    regcache_raw_read_unsigned (regcache, regnum, &tmp);
+    if (regnum == PCOQ_HEAD_REGNUM || regnum == PCOQ_TAIL_REGNUM)
+      tmp &= ~0x3;
+    store_unsigned_integer (buf, sizeof(tmp), tmp);
+}
+
 /* Here is a table of C type sizes on hppa with various compiles
    and options.  I measured this on PA 9000/800 with HP-UX 11.11
    and these compilers:
@@ -2621,7 +2647,7 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     return (arches->gdbarch);
 
   /* If none found, then allocate and initialize one.  */
-  tdep = XMALLOC (struct gdbarch_tdep);
+  tdep = XZALLOC (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
   /* Determine from the bfd_arch_info structure if we are dealing with
@@ -2725,6 +2751,8 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   frame_unwind_append_sniffer (gdbarch, hppa_frame_unwind_sniffer);
   frame_base_append_sniffer (gdbarch, hppa_frame_base_sniffer);
 
+  set_gdbarch_pseudo_register_read (gdbarch, hppa_pseudo_register_read);
+
   /* Hook in ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
@@ -2734,7 +2762,11 @@ hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 static void
 hppa_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
 {
-   /* Nothing to print for the moment.  */
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+  fprintf_unfiltered (file, "bytes_per_address = %d\n", 
+                      tdep->bytes_per_address);
+  fprintf_unfiltered (file, "elf = %s\n", tdep->is_elf ? "yes" : "no");
 }
 
 void
@@ -2747,6 +2779,8 @@ _initialize_hppa_tdep (void)
 
   gdbarch_register (bfd_arch_hppa, hppa_gdbarch_init, hppa_dump_tdep);
 
+  hppa_objfile_priv_data = register_objfile_data ();
+
   add_cmd ("unwind", class_maintenance, unwind_command,
           "Print unwind table entry at given address.",
           &maintenanceprintlist);
@@ -2780,5 +2814,10 @@ be no argument or the argument must be a depth.\n"), NULL);
                            break_at_finish_at_depth_command,
 "Set breakpoint at procedure exit.  Either there should\n\
 be no argument or the argument must be a depth.\n"), NULL);
+
+  /* Debug this files internals. */
+  add_show_from_set (add_set_cmd ("hppa", class_maintenance, var_zinteger,
+                                 &hppa_debug, "Set hppa debugging.\n\
+When non-zero, hppa specific debugging is enabled.", &setdebuglist), &showdebuglist);
 }
 
This page took 0.035594 seconds and 4 git commands to generate.