1 /* Target-dependent code for HP PA-RISC BSD's.
3 Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
23 #include "arch-utils.h"
33 #include "gdb_assert.h"
34 #include "gdb_string.h"
36 #include "elf/common.h"
38 #include "hppa-tdep.h"
39 #include "solib-svr4.h"
41 /* Core file support. */
43 /* Sizeof `struct reg' in <machine/reg.h>. */
44 #define HPPABSD_SIZEOF_GREGS (34 * 4)
46 /* Supply register REGNUM from the buffer specified by GREGS and LEN
47 in the general-purpose register set REGSET to register cache
48 REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
51 hppabsd_supply_gregset (const struct regset
*regset
, struct regcache
*regcache
,
52 int regnum
, const void *gregs
, size_t len
)
54 const gdb_byte
*regs
= gregs
;
58 gdb_assert (len
>= HPPABSD_SIZEOF_GREGS
);
60 for (i
= HPPA_R1_REGNUM
, offset
= 4; i
<= HPPA_R31_REGNUM
; i
++, offset
+= 4)
62 if (regnum
== -1 || regnum
== i
)
63 regcache_raw_supply (regcache
, i
, regs
+ offset
);
66 if (regnum
== -1 || regnum
== HPPA_SAR_REGNUM
)
67 regcache_raw_supply (regcache
, HPPA_SAR_REGNUM
, regs
);
68 if (regnum
== -1 || regnum
== HPPA_PCOQ_HEAD_REGNUM
)
69 regcache_raw_supply (regcache
, HPPA_PCOQ_HEAD_REGNUM
, regs
+ 32 * 4);
70 if (regnum
== -1 || regnum
== HPPA_PCOQ_TAIL_REGNUM
)
71 regcache_raw_supply (regcache
, HPPA_PCOQ_TAIL_REGNUM
, regs
+ 33 * 4);
74 /* OpenBSD/hppa register set. */
76 static struct regset hppabsd_gregset
=
79 hppabsd_supply_gregset
82 /* Return the appropriate register set for the core section identified
83 by SECT_NAME and SECT_SIZE. */
85 static const struct regset
*
86 hppabsd_regset_from_core_section (struct gdbarch
*gdbarch
,
87 const char *sect_name
, size_t sect_size
)
89 if (strcmp (sect_name
, ".reg") == 0 && sect_size
>= HPPABSD_SIZEOF_GREGS
)
90 return &hppabsd_gregset
;
97 hppabsd_find_global_pointer (struct value
*function
)
99 CORE_ADDR faddr
= value_as_address (function
);
100 struct obj_section
*faddr_sec
;
103 /* Is this a plabel? If so, dereference it to get the Global Pointer
107 if (target_read_memory ((faddr
& ~3) + 4, buf
, sizeof buf
) == 0)
108 return extract_unsigned_integer (buf
, sizeof buf
);
111 /* If the address is in the .plt section, then the real function
112 hasn't yet been fixed up by the linker so we cannot determine the
113 Global Pointer for that function. */
114 if (in_plt_section (faddr
, NULL
))
117 faddr_sec
= find_pc_section (faddr
);
118 if (faddr_sec
!= NULL
)
120 struct obj_section
*sec
;
122 ALL_OBJFILE_OSECTIONS (faddr_sec
->objfile
, sec
)
124 if (strcmp (sec
->the_bfd_section
->name
, ".dynamic") == 0)
128 if (sec
< faddr_sec
->objfile
->sections_end
)
130 CORE_ADDR addr
= sec
->addr
;
132 while (addr
< sec
->endaddr
)
137 if (target_read_memory (addr
, buf
, sizeof buf
) != 0)
140 tag
= extract_signed_integer (buf
, sizeof buf
);
141 if (tag
== DT_PLTGOT
)
145 if (target_read_memory (addr
+ 4, buf
, sizeof buf
) != 0)
148 /* The OpenBSD ld.so doesn't relocate DT_PLTGOT, so
149 we have to do it ourselves. */
150 pltgot
= extract_unsigned_integer (buf
, sizeof buf
);
151 pltgot
+= ANOFFSET (sec
->objfile
->section_offsets
,
152 SECT_OFF_TEXT (sec
->objfile
));
169 hppabsd_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
171 struct gdbarch_tdep
*tdep
= gdbarch_tdep (gdbarch
);
173 /* OpenBSD and NetBSD have a 64-bit 'long double'. */
174 set_gdbarch_long_double_bit (gdbarch
, 64);
175 set_gdbarch_long_double_format (gdbarch
, floatformats_ieee_double
);
177 /* Core file support. */
178 set_gdbarch_regset_from_core_section
179 (gdbarch
, hppabsd_regset_from_core_section
);
181 /* OpenBSD and NetBSD use ELF. */
183 tdep
->find_global_pointer
= hppabsd_find_global_pointer
;
184 tdep
->in_solib_call_trampoline
= hppa_in_solib_call_trampoline
;
185 set_gdbarch_skip_trampoline_code (gdbarch
, hppa_skip_trampoline_code
);
187 /* OpenBSD and NetBSD use SVR4-style shared libraries. */
188 set_solib_svr4_fetch_link_map_offsets
189 (gdbarch
, svr4_ilp32_fetch_link_map_offsets
);
193 /* OpenBSD uses uses the traditional NetBSD core file format, even for
194 ports that use ELF. */
195 #define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
197 static enum gdb_osabi
198 hppabsd_core_osabi_sniffer (bfd
*abfd
)
200 if (strcmp (bfd_get_target (abfd
), "netbsd-core") == 0)
201 return GDB_OSABI_NETBSD_CORE
;
203 return GDB_OSABI_UNKNOWN
;
207 /* Provide a prototype to silence -Wmissing-prototypes. */
208 void _initialize_hppabsd_tdep (void);
211 _initialize_hppabsd_tdep (void)
213 /* BFD doesn't set a flavour for NetBSD style a.out core files. */
214 gdbarch_register_osabi_sniffer (bfd_arch_hppa
, bfd_target_unknown_flavour
,
215 hppabsd_core_osabi_sniffer
);
217 gdbarch_register_osabi (bfd_arch_hppa
, 0, GDB_OSABI_NETBSD_ELF
,
219 gdbarch_register_osabi (bfd_arch_hppa
, 0, GDB_OSABI_OPENBSD_ELF
,