2007-11-15 Markus Deuling <deuling@de.ibm.com>
[deliverable/binutils-gdb.git] / gdb / hppabsd-tdep.c
index 0a54371527d32d975d4d64cbb13c2b02363e774a..f167f752c154246a97de463caa7a9ce69d0bfad5 100644 (file)
@@ -1,12 +1,12 @@
 /* Target-dependent code for HP PA-RISC BSD's.
 
-   Copyright 2004 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "arch-utils.h"
+#include "gdbtypes.h"
+#include "symtab.h"
+#include "objfiles.h"
 #include "osabi.h"
 #include "regcache.h"
 #include "regset.h"
+#include "target.h"
+#include "value.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
 
+#include "elf/common.h"
+
 #include "hppa-tdep.h"
 #include "solib-svr4.h"
 
@@ -44,7 +49,7 @@ static void
 hppabsd_supply_gregset (const struct regset *regset, struct regcache *regcache,
                     int regnum, const void *gregs, size_t len)
 {
-  const char *regs = gregs;
+  const gdb_byte *regs = gregs;
   size_t offset;
   int i;
 
@@ -86,21 +91,98 @@ hppabsd_regset_from_core_section (struct gdbarch *gdbarch,
 }
 \f
 
+CORE_ADDR
+hppabsd_find_global_pointer (struct value *function)
+{
+  CORE_ADDR faddr = value_as_address (function);
+  struct obj_section *faddr_sec;
+  gdb_byte buf[4];
+
+  /* Is this a plabel? If so, dereference it to get the Global Pointer
+     value.  */
+  if (faddr & 2)
+    {
+      if (target_read_memory ((faddr & ~3) + 4, buf, sizeof buf) == 0)
+       return extract_unsigned_integer (buf, sizeof buf);
+    }
+
+  /* If the address is in the .plt section, then the real function
+     hasn't yet been fixed up by the linker so we cannot determine the
+     Global Pointer for that function.  */
+  if (in_plt_section (faddr, NULL))
+    return 0;
+
+  faddr_sec = find_pc_section (faddr);
+  if (faddr_sec != NULL)
+    {
+      struct obj_section *sec;
+
+      ALL_OBJFILE_OSECTIONS (faddr_sec->objfile, sec)
+       {
+         if (strcmp (sec->the_bfd_section->name, ".dynamic") == 0)
+           break;
+       }
+
+      if (sec < faddr_sec->objfile->sections_end)
+       {
+         CORE_ADDR addr = sec->addr;
+
+         while (addr < sec->endaddr)
+           {
+             gdb_byte buf[4];
+             LONGEST tag;
+
+             if (target_read_memory (addr, buf, sizeof buf) != 0)
+               break;
+
+             tag = extract_signed_integer (buf, sizeof buf);
+             if (tag == DT_PLTGOT)
+               {
+                 CORE_ADDR pltgot;
+
+                 if (target_read_memory (addr + 4, buf, sizeof buf) != 0)
+                   break;
+
+                 /* The OpenBSD ld.so doesn't relocate DT_PLTGOT, so
+                    we have to do it ourselves.  */
+                 pltgot = extract_unsigned_integer (buf, sizeof buf);
+                 pltgot += ANOFFSET (sec->objfile->section_offsets,
+                                     SECT_OFF_TEXT (sec->objfile));
+                 return pltgot;
+               }
+
+             if (tag == DT_NULL)
+               break;
+
+             addr += 8;
+           }
+       }
+    }
+
+  return 0;
+}
+\f
+
 static void
 hppabsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
+  /* OpenBSD and NetBSD have a 64-bit 'long double'.  */
+  set_gdbarch_long_double_bit (gdbarch, 64);
+  set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
+
   /* Core file support.  */
   set_gdbarch_regset_from_core_section
     (gdbarch, hppabsd_regset_from_core_section);
 
   /* OpenBSD and NetBSD use ELF.  */
   tdep->is_elf = 1;
+  tdep->find_global_pointer = hppabsd_find_global_pointer;
+  tdep->in_solib_call_trampoline = hppa_in_solib_call_trampoline;
+  set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code);
 
-  /* OpenBSD and NetBSD uses SVR4-style shared libraries.  */
-  set_gdbarch_in_solib_call_trampoline
-    (gdbarch, generic_in_solib_call_trampoline);
+  /* OpenBSD and NetBSD use SVR4-style shared libraries.  */
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
 }
This page took 0.025366 seconds and 4 git commands to generate.