#define MASK_14 0x3fff
#define MASK_21 0x1fffff
-/* Define offsets into the call dummy for the _sr4export address.
- See comments related to CALL_DUMMY for more info. */
-#define SR4EXPORT_LDIL_OFFSET (HPPA_INSTRUCTION_SIZE * 12)
-#define SR4EXPORT_LDO_OFFSET (HPPA_INSTRUCTION_SIZE * 13)
-
/* Sizes (in bytes) of the native unwind entries. */
#define UNWIND_ENTRY_SIZE 16
#define STUB_UNWIND_ENTRY_SIZE 8
hppa_get_field (word, 11, 15) << 11 |
(word & 0x1) << 16, 17) << 2;
}
+
+CORE_ADDR
+hppa_symbol_address(const char *sym)
+{
+ struct minimal_symbol *minsym;
+
+ minsym = lookup_minimal_symbol (sym, NULL, NULL);
+ if (minsym)
+ return SYMBOL_VALUE_ADDRESS (minsym);
+ else
+ return (CORE_ADDR)-1;
+}
\f
/* Compare the start address for two unwind entries returning 1 if
arguments into their proper slots. */
CORE_ADDR
-hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+hppa32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
/* Two passes. First pass computes the location of everything,
second pass writes the bytes out. */
int write_pass;
+
+ /* Global pointer (r19) of the function we are trying to call. */
+ CORE_ADDR gp;
+
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
for (write_pass = 0; write_pass < 2; write_pass++)
{
CORE_ADDR struct_ptr = 0;
the higher-ordered word is stored in the lower-ordered
argument, and even though it is a 8-byte quantity the
registers need not be 8-byte aligned. */
- if (param_len > 4)
+ if (param_len > 4 && param_len < 8)
small_struct = 1;
}
if (struct_return)
write_register (28, struct_addr);
+ gp = tdep->find_global_pointer (function);
+
+ if (gp != 0)
+ write_register (19, gp);
+
/* Set the return address. */
regcache_cooked_write_unsigned (regcache, HPPA_RP_REGNUM, bp_addr);
to the callee, so we do that too. */
CORE_ADDR
-hppa64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
return param_end + 64;
}
+static CORE_ADDR
+hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+ CORE_ADDR addr,
+ struct target_ops *targ)
+{
+ if (addr & 2)
+ {
+ CORE_ADDR plabel;
+
+ plabel = addr & ~3;
+ target_read_memory(plabel, (char *)&addr, 4);
+ }
+
+ return addr;
+}
+
static CORE_ADDR
hppa32_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
{
old_save_sp = save_sp;
old_stack_remaining = stack_remaining;
- status = read_memory_nobpt (pc, buf, 4);
+ status = deprecated_read_memory_nobpt (pc, buf, 4);
inst = extract_unsigned_integer (buf, 4);
/* Yow! */
while (reg_num >= (TARGET_PTR_BIT == 64 ? 19 : 23) && reg_num <= 26)
{
pc += 4;
- status = read_memory_nobpt (pc, buf, 4);
+ status = deprecated_read_memory_nobpt (pc, buf, 4);
inst = extract_unsigned_integer (buf, 4);
if (status != 0)
return pc;
reg_num = inst_saves_fr (inst);
save_fr &= ~(1 << reg_num);
- status = read_memory_nobpt (pc + 4, buf, 4);
+ status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
next_inst = extract_unsigned_integer (buf, 4);
/* Yow! */
while (reg_num >= 4 && reg_num <= (TARGET_PTR_BIT == 64 ? 11 : 7))
{
pc += 8;
- status = read_memory_nobpt (pc, buf, 4);
+ status = deprecated_read_memory_nobpt (pc, buf, 4);
inst = extract_unsigned_integer (buf, 4);
if (status != 0)
return pc;
if ((inst & 0xfc000000) != 0x34000000)
break;
- status = read_memory_nobpt (pc + 4, buf, 4);
+ status = deprecated_read_memory_nobpt (pc + 4, buf, 4);
next_inst = extract_unsigned_integer (buf, 4);
if (status != 0)
return pc;
{
int reg;
char buf4[4];
- long status = read_memory_nobpt (pc, buf4, sizeof buf4);
+ long status = deprecated_read_memory_nobpt (pc, buf4, sizeof buf4);
long inst = extract_unsigned_integer (buf4, sizeof buf4);
/* Note the interesting effects of this instruction. */
and saved on the stack, the Save_SP flag is set. We use this to
decide whether to use the frame pointer for unwinding.
- fp should never be zero here; checking just in case.
+ fp may be zero if it is not available in an inner frame because
+ it has been modified by not yet saved.
TODO: For the HP compiler, maybe we should use the alloca_frame flag
instead of Save_SP. */
fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [frame pointer] }",
paddr_nz (cache->base));
}
- else if (frame_pc_unwind (next_frame) >= prologue_end)
+ else if (u->Save_SP
+ && trad_frame_addr_p (cache->saved_regs, HPPA_SP_REGNUM))
{
- if (u->Save_SP && trad_frame_addr_p (cache->saved_regs, HPPA_SP_REGNUM))
- {
/* Both we're expecting the SP to be saved and the SP has been
saved. The entry SP value is saved at this frame's SP
address. */
if (hppa_debug)
fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [saved] }",
paddr_nz (cache->base));
- }
- else
- {
- /* The prologue has been slowly allocating stack space. Adjust
- the SP back. */
- cache->base = this_sp - frame_size;
- if (hppa_debug)
- fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ",
- paddr_nz (cache->base));
-
- }
}
else
{
- /* This frame has not yet been created. */
- cache->base = this_sp;
-
+ /* The prologue has been slowly allocating stack space. Adjust
+ the SP back. */
+ cache->base = this_sp - frame_size;
if (hppa_debug)
- fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [before prologue] } ",
+ fprintf_unfiltered (gdb_stdlog, " (base=0x%s) [unwind adjust] } ",
paddr_nz (cache->base));
}
-
trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base);
}
as the return register while normal code uses "rp". */
if (u->Millicode)
{
- if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM))
+ if (trad_frame_addr_p (cache->saved_regs, 31))
cache->saved_regs[HPPA_PCOQ_HEAD_REGNUM] = cache->saved_regs[31];
else
{
}
}
+ /* If the frame pointer was not saved in this frame, but we should be saving
+ it, set it to an invalid value so that another frame will not pick up the
+ wrong frame pointer. This can happen if we start unwinding after the
+ frame pointer has been modified, but before we've saved it to the
+ stack. */
+ if (u->Save_SP && !trad_frame_addr_p (cache->saved_regs, HPPA_FP_REGNUM))
+ trad_frame_set_value (cache->saved_regs, HPPA_FP_REGNUM, 0);
+
{
/* Convert all the offsets into addresses. */
int reg;
hppa_fallback_frame_cache (struct frame_info *next_frame, void **this_cache)
{
struct hppa_frame_cache *cache;
+ unsigned int frame_size;
CORE_ADDR pc, start_pc, end_pc, cur_pc;
cache = FRAME_OBSTACK_ZALLOC (struct hppa_frame_cache);
pc = frame_func_unwind (next_frame);
cur_pc = frame_pc_unwind (next_frame);
+ frame_size = 0;
find_pc_partial_function (pc, NULL, &start_pc, &end_pc);
insn = read_memory_unsigned_integer (pc, 4);
+ frame_size += prologue_inst_adjust_sp (insn);
+
/* There are limited ways to store the return pointer into the
stack. */
if (insn == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */
- {
- cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
- break;
- }
+ cache->saved_regs[HPPA_RP_REGNUM].addr = -20;
else if (insn == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */
- {
- cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
- break;
- }
+ cache->saved_regs[HPPA_RP_REGNUM].addr = -16;
}
- cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM);
+ cache->base = frame_unwind_register_unsigned (next_frame, HPPA_SP_REGNUM) - frame_size;
+ trad_frame_set_value (cache->saved_regs, HPPA_SP_REGNUM, cache->base);
if (trad_frame_addr_p (cache->saved_regs, HPPA_RP_REGNUM))
{
return &hppa_fallback_frame_unwind;
}
-static CORE_ADDR
-hppa_frame_base_address (struct frame_info *next_frame,
- void **this_cache)
-{
- struct hppa_frame_cache *info = hppa_frame_cache (next_frame,
- this_cache);
- return info->base;
-}
-
-static const struct frame_base hppa_frame_base = {
- &hppa_frame_unwind,
- hppa_frame_base_address,
- hppa_frame_base_address,
- hppa_frame_base_address
-};
-
-static const struct frame_base *
-hppa_frame_base_sniffer (struct frame_info *next_frame)
-{
- return &hppa_frame_base;
-}
-
/* Stub frames, used for all kinds of call stubs. */
struct hppa_stub_unwind_cache
{
{
CORE_ADDR pc = frame_pc_unwind (next_frame);
- if (IN_SOLIB_CALL_TRAMPOLINE (pc, NULL)
+ if (pc == 0
+ || IN_SOLIB_CALL_TRAMPOLINE (pc, NULL)
|| IN_SOLIB_RETURN_TRAMPOLINE (pc, NULL))
return &hppa_stub_frame_unwind;
return NULL;
store_unsigned_integer (buf, sizeof(tmp), tmp);
}
+static CORE_ADDR
+hppa_find_global_pointer (struct value *function)
+{
+ return 0;
+}
+
void
hppa_frame_prev_register_helper (struct frame_info *next_frame,
struct trad_frame_saved_reg saved_regs[],
enum lval_type *lvalp, CORE_ADDR *addrp,
int *realnump, void *valuep)
{
- int pcoqt = (regnum == HPPA_PCOQ_TAIL_REGNUM);
- struct gdbarch *gdbarch = get_frame_arch (next_frame);
- int regsize = register_size (gdbarch, HPPA_PCOQ_HEAD_REGNUM);
+ if (regnum == HPPA_PCOQ_TAIL_REGNUM)
+ {
+ if (valuep)
+ {
+ CORE_ADDR pc;
- if (pcoqt)
- regnum = HPPA_PCOQ_HEAD_REGNUM;
+ trad_frame_get_prev_register (next_frame, saved_regs,
+ HPPA_PCOQ_HEAD_REGNUM, optimizedp,
+ lvalp, addrp, realnump, valuep);
- trad_frame_prev_register (next_frame, saved_regs, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
+ pc = extract_unsigned_integer (valuep, 4);
+ store_unsigned_integer (valuep, 4, pc + 4);
+ }
+
+ /* It's a computed value. */
+ *optimizedp = 0;
+ *lvalp = not_lval;
+ *addrp = 0;
+ *realnump = -1;
+ return;
+ }
- if (pcoqt)
- store_unsigned_integer (valuep, regsize,
- extract_unsigned_integer (valuep, regsize) + 4);
+ trad_frame_get_prev_register (next_frame, saved_regs, regnum,
+ optimizedp, lvalp, addrp, realnump, valuep);
}
+\f
/* 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
else
tdep->bytes_per_address = 4;
+ tdep->find_global_pointer = hppa_find_global_pointer;
+
/* Some parts of the gdbarch vector depend on whether we are running
on a 32 bits or 64 bits target. */
switch (tdep->bytes_per_address)
case 4:
set_gdbarch_push_dummy_call (gdbarch, hppa32_push_dummy_call);
set_gdbarch_frame_align (gdbarch, hppa32_frame_align);
+ set_gdbarch_convert_from_func_ptr_addr
+ (gdbarch, hppa32_convert_from_func_ptr_addr);
break;
case 8:
set_gdbarch_push_dummy_call (gdbarch, hppa64_push_dummy_call);
frame_unwind_append_sniffer (gdbarch, hppa_stub_unwind_sniffer);
frame_unwind_append_sniffer (gdbarch, hppa_frame_unwind_sniffer);
frame_unwind_append_sniffer (gdbarch, hppa_fallback_unwind_sniffer);
- frame_base_append_sniffer (gdbarch, hppa_frame_base_sniffer);
return gdbarch;
}
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);
+ deprecated_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);
}
-