#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
/* 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. */
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. */
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
{
/* 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);
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;
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;
}
{
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 */
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 */
&& 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];
}
first = middle + 1;
}
} /* ALL_OBJFILES() */
+
+ if (hppa_debug)
+ fprintf_unfiltered (gdb_stdlog, "NULL (not found) }\n");
+
return NULL;
}
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.
/* 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);
/* 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);
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;
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;
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;
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;
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);
/* 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;
}
}
+ if (hppa_debug)
+ fprintf_unfiltered (gdb_stdlog, "base=0x%s }",
+ paddr_nz (((struct hppa_frame_cache *)*this_cache)->base));
return (*this_cache);
}
/* 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)
{
/* 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
}
-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.
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:
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
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);
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
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);
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);
}