/* Target-dependent code for the HP PA-RISC architecture.
- Copyright (C) 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
- 2011 Free Software Foundation, Inc.
+ Copyright (C) 1986-2015 Free Software Foundation, Inc.
Contributed by the Center for Software Science at the
University of Utah (pa-gdb-bugs@cs.utah.edu).
#include "regcache.h"
#include "completer.h"
#include "osabi.h"
-#include "gdb_assert.h"
#include "arch-utils.h"
/* For argument passing to the inferior. */
#include "symtab.h"
static const int hppa32_num_regs = 128;
static const int hppa64_num_regs = 96;
+/* We use the objfile->obj_private pointer for two things:
+ * 1. An unwind table;
+ *
+ * 2. A pointer to any associated shared library object.
+ *
+ * #defines are used to help refer to these objects.
+ */
+
+/* Info about the unwind table associated with an object file.
+ * This is hung off of the "objfile->obj_private" pointer, and
+ * is allocated in the objfile's psymbol obstack. This allows
+ * us to have unique unwind info for each executable and shared
+ * library that we are debugging.
+ */
+struct hppa_unwind_info
+ {
+ struct unwind_table_entry *table; /* Pointer to unwind info */
+ struct unwind_table_entry *cache; /* Pointer to last entry we found */
+ int last; /* Index of last entry */
+ };
+
+struct hppa_objfile_private
+ {
+ struct hppa_unwind_info *unwind_info; /* a pointer */
+ struct so_list *so_info; /* a pointer */
+ CORE_ADDR dp;
+
+ int dummy_call_sequence_reg;
+ CORE_ADDR dummy_call_sequence_addr;
+ };
+
/* 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;
+static const struct objfile_data *hppa_objfile_priv_data = NULL;
/* Get at various relevent fields of an instruction word. */
#define MASK_5 0x1f
CORE_ADDR
hppa_symbol_address(const char *sym)
{
- struct minimal_symbol *minsym;
+ struct bound_minimal_symbol minsym;
minsym = lookup_minimal_symbol (sym, NULL, NULL);
- if (minsym)
- return SYMBOL_VALUE_ADDRESS (minsym);
+ if (minsym.minsym)
+ return BMSYMBOL_VALUE_ADDRESS (minsym);
else
return (CORE_ADDR)-1;
}
-struct hppa_objfile_private *
+static struct hppa_objfile_private *
hppa_init_objfile_priv_data (struct objfile *objfile)
{
struct hppa_objfile_private *priv;
static int
compare_unwind_entries (const void *arg1, const void *arg2)
{
- const struct unwind_table_entry *a = arg1;
- const struct unwind_table_entry *b = arg2;
+ const struct unwind_table_entry *a = (const struct unwind_table_entry *) arg1;
+ const struct unwind_table_entry *b = (const struct unwind_table_entry *) arg2;
if (a->region_start > b->region_start)
return 1;
static void
internalize_unwinds (struct objfile *objfile, struct unwind_table_entry *table,
asection *section, unsigned int entries,
- unsigned int size, CORE_ADDR text_offset)
+ size_t size, CORE_ADDR text_offset)
{
/* We will read the unwind entries into temporary memory, then
fill in the actual unwind table. */
struct gdbarch *gdbarch = get_objfile_arch (objfile);
unsigned long tmp;
unsigned i;
- char *buf = alloca (size);
+ char *buf = (char *) alloca (size);
CORE_ADDR low_text_segment_address;
/* For ELF targets, then unwinds are supposed to
read_unwind_info (struct objfile *objfile)
{
asection *unwind_sec, *stub_unwind_sec;
- unsigned unwind_size, stub_unwind_size, total_size;
+ size_t unwind_size, stub_unwind_size, total_size;
unsigned index, unwind_entries;
unsigned stub_entries, total_entries;
CORE_ADDR text_offset;
struct hppa_unwind_info *ui;
struct hppa_objfile_private *obj_private;
- text_offset = ANOFFSET (objfile->section_offsets, 0);
+ text_offset = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
ui = (struct hppa_unwind_info *) obstack_alloc (&objfile->objfile_obstack,
sizeof (struct hppa_unwind_info));
if (stub_unwind_size > 0)
{
unsigned int i;
- char *buf = alloca (stub_unwind_size);
+ char *buf = (char *) alloca (stub_unwind_size);
/* Read in the stub unwind entries. */
bfd_get_section_contents (objfile->obfd, stub_unwind_sec, buf,
{
struct hppa_unwind_info *ui;
ui = NULL;
- priv = objfile_data (objfile, hppa_objfile_priv_data);
+ priv = ((struct hppa_objfile_private *)
+ objfile_data (objfile, hppa_objfile_priv_data));
if (priv)
ui = ((struct hppa_objfile_private *) priv)->unwind_info;
if (!ui)
{
read_unwind_info (objfile);
- priv = objfile_data (objfile, hppa_objfile_priv_data);
+ priv = ((struct hppa_objfile_private *)
+ objfile_data (objfile, hppa_objfile_priv_data));
if (priv == NULL)
error (_("Internal error reading unwind information."));
ui = ((struct hppa_objfile_private *) priv)->unwind_info;
return NULL;
}
-/* The epilogue is defined here as the area either on the `bv' instruction
+/* Implement the stack_frame_destroyed_p gdbarch method.
+
+ The epilogue is defined here as the area either on the `bv' instruction
itself or an instruction which destroys the function's stack frame.
We do not assume that the epilogue is at the end of a function as we can
also have return sequences in the middle of a function. */
+
static int
-hppa_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+hppa_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned long status;
unsigned int inst;
- char buf[4];
- int off;
+ gdb_byte buf[4];
status = target_read_memory (pc, buf, 4);
if (status != 0)
struct type *type = check_typedef (value_type (arg));
/* The corresponding parameter that is pushed onto the
stack, and [possibly] passed in a register. */
- char param_val[8];
+ gdb_byte param_val[8];
int param_len;
memset (param_val, 0, sizeof param_val);
if (TYPE_LENGTH (type) > 8)
addr += 2 * 8)
{
ULONGEST opdaddr;
- char tmp[8];
+ gdb_byte tmp[8];
if (target_read_memory (addr, tmp, sizeof (tmp)))
break;
/* Handle 32/64-bit struct return conventions. */
static enum return_value_convention
-hppa32_return_value (struct gdbarch *gdbarch, struct type *func_type,
+hppa32_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
}
static enum return_value_convention
-hppa64_return_value (struct gdbarch *gdbarch, struct type *func_type,
+hppa64_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
}
/* Return the register number for a GR which is saved by INST or
- zero it INST does not save a GR. */
+ zero if INST does not save a GR.
-static int
-inst_saves_gr (unsigned long inst)
-{
- /* Does it look like a stw? */
- if ((inst >> 26) == 0x1a || (inst >> 26) == 0x1b
- || (inst >> 26) == 0x1f
- || ((inst >> 26) == 0x1f
- && ((inst >> 6) == 0xa)))
- return hppa_extract_5R_store (inst);
+ Referenced from:
- /* Does it look like a std? */
- if ((inst >> 26) == 0x1c
- || ((inst >> 26) == 0x03
- && ((inst >> 6) & 0xf) == 0xb))
- return hppa_extract_5R_store (inst);
+ parisc 1.1:
+ https://parisc.wiki.kernel.org/images-parisc/6/68/Pa11_acd.pdf
- /* Does it look like a stwm? GCC & HPC may use this in prologues. */
- if ((inst >> 26) == 0x1b)
- return hppa_extract_5R_store (inst);
+ parisc 2.0:
+ https://parisc.wiki.kernel.org/images-parisc/7/73/Parisc2.0.pdf
- /* Does it look like sth or stb? HPC versions 9.0 and later use these
- too. */
- if ((inst >> 26) == 0x19 || (inst >> 26) == 0x18
- || ((inst >> 26) == 0x3
- && (((inst >> 6) & 0xf) == 0x8
- || (inst >> 6) & 0xf) == 0x9))
- return hppa_extract_5R_store (inst);
+ According to Table 6-5 of Chapter 6 (Memory Reference Instructions)
+ on page 106 in parisc 2.0, all instructions for storing values from
+ the general registers are:
- return 0;
+ Store: stb, sth, stw, std (according to Chapter 7, they
+ are only in both "inst >> 26" and "inst >> 6".
+ Store Absolute: stwa, stda (according to Chapter 7, they are only
+ in "inst >> 6".
+ Store Bytes: stby, stdby (according to Chapter 7, they are
+ only in "inst >> 6").
+
+ For (inst >> 26), according to Chapter 7:
+
+ The effective memory reference address is formed by the addition
+ of an immediate displacement to a base value.
+
+ - stb: 0x18, store a byte from a general register.
+
+ - sth: 0x19, store a halfword from a general register.
+
+ - stw: 0x1a, store a word from a general register.
+
+ - stwm: 0x1b, store a word from a general register and perform base
+ register modification (2.0 will still treate it as stw).
+
+ - std: 0x1c, store a doubleword from a general register (2.0 only).
+
+ - stw: 0x1f, store a word from a general register (2.0 only).
+
+ For (inst >> 6) when ((inst >> 26) == 0x03), according to Chapter 7:
+
+ The effective memory reference address is formed by the addition
+ of an index value to a base value specified in the instruction.
+
+ - stb: 0x08, store a byte from a general register (1.1 calls stbs).
+
+ - sth: 0x09, store a halfword from a general register (1.1 calls
+ sths).
+
+ - stw: 0x0a, store a word from a general register (1.1 calls stws).
+
+ - std: 0x0b: store a doubleword from a general register (2.0 only)
+
+ Implement fast byte moves (stores) to unaligned word or doubleword
+ destination.
+
+ - stby: 0x0c, for unaligned word (1.1 calls stbys).
+
+ - stdby: 0x0d for unaligned doubleword (2.0 only).
+
+ Store a word or doubleword using an absolute memory address formed
+ using short or long displacement or indexed
+
+ - stwa: 0x0e, store a word from a general register to an absolute
+ address (1.0 calls stwas).
+
+ - stda: 0x0f, store a doubleword from a general register to an
+ absolute address (2.0 only). */
+
+static int
+inst_saves_gr (unsigned long inst)
+{
+ switch ((inst >> 26) & 0x0f)
+ {
+ case 0x03:
+ switch ((inst >> 6) & 0x0f)
+ {
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ case 0x0e:
+ case 0x0f:
+ return hppa_extract_5R_store (inst);
+ default:
+ return 0;
+ }
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ /* no 0x1d or 0x1e -- according to parisc 2.0 document */
+ case 0x1f:
+ return hppa_extract_5R_store (inst);
+ default:
+ return 0;
+ }
}
/* Return the register number for a FR which is saved by INST or
int stop_before_branch)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- char buf[4];
+ gdb_byte buf[4];
CORE_ADDR orig_pc = pc;
unsigned long inst, stack_remaining, save_gr, save_fr, save_rp, save_sp;
unsigned long args_stored, status, i, restart_gr, restart_fr;
{
struct symtab_and_line sal;
CORE_ADDR func_addr, func_end;
- struct symbol *f;
/* If we can not find the symbol in the partial symbol table, then
there is no hope we can determine the function's start address
static CORE_ADDR
hppa_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
{
- unsigned long inst;
- int offset;
CORE_ADDR post_prologue_pc;
- char buf[4];
/* 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
struct hppa_frame_cache *cache;
long saved_gr_mask;
long saved_fr_mask;
- CORE_ADDR this_sp;
long frame_size;
struct unwind_table_entry *u;
CORE_ADDR prologue_end;
if (hppa_debug)
fprintf_unfiltered (gdb_stdlog, "base=%s (cached) }",
paddress (gdbarch, ((struct hppa_frame_cache *)*this_cache)->base));
- return (*this_cache);
+ return (struct hppa_frame_cache *) (*this_cache);
}
cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache);
(*this_cache) = cache;
{
if (hppa_debug)
fprintf_unfiltered (gdb_stdlog, "base=NULL (no unwind entry) }");
- return (*this_cache);
+ return (struct hppa_frame_cache *) (*this_cache);
}
/* Turn the Entry_GR field into a bitmask. */
pc += 4)
{
int reg;
- char buf4[4];
+ gdb_byte buf4[4];
long inst;
if (!safe_frame_unwind_memory (this_frame, pc, buf4, sizeof buf4))
{
error (_("Cannot read instruction at %s."),
paddress (gdbarch, pc));
- return (*this_cache);
+ return (struct hppa_frame_cache *) (*this_cache);
}
inst = extract_unsigned_integer (buf4, sizeof buf4, byte_order);
if (hppa_debug)
fprintf_unfiltered (gdb_stdlog, "base=%s }",
paddress (gdbarch, ((struct hppa_frame_cache *)*this_cache)->base));
- return (*this_cache);
+ return (struct hppa_frame_cache *) (*this_cache);
}
static void
struct unwind_table_entry *u;
if (*this_cache)
- return *this_cache;
+ return (struct hppa_stub_unwind_cache *) *this_cache;
info = FRAME_OBSTACK_ZALLOC (struct hppa_stub_unwind_cache);
*this_cache = info;
if (pc == 0
|| (tdep->in_solib_call_trampoline != NULL
- && tdep->in_solib_call_trampoline (gdbarch, pc, NULL))
+ && tdep->in_solib_call_trampoline (gdbarch, pc))
|| gdbarch_in_solib_return_trampoline (gdbarch, pc, NULL))
return 1;
return 0;
/* Return the minimal symbol whose name is NAME and stub type is STUB_TYPE.
Return NULL if no such symbol was found. */
-struct minimal_symbol *
+struct bound_minimal_symbol
hppa_lookup_stub_minimal_symbol (const char *name,
enum unwind_stub_types stub_type)
{
struct objfile *objfile;
struct minimal_symbol *msym;
+ struct bound_minimal_symbol result = { NULL, NULL };
ALL_MSYMBOLS (objfile, msym)
{
- if (strcmp (SYMBOL_LINKAGE_NAME (msym), name) == 0)
+ if (strcmp (MSYMBOL_LINKAGE_NAME (msym), name) == 0)
{
struct unwind_table_entry *u;
- u = find_unwind_entry (SYMBOL_VALUE (msym));
+ u = find_unwind_entry (MSYMBOL_VALUE (msym));
if (u != NULL && u->stub_unwind.stub_type == stub_type)
- return msym;
+ {
+ result.objfile = objfile;
+ result.minsym = msym;
+ return result;
+ }
}
}
- return NULL;
+ return result;
}
static void
}
static CORE_ADDR
-hppa_smash_text_address (struct gdbarch *gdbarch, CORE_ADDR addr)
+hppa_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
{
/* The low two bits of the PC on the PA contain the privilege level.
Some genius implementing a (non-GCC) compiler apparently decided
return frame_unwind_got_constant (this_frame, regnum, pc + 4);
}
- /* Make sure the "flags" register is zero in all unwound frames.
- The "flags" registers is a HP-UX specific wart, and only the code
- in hppa-hpux-tdep.c depends on it. However, it is easier to deal
- with it here. This shouldn't affect other systems since those
- should provide zero for the "flags" register anyway. */
- if (regnum == HPPA_FLAGS_REGNUM)
- return frame_unwind_got_constant (this_frame, regnum, 0);
-
return trad_frame_get_prev_register (this_frame, saved_regs, regnum);
}
\f
{ 0, 0 }
};
-static struct insn_pattern hppa_sigtramp[] = {
- /* ldi 0, %r25 or ldi 1, %r25 */
- { 0x34190000, 0xfffffffd },
- /* ldi __NR_rt_sigreturn, %r20 */
- { 0x3414015a, 0xffffffff },
- /* be,l 0x100(%sr2, %r0), %sr0, %r31 */
- { 0xe4008200, 0xffffffff },
- /* nop */
- { 0x08000240, 0xffffffff },
- { 0, 0 }
-};
-
/* Maximum number of instructions on the patterns above. */
#define HPPA_MAX_INSN_PATTERN_LEN 4
}
int
-hppa_in_solib_call_trampoline (struct gdbarch *gdbarch,
- CORE_ADDR pc, char *name)
+hppa_in_solib_call_trampoline (struct gdbarch *gdbarch, CORE_ADDR pc)
{
unsigned int insn[HPPA_MAX_INSN_PATTERN_LEN];
struct unwind_table_entry *u;
- if (in_plt_section (pc, name) || hppa_in_dyncall (pc))
+ if (in_plt_section (pc) || hppa_in_dyncall (pc))
return 1;
/* The GNU toolchain produces linker stubs without unwind
/* fallthrough */
}
- if (in_plt_section (pc, NULL))
+ if (in_plt_section (pc))
{
pc = read_memory_typed_address (pc, func_ptr_type);
/* If the PLT slot has not yet been resolved, the target will be
the PLT stub. */
- if (in_plt_section (pc, NULL))
+ if (in_plt_section (pc))
{
/* Sanity check: are we pointing to the PLT stub? */
if (!hppa_match_insns (gdbarch, pc, hppa_plt_stub, insn))
return (arches->gdbarch);
/* If none found, then allocate and initialize one. */
- tdep = XZALLOC (struct gdbarch_tdep);
+ tdep = XCNEW (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
/* Determine from the bfd_arch_info structure if we are dealing with
/* The following gdbarch vector elements do not depend on the address
size, or in any other gdbarch element previously set. */
set_gdbarch_skip_prologue (gdbarch, hppa_skip_prologue);
- set_gdbarch_in_function_epilogue_p (gdbarch,
- hppa_in_function_epilogue_p);
+ set_gdbarch_stack_frame_destroyed_p (gdbarch,
+ hppa_stack_frame_destroyed_p);
set_gdbarch_inner_than (gdbarch, core_addr_greaterthan);
set_gdbarch_sp_regnum (gdbarch, HPPA_SP_REGNUM);
set_gdbarch_fp0_regnum (gdbarch, HPPA_FP0_REGNUM);
- set_gdbarch_addr_bits_remove (gdbarch, hppa_smash_text_address);
- set_gdbarch_smash_text_address (gdbarch, hppa_smash_text_address);
+ set_gdbarch_addr_bits_remove (gdbarch, hppa_addr_bits_remove);
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_read_pc (gdbarch, hppa_read_pc);
set_gdbarch_write_pc (gdbarch, hppa_write_pc);