/* Target-dependent code for HP-UX on PA-RISC.
- Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GDB.
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. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "arch-utils.h"
#include "solib-som.h"
#include "solib-pa64.h"
#include "regset.h"
+#include "exceptions.h"
#include "gdb_string.h"
#define IS_32BIT_TARGET(_gdbarch) \
((gdbarch_tdep (_gdbarch))->bytes_per_address == 4)
+/* Bit in the `ss_flag' member of `struct save_state' that indicates
+ that the 64-bit register values are live. From
+ <machine/save_state.h>. */
+#define HPPA_HPUX_SS_WIDEREGS 0x40
+
+/* Offsets of various parts of `struct save_state'. From
+ <machine/save_state.h>. */
+#define HPPA_HPUX_SS_FLAGS_OFFSET 0
+#define HPPA_HPUX_SS_NARROW_OFFSET 4
+#define HPPA_HPUX_SS_FPBLOCK_OFFSET 256
+#define HPPA_HPUX_SS_WIDE_OFFSET 640
+
+/* The size of `struct save_state. */
+#define HPPA_HPUX_SAVE_STATE_SIZE 1152
+
+/* The size of `struct pa89_save_state', which corresponds to PA-RISC
+ 1.1, the lowest common denominator that we support. */
+#define HPPA_HPUX_PA89_SAVE_STATE_SIZE 512
+
+
/* Forward declarations. */
extern void _initialize_hppa_hpux_tdep (void);
extern initialize_file_ftype _initialize_hppa_hpux_tdep;
}
/* Should never happen. */
- warning ("Unable to find branch in parameter relocation stub.\n");
+ warning (_("Unable to find branch in parameter relocation stub."));
return 0;
}
}
/* Should never happen. */
- warning ("Unable to find branch in parameter relocation stub.\n");
+ warning (_("Unable to find branch in parameter relocation stub."));
return 0;
}
/* Make sure we haven't walked outside the range of this stub. */
if (u != find_unwind_entry (loc))
{
- warning ("Unable to find branch in linker stub");
+ warning (_("Unable to find branch in linker stub"));
return orig_pc == pc ? 0 : pc & ~0x3;
}
return (hppa_extract_21 (prev_inst) + hppa_extract_17 (curr_inst)) & ~0x3;
else
{
- warning ("Unable to find ldil X,%%r1 before ble Y(%%sr4,%%r1).");
+ warning (_("Unable to find ldil X,%%r1 before ble Y(%%sr4,%%r1)."));
return orig_pc == pc ? 0 : pc & ~0x3;
}
}
stubsym = lookup_minimal_symbol_by_pc (loc);
if (stubsym == NULL)
{
- warning ("Unable to find symbol for 0x%lx", loc);
+ warning (_("Unable to find symbol for 0x%lx"), loc);
return orig_pc == pc ? 0 : pc & ~0x3;
}
libsym = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (stubsym), NULL, NULL);
if (libsym == NULL)
{
- warning ("Unable to find library symbol for %s\n",
+ warning (_("Unable to find library symbol for %s."),
DEPRECATED_SYMBOL_NAME (stubsym));
return orig_pc == pc ? 0 : pc & ~0x3;
}
(read_register (HPPA_SP_REGNUM) - 8, 4)) & ~0x3;
else
{
- warning ("Unable to find restore of %%rp before bv (%%rp).");
+ warning (_("Unable to find restore of %%rp before bv (%%rp)."));
return orig_pc == pc ? 0 : pc & ~0x3;
}
}
GDB can set a breakpoint on this callback and find out what
exception event has occurred. */
-/* The name of the hook to be set to point to the callback function */
+/* The name of the hook to be set to point to the callback function. */
static char HP_ACC_EH_notify_hook[] = "__eh_notify_hook";
-/* The name of the function to be used to set the hook value */
+/* The name of the function to be used to set the hook value. */
static char HP_ACC_EH_set_hook_value[] = "__eh_set_hook_value";
/* The name of the callback function in end.o */
static char HP_ACC_EH_notify_callback[] = "__d_eh_notify_callback";
-/* Name of function in end.o on which a break is set (called by above) */
+/* Name of function in end.o on which a break is set (called by above). */
static char HP_ACC_EH_break[] = "__d_eh_break";
-/* Name of flag (in end.o) that enables catching throws */
+/* Name of flag (in end.o) that enables catching throws. */
static char HP_ACC_EH_catch_throw[] = "__d_eh_catch_throw";
-/* Name of flag (in end.o) that enables catching catching */
+/* Name of flag (in end.o) that enables catching catching. */
static char HP_ACC_EH_catch_catch[] = "__d_eh_catch_catch";
-/* The enum used by aCC */
+/* The enum used by aCC. */
typedef enum
{
__EH_NOTIFY_THROW,
msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
if (msymbol == NULL)
{
- warning ("Unable to find __d_pid symbol in object file.");
- warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+ warning (_("Unable to find __d_pid symbol in object file.\n"
+ "Suggest linking executable with -g (links in /opt/langtools/lib/end.o)."));
return 1;
}
store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
if (target_write_memory (anaddr, buf, 4)) /* FIXME 32x64? */
{
- warning ("Unable to write __d_pid");
- warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
+ warning (_("Unable to write __d_pid.\n"
+ "Suggest linking executable with -g (links in /opt/langtools/lib/end.o)."));
return 1;
}
return 0;
target_read_memory (value_return_addr, (char *) &stub_addr, sizeof (stub_addr));
if (stub_addr <= 0)
- error ("call to __d_shl_get failed, error code is %d", err_value);
+ error (_("call to __d_shl_get failed, error code is %d"), err_value);
return (stub_addr);
}
}
/* Initialize exception catchpoint support by looking for the
- necessary hooks/callbacks in end.o, etc., and set the hook value to
- point to the required debug function
+ necessary hooks/callbacks in end.o, etc., and set the hook value
+ to point to the required debug function.
Return 0 => failure
1 => success */
/* Detect and disallow recursion. On HP-UX with aCC, infinite
recursion is a possibility because finding the hook for exception
callbacks involves making a call in the inferior, which means
- re-inserting breakpoints which can re-invoke this code */
+ re-inserting breakpoints which can re-invoke this code. */
static int recurse = 0;
if (recurse > 0)
if (!deprecated_hp_som_som_object_present)
return 0;
- /* We have a SOM executable with SOM debug info; find the hooks */
+ /* We have a SOM executable with SOM debug info; find the hooks. */
/* First look for the notify hook provided by aCC runtime libs */
/* If we find this symbol, we conclude that the executable must
should *not* be tried as an alternative.
ASSUMPTION: Only HP aCC code will have __eh_notify_hook defined.
- ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
+ ASSUMPTION: HP aCC and g++ modules cannot be linked together. */
/* libCsup has this hook; it'll usually be non-debuggable */
msym = lookup_minimal_symbol (HP_ACC_EH_notify_hook, NULL, NULL);
}
else
{
- warning ("Unable to find exception callback hook (%s).", HP_ACC_EH_notify_hook);
- warning ("Executable may not have been compiled debuggable with HP aCC.");
- warning ("GDB will be unable to intercept exception events.");
+ warning (_("\
+Unable to find exception callback hook (%s).\n\
+Executable may not have been compiled debuggable with HP aCC.\n\
+GDB will be unable to intercept exception events."),
+ HP_ACC_EH_notify_hook);
eh_notify_hook_addr = 0;
hp_cxx_exception_support = 0;
return 0;
}
/* Next look for the notify callback routine in end.o */
- /* This is always available in the SOM symbol dictionary if end.o is linked in */
+ /* This is always available in the SOM symbol dictionary if end.o is
+ linked in. */
msym = lookup_minimal_symbol (HP_ACC_EH_notify_callback, NULL, NULL);
if (msym)
{
}
else
{
- warning ("Unable to find exception callback routine (%s).", HP_ACC_EH_notify_callback);
- warning ("Suggest linking executable with -g (links in /opt/langtools/lib/end.o).");
- warning ("GDB will be unable to intercept exception events.");
+ warning (_("\
+Unable to find exception callback routine (%s).\n\
+Suggest linking executable with -g (links in /opt/langtools/lib/end.o).\n\
+GDB will be unable to intercept exception events."),
+ HP_ACC_EH_notify_callback);
eh_notify_callback_addr = 0;
return 0;
}
shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
if (shlib_info && (bfd_section_size (symfile_objfile->obfd, shlib_info) != 0))
{
- /* The minsym we have has the local code address, but that's not the
- plabel that can be used by an inter-load-module call. */
- /* Find solib handle for main image (which has end.o), and use that
- and the min sym as arguments to __d_shl_get() (which does the equivalent
- of shl_findsym()) to find the plabel. */
+ /* The minsym we have has the local code address, but that's not
+ the plabel that can be used by an inter-load-module call. */
+ /* Find solib handle for main image (which has end.o), and use
+ that and the min sym as arguments to __d_shl_get() (which
+ does the equivalent of shl_findsym()) to find the plabel. */
args_for_find_stub args;
static char message[] = "Error while finding exception callback hook:\n";
{
/* We can get here either if there is no plabel in the export list
for the main image, or if something strange happened (?) */
- warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
- warning ("GDB will not be able to intercept exception events.");
+ warning (_("\
+Couldn't find a plabel (indirect function label) for the exception callback.\n\
+GDB will not be able to intercept exception events."));
return 0;
}
}
}
else
{
- warning ("Unable to find exception callback routine to set breakpoint (%s).", HP_ACC_EH_break);
- warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
- warning ("GDB will be unable to intercept exception events.");
+ warning (_("\
+Unable to find exception callback routine to set breakpoint (%s).\n\
+Suggest linking executable with -g (link in /opt/langtools/lib/end.o).\n\
+GDB will be unable to intercept exception events."),
+ HP_ACC_EH_break);
eh_break_addr = 0;
return 0;
}
}
else
{
- warning ("Unable to enable interception of exception catches.");
- warning ("Executable may not have been compiled debuggable with HP aCC.");
- warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+ warning (_("\
+Unable to enable interception of exception catches.\n\
+Executable may not have been compiled debuggable with HP aCC.\n\
+Suggest linking executable with -g (link in /opt/langtools/lib/end.o)."));
return 0;
}
}
}
else
{
- warning ("Unable to enable interception of exception throws.");
- warning ("Executable may not have been compiled debuggable with HP aCC.");
- warning ("Suggest linking executable with -g (link in /opt/langtools/lib/end.o).");
+ warning (_("\
+Unable to enable interception of exception throws.\n\
+Executable may not have been compiled debuggable with HP aCC.\n\
+Suggest linking executable with -g (link in /opt/langtools/lib/end.o)."));
return 0;
}
}
/* there may be other cases in the future */
}
- /* Set the EH hook to point to the callback routine */
+ /* Set the EH hook to point to the callback routine. */
store_unsigned_integer (buf, 4, enable ? eh_notify_callback_addr : 0); /* FIXME 32x64 problem */
/* pai: (temp) FIXME should there be a pack operation first? */
if (target_write_memory (eh_notify_hook_addr, buf, 4)) /* FIXME 32x64 problem */
{
- warning ("Could not write to target memory for exception event callback.");
- warning ("Interception of exception events may not work.");
+ warning (_("\
+Could not write to target memory for exception event callback.\n\
+Interception of exception events may not work."));
return (struct symtab_and_line *) -1;
}
if (enable)
}
else
{
- warning ("Internal error: Invalid inferior pid? Cannot intercept exception events.");
+ warning (_("Internal error: Invalid inferior pid? Cannot intercept exception events."));
return (struct symtab_and_line *) -1;
}
}
store_unsigned_integer (buf, 4, enable ? 1 : 0);
if (target_write_memory (eh_catch_throw_addr, buf, 4)) /* FIXME 32x64? */
{
- warning ("Couldn't enable exception throw interception.");
+ warning (_("Couldn't enable exception throw interception."));
return (struct symtab_and_line *) -1;
}
break;
store_unsigned_integer (buf, 4, enable ? 1 : 0);
if (target_write_memory (eh_catch_catch_addr, buf, 4)) /* FIXME 32x64? */
{
- warning ("Couldn't enable exception catch interception.");
+ warning (_("Couldn't enable exception catch interception."));
return (struct symtab_and_line *) -1;
}
break;
default:
- error ("Request to enable unknown or unsupported exception event.");
+ error (_("Request to enable unknown or unsupported exception event."));
}
/* Copy break address into new sal struct, malloc'ing if needed. */
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
struct hppa_hpux_sigtramp_unwind_cache *info;
unsigned int flag;
- CORE_ADDR sp, scptr;
- int i, incr, off, szoff;
+ CORE_ADDR sp, scptr, off;
+ int i, incr, szoff;
if (*this_cache)
return *this_cache;
sp = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
- scptr = sp - 1352;
+ if (IS_32BIT_TARGET (gdbarch))
+ scptr = sp - 1352;
+ else
+ scptr = sp - 1520;
+
off = scptr;
/* See /usr/include/machine/save_state.h for the structure of the save_state_t
structure. */
- flag = read_memory_unsigned_integer(scptr, 4);
-
- if (!(flag & 0x40))
+ flag = read_memory_unsigned_integer(scptr + HPPA_HPUX_SS_FLAGS_OFFSET, 4);
+
+ if (!(flag & HPPA_HPUX_SS_WIDEREGS))
{
/* Narrow registers. */
- off = scptr + offsetof (save_state_t, ss_narrow);
+ off = scptr + HPPA_HPUX_SS_NARROW_OFFSET;
incr = 4;
szoff = 0;
}
else
{
/* Wide registers. */
- off = scptr + offsetof (save_state_t, ss_wide) + 8;
+ off = scptr + HPPA_HPUX_SS_WIDE_OFFSET + 8;
incr = 8;
szoff = (tdep->bytes_per_address == 4 ? 4 : 0);
}
{
if (hppa_hpux_tramp_reg[i] > 0)
info->saved_regs[hppa_hpux_tramp_reg[i]].addr = off + szoff;
+
off += incr;
}
static void
hppa_hpux_sigtramp_frame_prev_register (struct frame_info *next_frame,
- void **this_prologue_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp,
- CORE_ADDR *addrp,
- int *realnump, void *valuep)
+ void **this_prologue_cache,
+ int regnum, int *optimizedp,
+ enum lval_type *lvalp,
+ CORE_ADDR *addrp,
+ int *realnump, gdb_byte *valuep)
{
struct hppa_hpux_sigtramp_unwind_cache *info
= hppa_hpux_sigtramp_frame_unwind_cache (next_frame, this_prologue_cache);
static const struct frame_unwind *
hppa_hpux_sigtramp_unwind_sniffer (struct frame_info *next_frame)
{
+ struct unwind_table_entry *u;
CORE_ADDR pc = frame_pc_unwind (next_frame);
- char *name;
- find_pc_partial_function (pc, &name, NULL, NULL);
+ u = find_unwind_entry (pc);
+
+ /* If this is an export stub, try to get the unwind descriptor for
+ the actual function itself. */
+ if (u && u->stub_unwind.stub_type == EXPORT)
+ {
+ gdb_byte buf[HPPA_INSN_SIZE];
+ unsigned long insn;
+
+ if (!safe_frame_unwind_memory (next_frame, u->region_start,
+ buf, sizeof buf))
+ return NULL;
+
+ insn = extract_unsigned_integer (buf, sizeof buf);
+ if ((insn & 0xffe0e000) == 0xe8400000)
+ u = find_unwind_entry(u->region_start + hppa_extract_17 (insn) + 8);
+ }
- if (name && strcmp(name, "_sigreturn") == 0)
+ if (u && u->HP_UX_interrupt_marker)
return &hppa_hpux_sigtramp_frame_unwind;
return NULL;
hppa_hpux_search_pattern (CORE_ADDR start, CORE_ADDR end,
unsigned int *patterns, int count)
{
- unsigned int *buf;
+ int num_insns = (end - start + HPPA_INSN_SIZE) / HPPA_INSN_SIZE;
+ unsigned int *insns;
+ gdb_byte *buf;
int offset, i;
- int region, insns;
-
- region = end - start + 4;
- insns = region / 4;
- buf = (unsigned int *) alloca (region);
- read_memory (start, (char *) buf, region);
+ buf = alloca (num_insns * HPPA_INSN_SIZE);
+ insns = alloca (num_insns * sizeof (unsigned int));
- for (i = 0; i < insns; i++)
- buf[i] = extract_unsigned_integer (&buf[i], 4);
+ read_memory (start, buf, num_insns * HPPA_INSN_SIZE);
+ for (i = 0; i < num_insns; i++, buf += HPPA_INSN_SIZE)
+ insns[i] = extract_unsigned_integer (buf, HPPA_INSN_SIZE);
- for (offset = 0; offset <= insns - count; offset++)
+ for (offset = 0; offset <= num_insns - count; offset++)
{
for (i = 0; i < count; i++)
{
- if ((buf[offset + i] & patterns[i]) != patterns[i])
+ if ((insns[offset + i] & patterns[i]) != patterns[i])
break;
}
if (i == count)
break;
}
-
- if (offset <= insns - count)
- return start + offset * 4;
+
+ if (offset <= num_insns - count)
+ return start + offset * HPPA_INSN_SIZE;
else
return 0;
}
if (!priv)
priv = hppa_init_objfile_priv_data (obj);
if (!priv)
- error ("Internal error creating objfile private data.\n");
+ error (_("Internal error creating objfile private data."));
/* Use the cached value if we have one. */
if (priv->dummy_call_sequence_addr != 0)
if (!priv)
priv = hppa_init_objfile_priv_data (obj);
if (!priv)
- error ("Internal error creating objfile private data.\n");
+ error (_("Internal error creating objfile private data."));
/* Use the cached value if we have one. */
if (priv->dummy_call_sequence_addr != 0)
{
CORE_ADDR begin, end;
char *name;
- unsigned int insns[2];
+ gdb_byte buf[2 * HPPA_INSN_SIZE];
int offset;
find_pc_partial_function (SYMBOL_VALUE_ADDRESS (msym), &name,
if (name == NULL || begin == 0 || end == 0)
continue;
- if (target_read_memory (end - sizeof (insns), (char *)insns, sizeof (insns)) == 0)
+ if (target_read_memory (end - sizeof (buf), buf, sizeof (buf)) == 0)
{
- for (offset = 0; offset < ARRAY_SIZE (insns); offset++)
+ for (offset = 0; offset < sizeof (buf); offset++)
{
unsigned int insn;
- insn = extract_unsigned_integer (&insns[offset], 4);
+ insn = extract_unsigned_integer (buf + offset, HPPA_INSN_SIZE);
if (insn == 0xe840d002) /* bve,n (rp) */
{
- addr = (end - sizeof (insns)) + (offset * 4);
+ addr = (end - sizeof (buf)) + offset;
goto found_pattern;
}
}
}
}
- warning ("Cannot find suitable address to place dummy breakpoint; nested "
- "calls may fail.\n");
+ warning (_("Cannot find suitable address to place dummy breakpoint; nested "
+ "calls may fail."));
return addr - 4;
}
return it can return to the space of our trampoline. */
stubaddr = hppa_hpux_find_import_stub_for_addr (funcaddr);
if (stubaddr == 0)
- error ("Cannot call external function not referenced by application "
- "(no import stub).\n");
+ error (_("Cannot call external function not referenced by application "
+ "(no import stub).\n"));
regcache_cooked_write_unsigned (current_regcache, 22, stubaddr);
write_memory (sp, (char *)&hppa32_tramp, sizeof (hppa32_tramp));
*real_pc = hppa32_hpux_search_dummy_call_sequence (gdbarch, pc, &argreg);
if (*real_pc == 0)
- error ("Cannot make interspace call from here.\n");
+ error (_("Cannot make interspace call from here."));
regcache_cooked_write_unsigned (current_regcache, argreg, sp);
*real_pc = hppa64_hpux_search_dummy_call_sequence (gdbarch, pc, &argreg);
if (*real_pc == 0)
- error ("Cannot make interspace call from here.\n");
+ error (_("Cannot make interspace call from here."));
regcache_cooked_write_unsigned (current_regcache, argreg, sp);
\f
-/* Bit in the `ss_flag' member of `struct save_state' that indicates
- that the 64-bit register values are live. From
- <machine/save_state.h>. */
-#define HPPA_HPUX_SS_WIDEREGS 0x40
-
-/* Offsets of various parts of `struct save_state'. From
- <machine/save_state.h>. */
-#define HPPA_HPUX_SS_FLAGS_OFFSET 0
-#define HPPA_HPUX_SS_NARROW_OFFSET 4
-#define HPPA_HPUX_SS_FPBLOCK_OFFSET 256
-#define HPPA_HPUX_SS_WIDE_OFFSET 640
-
-/* The size of `struct save_state. */
-#define HPPA_HPUX_SAVE_STATE_SIZE 1152
-
-/* The size of `struct pa89_save_state', which corresponds to PA-RISC
- 1.1, the lowest common denominator that we support. */
-#define HPPA_HPUX_PA89_SAVE_STATE_SIZE 512
-
static void
hppa_hpux_supply_ss_narrow (struct regcache *regcache,
int regnum, const char *save_state)
/* If the SS_WIDEREGS flag is set, we really do need the full
`struct save_state'. */
if (flags & HPPA_HPUX_SS_WIDEREGS && len < HPPA_HPUX_SAVE_STATE_SIZE)
- error ("Register set contents too small");
+ error (_("Register set contents too small"));
if (flags & HPPA_HPUX_SS_WIDEREGS)
hppa_hpux_supply_ss_wide (regcache, regnum, save_state);
{
if (strcmp (bfd_get_target (abfd), "hpux-core") == 0)
return GDB_OSABI_HPUX_SOM;
+ else if (strcmp (bfd_get_target (abfd), "elf64-hppa") == 0)
+ {
+ asection *section;
+
+ section = bfd_get_section_by_name (abfd, ".kernel");
+ if (section)
+ {
+ bfd_size_type size;
+ char *contents;
+
+ size = bfd_section_size (abfd, section);
+ contents = alloca (size);
+ if (bfd_get_section_contents (abfd, section, contents,
+ (file_ptr) 0, size)
+ && strcmp (contents, "HP-UX") == 0)
+ return GDB_OSABI_HPUX_ELF;
+ }
+ }
return GDB_OSABI_UNKNOWN;
}
gdbarch_register_osabi_sniffer (bfd_arch_unknown,
bfd_target_unknown_flavour,
hppa_hpux_core_osabi_sniffer);
+ gdbarch_register_osabi_sniffer (bfd_arch_hppa,
+ bfd_target_elf_flavour,
+ hppa_hpux_core_osabi_sniffer);
gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_HPUX_SOM,
hppa_hpux_som_init_abi);