u = find_unwind_entry (frame->pc);
if (u == 0)
- return frameless_look_for_prologue (frame);
+ return 0;
return (u->Total_frame_size == 0 && u->stub_type == 0);
}
FRAME frame;
{
CORE_ADDR pc = get_frame_pc (frame);
+ struct unwind_table_entry *u;
/* BSD, HPUX & OSF1 all lay out the hardware state in the same manner
at the base of the frame in an interrupt handler. Registers within
return rp;
}
+restart:
if (frameless_function_invocation (frame))
{
int ret_regnum;
fi = get_frame_info (frame->next);
get_frame_saved_regs (fi, &saved_regs);
if (read_memory_integer (saved_regs.regs[FLAGS_REGNUM] & 0x2, 4))
- return read_memory_integer (saved_regs.regs[31], 4);
+ pc = read_memory_integer (saved_regs.regs[31], 4) & ~0x3;
else
- return read_memory_integer (saved_regs.regs[RP_REGNUM], 4);
+ pc = read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~0x3;
}
else
- return read_register (ret_regnum) & ~0x3;
+ pc = read_register (ret_regnum) & ~0x3;
}
else
{
fi = get_frame_info (frame->next);
get_frame_saved_regs (fi, &saved_regs);
if (read_memory_integer (saved_regs.regs[FLAGS_REGNUM] & 0x2, 4))
- return read_memory_integer (saved_regs.regs[31], 4);
+ pc = read_memory_integer (saved_regs.regs[31], 4) & ~0x3;
else
- return read_memory_integer (saved_regs.regs[RP_REGNUM], 4);
+ pc = read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~0x3;
}
else if (rp_offset == 0)
- return read_register (RP_REGNUM) & ~0x3;
+ pc = read_register (RP_REGNUM) & ~0x3;
else
- return read_memory_integer (frame->frame + rp_offset, 4) & ~0x3;
+ pc = read_memory_integer (frame->frame + rp_offset, 4) & ~0x3;
}
+
+ /* If PC is inside a linker stub, then dig out the address the stub
+ will return to. */
+ u = find_unwind_entry (pc);
+ if (u && u->stub_type != 0)
+ goto restart;
+
+ return pc;
}
\f
/* We need to correct the PC and the FP for the outermost frame when we are
CORE_ADDR dyncall_addr, sr4export_addr;
struct minimal_symbol *msymbol;
int flags = read_register (FLAGS_REGNUM);
+ struct unwind_table_entry *u;
msymbol = lookup_minimal_symbol ("$$dyncall", (struct objfile *) NULL);
if (msymbol == NULL)
dyncall_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ /* FUN could be a procedure label, in which case we have to get
+ its real address and the value of its GOT/DP. */
+ if (fun & 0x2)
+ {
+ /* Get the GOT/DP value for the target function. It's
+ at *(fun+4). Note the call dummy is *NOT* allowed to
+ trash %r19 before calling the target function. */
+ write_register (19, read_memory_integer ((fun & ~0x3) + 4, 4));
+
+ /* Now get the real address for the function we are calling, it's
+ at *fun. */
+ fun = (CORE_ADDR) read_memory_integer (fun & ~0x3, 4);
+ }
+
+ /* If we are calling an import stub (eg calling into a dynamic library)
+ then have sr4export call the magic __d_plt_call routine which is linked
+ in from end.o. (You can't use _sr4export to call the import stub as
+ the value in sp-24 will get fried and you end up returning to the
+ wrong location. You can't call the import stub directly as the code
+ to bind the PLT entry to a function can't return to a stack address.) */
+ u = find_unwind_entry (fun);
+ if (u && u->stub_type == IMPORT)
+ {
+ CORE_ADDR new_fun;
+ msymbol = lookup_minimal_symbol ("__d_plt_call", (struct objfile *) NULL);
+ if (msymbol == NULL)
+ error ("Can't find an address for __d_plt_call trampoline");
+
+ /* This is where sr4export will jump to. */
+ new_fun = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ /* We have to store the address of the stub in __shlib_funcptr. */
+ msymbol = lookup_minimal_symbol ("__shlib_funcptr",
+ (struct objfile *)NULL);
+ if (msymbol == NULL)
+ error ("Can't find an address for __shlib_funcptr");
+
+ target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol), (char *)&fun, 4);
+ fun = new_fun;
+
+ }
+
+ /* We still need sr4export's address too. */
msymbol = lookup_minimal_symbol ("_sr4export", (struct objfile *) NULL);
if (msymbol == NULL)
error ("Can't find an address for _sr4export trampoline");