mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-09-10 10:12:21 +08:00
* hppah-tdep.c (frame_saved_pc): Use better test for outermost
frame. Use find_return_regnum to find the caller. * (find_unwind_entry): New routine to locate stack frame info associated with a procedure. This looks in the $UNWIND_START$ section in the SOM file. * (find_return_regnum): New routine. Uses find_unwind_entry() to figure out where the caller's return address is stored. * (find_proc_framesize): New routine. Uses find_unwind_entry() to figure out the frame size for a procedure. * (saved_pc_after_call): New routine, moved from tm-hppa.h. * (init_extra_frame_info): New routine. Corrects PC and FP for outermost frame if necessary. * (frame_chain): New routine, moved from tm-hppa.h. * (skip_trampoline_code): Handle computed function calls (ie: calls from $$dyncall). * (unwind_command): Temporary support function to allow user to control/observe aspects of the unwind (stack frame) info. * infcmd.c (read_pc): (Temporary), put a hack in to see if the PC was in a system call, if so, then read the PC from r31. * tm-hppah.h (SKIP_TRAMPOLINE_CODE, IN_SOLIB_TRAMPOLINE): Deal with extra arg for skip_trampoline_code(). * (INIT_EXTRA_FRAME_INFO): Define to point at subr (see above). * (FRAME_CHAIN, FRAME_CHAIN_VALID): Turn into real subroutines. * tm-hppa.h (SAVED_PC_AFTER_CALL): Turn into real subroutine.
This commit is contained in:
@ -1,3 +1,30 @@
|
||||
Mon Dec 28 15:00:01 1992 Stu Grossman (grossman at cygnus.com)
|
||||
|
||||
* hppah-tdep.c (frame_saved_pc): Use better test for outermost
|
||||
frame. Use find_return_regnum to find the caller.
|
||||
* (find_unwind_entry): New routine to locate stack frame info
|
||||
associated with a procedure. This looks in the $UNWIND_START$
|
||||
section in the SOM file.
|
||||
* (find_return_regnum): New routine. Uses find_unwind_entry() to
|
||||
figure out where the caller's return address is stored.
|
||||
* (find_proc_framesize): New routine. Uses find_unwind_entry()
|
||||
to figure out the frame size for a procedure.
|
||||
* (saved_pc_after_call): New routine, moved from tm-hppa.h.
|
||||
* (init_extra_frame_info): New routine. Corrects PC and FP for
|
||||
outermost frame if necessary.
|
||||
* (frame_chain): New routine, moved from tm-hppa.h.
|
||||
* (skip_trampoline_code): Handle computed function calls (ie:
|
||||
calls from $$dyncall).
|
||||
* (unwind_command): Temporary support function to allow user
|
||||
to control/observe aspects of the unwind (stack frame) info.
|
||||
* infcmd.c (read_pc): (Temporary), put a hack in to see if the PC
|
||||
was in a system call, if so, then read the PC from r31.
|
||||
* tm-hppah.h (SKIP_TRAMPOLINE_CODE, IN_SOLIB_TRAMPOLINE): Deal
|
||||
with extra arg for skip_trampoline_code().
|
||||
* (INIT_EXTRA_FRAME_INFO): Define to point at subr (see above).
|
||||
* (FRAME_CHAIN, FRAME_CHAIN_VALID): Turn into real subroutines.
|
||||
* tm-hppa.h (SAVED_PC_AFTER_CALL): Turn into real subroutine.
|
||||
|
||||
Sun Dec 27 17:34:15 1992 Fred Fish (fnf@cygnus.com)
|
||||
|
||||
* dbxread.c (dbx_symfile_init, elfstab_build_psymtabs):
|
||||
|
213
gdb/hppah-tdep.c
213
gdb/hppah-tdep.c
@ -260,29 +260,150 @@ extract_17 (word)
|
||||
(word & 0x1) << 16, 17) << 2;
|
||||
}
|
||||
|
||||
int use_unwind = 0;
|
||||
|
||||
static struct unwind_table_entry *
|
||||
find_unwind_entry(pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
static struct unwind_table_entry *unwind = NULL, *unwind_end;
|
||||
struct unwind_table_entry *u;
|
||||
|
||||
if (!use_unwind)
|
||||
return NULL;
|
||||
|
||||
if (!unwind)
|
||||
{
|
||||
asection *unwind_sec;
|
||||
|
||||
unwind_sec = bfd_get_section_by_name (exec_bfd, "$UNWIND_START$");
|
||||
if (unwind_sec)
|
||||
{
|
||||
int size;
|
||||
|
||||
size = bfd_section_size (exec_bfd, unwind_sec);
|
||||
unwind = malloc (size);
|
||||
unwind_end = unwind + size/sizeof (struct unwind_table_entry);
|
||||
|
||||
bfd_get_section_contents (exec_bfd, unwind_sec, unwind, 0, size);
|
||||
}
|
||||
}
|
||||
|
||||
for (u = unwind; u < unwind_end; u++)
|
||||
{
|
||||
if (pc >= u->region_start
|
||||
&& pc <= u->region_end)
|
||||
return u;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
find_return_regnum(pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
struct unwind_table_entry *u;
|
||||
|
||||
u = find_unwind_entry (pc);
|
||||
|
||||
if (!u)
|
||||
return RP_REGNUM;
|
||||
|
||||
if (u->Millicode)
|
||||
return 31;
|
||||
|
||||
return RP_REGNUM;
|
||||
}
|
||||
|
||||
int
|
||||
find_proc_framesize(pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
struct unwind_table_entry *u;
|
||||
|
||||
u = find_unwind_entry (pc);
|
||||
|
||||
if (!u)
|
||||
return -1;
|
||||
|
||||
return u->Total_frame_size << 3;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
saved_pc_after_call (frame)
|
||||
FRAME frame;
|
||||
{
|
||||
int ret_regnum;
|
||||
|
||||
ret_regnum = find_return_regnum (get_frame_pc (frame));
|
||||
|
||||
return read_register (ret_regnum) & ~0x3;
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
frame_saved_pc (frame)
|
||||
FRAME frame;
|
||||
{
|
||||
if (get_current_frame () == frame)
|
||||
if (!frame->next)
|
||||
{
|
||||
struct frame_saved_regs saved_regs;
|
||||
CORE_ADDR pc = get_frame_pc (frame);
|
||||
int flags;
|
||||
int ret_regnum;
|
||||
|
||||
flags = read_register (FLAGS_REGNUM);
|
||||
get_frame_saved_regs (frame, &saved_regs);
|
||||
if (pc >= millicode_start && pc < millicode_end
|
||||
|| (flags & 2)) /* In system call? */
|
||||
return read_register (31) & ~3;
|
||||
else if (saved_regs.regs[RP_REGNUM])
|
||||
return read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~3;
|
||||
else
|
||||
return read_register (RP_REGNUM) & ~3;
|
||||
ret_regnum = find_return_regnum (pc);
|
||||
|
||||
return read_register (ret_regnum) & ~0x3;
|
||||
}
|
||||
return read_memory_integer (frame->frame - 20, 4) & ~0x3;
|
||||
}
|
||||
|
||||
/* We need to correct the PC and the FP for the outermost frame when we are
|
||||
in a system call. */
|
||||
|
||||
void
|
||||
init_extra_frame_info (fromleaf, frame)
|
||||
int fromleaf;
|
||||
struct frame_info *frame;
|
||||
{
|
||||
int flags;
|
||||
int framesize;
|
||||
|
||||
if (frame->next) /* Only do this for outermost frame */
|
||||
return;
|
||||
|
||||
flags = read_register (FLAGS_REGNUM);
|
||||
if (flags & 2) /* In system call? */
|
||||
frame->pc = read_register (31) & ~0x3;
|
||||
|
||||
/* The outermost frame is always derived from PC-framesize */
|
||||
framesize = find_proc_framesize(frame->pc);
|
||||
if (framesize == -1)
|
||||
frame->frame = read_register (FP_REGNUM);
|
||||
else
|
||||
frame->frame = read_register (SP_REGNUM) - framesize;
|
||||
|
||||
if (framesize != 0) /* Frameless? */
|
||||
return;
|
||||
|
||||
/* For frameless functions, we need to look at the caller's frame */
|
||||
framesize = find_proc_framesize(FRAME_SAVED_PC(frame));
|
||||
if (framesize != -1)
|
||||
frame->frame -= framesize;
|
||||
}
|
||||
|
||||
FRAME_ADDR
|
||||
frame_chain (frame)
|
||||
struct frame_info *frame;
|
||||
{
|
||||
int framesize;
|
||||
|
||||
framesize = find_proc_framesize(FRAME_SAVED_PC(frame));
|
||||
|
||||
if (framesize != -1)
|
||||
return frame->frame - framesize;
|
||||
|
||||
return read_memory_integer (frame->frame, 4);
|
||||
}
|
||||
|
||||
/* To see if a frame chain is valid, see if the caller looks like it
|
||||
was compiled with gcc. */
|
||||
|
||||
@ -293,7 +414,6 @@ int frame_chain_valid (chain, thisframe)
|
||||
if (chain && (chain > 0x60000000))
|
||||
{
|
||||
CORE_ADDR pc = get_pc_function_start (FRAME_SAVED_PC (thisframe));
|
||||
|
||||
if (inside_entry_file (pc))
|
||||
return 0;
|
||||
/* look for stw rp, -20(0,sp); copy 4,1; copy sp, 4 */
|
||||
@ -629,13 +749,32 @@ pa_print_fp_reg (i)
|
||||
small piece of code that does long format (`external' in HPPA parlance)
|
||||
jumps. We figure out where the trampoline is going to end up, and return
|
||||
the PC of the final destination. If we aren't in a trampoline, we just
|
||||
return NULL. */
|
||||
return NULL.
|
||||
|
||||
For computed calls, we just extract the new PC from r22. */
|
||||
|
||||
CORE_ADDR
|
||||
skip_trampoline_code (pc)
|
||||
skip_trampoline_code (pc, name)
|
||||
CORE_ADDR pc;
|
||||
char *name;
|
||||
{
|
||||
long inst0, inst1;
|
||||
static CORE_ADDR dyncall = 0;
|
||||
struct minimal_symbol *msym;
|
||||
|
||||
/* FIXME XXX - dyncall must be initialized whenever we get a new exec file */
|
||||
|
||||
if (!dyncall)
|
||||
{
|
||||
msym = lookup_minimal_symbol ("$$dyncall", NULL);
|
||||
if (msym)
|
||||
dyncall = msym->address;
|
||||
else
|
||||
dyncall = -1;
|
||||
}
|
||||
|
||||
if (pc == dyncall)
|
||||
return (CORE_ADDR)(read_register (22) & ~0x3);
|
||||
|
||||
inst0 = read_memory_integer (pc, 4);
|
||||
inst1 = read_memory_integer (pc+4, 4);
|
||||
@ -644,7 +783,49 @@ skip_trampoline_code (pc)
|
||||
&& (inst1 & 0xffe0e002) == 0xe0202002) /* be,n yyy(sr4, r1) */
|
||||
pc = extract_21 (inst0) + extract_17 (inst1);
|
||||
else
|
||||
pc = NULL;
|
||||
pc = (CORE_ADDR)NULL;
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
static void
|
||||
unwind_command (exp, from_tty)
|
||||
char *exp;
|
||||
int from_tty;
|
||||
{
|
||||
CORE_ADDR address;
|
||||
union
|
||||
{
|
||||
int *foo;
|
||||
struct unwind_table_entry *u;
|
||||
} xxx;
|
||||
|
||||
/* If we have an expression, evaluate it and use it as the address. */
|
||||
|
||||
if (exp != 0 && *exp != 0)
|
||||
address = parse_and_eval_address (exp);
|
||||
else
|
||||
return;
|
||||
|
||||
xxx.u = find_unwind_entry (address);
|
||||
|
||||
if (!xxx.u)
|
||||
{
|
||||
printf ("Can't find unwind table entry for PC 0x%x\n", address);
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("%08x\n%08X\n%08X\n%08X\n", xxx.foo[0], xxx.foo[1], xxx.foo[2],
|
||||
xxx.foo[3]);
|
||||
}
|
||||
|
||||
void
|
||||
_initialize_hppah_tdep ()
|
||||
{
|
||||
add_com ("unwind", class_obscure, unwind_command, "Print unwind info\n");
|
||||
add_show_from_set
|
||||
(add_set_cmd ("use_unwind", class_obscure, var_boolean,
|
||||
(char *)&use_unwind,
|
||||
"Control the useage of unwind info.\n", &setlist),
|
||||
&showlist);
|
||||
}
|
||||
|
@ -877,6 +877,13 @@ path_command (dirname, from_tty)
|
||||
CORE_ADDR
|
||||
read_pc ()
|
||||
{
|
||||
#if GDB_TARGET_IS_HPPA
|
||||
int flags = read_register(FLAGS_REGNUM);
|
||||
|
||||
if (flags & 2)
|
||||
return read_register(31) & ~0x3;
|
||||
#endif
|
||||
|
||||
return ADDR_BITS_REMOVE ((CORE_ADDR) read_register (PC_REGNUM));
|
||||
}
|
||||
|
||||
|
@ -75,11 +75,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* If PC is in some function-call trampoline code, return the PC
|
||||
where the function itself actually starts. If not, return NULL. */
|
||||
|
||||
#define SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc)
|
||||
#define SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc, NULL)
|
||||
|
||||
/* Return non-zero if we are in some sort of a trampoline. */
|
||||
|
||||
#define IN_SOLIB_TRAMPOLINE(pc,name) skip_trampoline_code (pc)
|
||||
#define IN_SOLIB_TRAMPOLINE(pc, name) skip_trampoline_code (pc, name)
|
||||
|
||||
/* Immediately after a function call, return the saved pc.
|
||||
Can't go through the frames for this because on some machines
|
||||
@ -290,11 +290,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
((regno) >= PCSQ_TAIL_REGNUM && (regno) < IPSW_REGNUM) || \
|
||||
((regno) > IPSW_REGNUM && (regno) < FP4_REGNUM)
|
||||
|
||||
/* This is a piece of magic that is given a register number REGNO
|
||||
and as BLOCKEND the address in the system of the end of the user structure
|
||||
and stores in ADDR the address in the kernel or core dump
|
||||
of that register. */
|
||||
|
||||
#define INIT_EXTRA_FRAME_INFO(fromleaf, frame) init_extra_frame_info (fromleaf, frame)
|
||||
|
||||
/* Describe the pointer in each stack frame to the previous stack frame
|
||||
(its caller). */
|
||||
@ -313,13 +309,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
is the address of a 4-byte word containing the calling frame's
|
||||
address (previous FP). */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) \
|
||||
(!inside_entry_file ((thisframe)->pc) ? \
|
||||
read_memory_integer ((thisframe)->frame, 4) :\
|
||||
0)
|
||||
#define FRAME_CHAIN(thisframe) frame_chain (thisframe)
|
||||
|
||||
#if 0
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
frame_chain_valid (chain, thisframe)
|
||||
#endif
|
||||
|
||||
#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
|
||||
|
||||
|
@ -32,11 +32,7 @@ extern CORE_ADDR millicode_start, millicode_end;
|
||||
some instructions. */
|
||||
|
||||
#undef SAVED_PC_AFTER_CALL
|
||||
#define SAVED_PC_AFTER_CALL(frame) \
|
||||
((get_frame_pc (frame) >= millicode_start \
|
||||
&& get_frame_pc (frame) < millicode_end) ? \
|
||||
read_register (31) & ~3 \
|
||||
: read_register (RP_REGNUM) & ~3)
|
||||
#define SAVED_PC_AFTER_CALL(frame) saved_pc_after_call (frame)
|
||||
|
||||
/* We need to figure out where the text region is so that we use the
|
||||
appropriate ptrace operator to manipulate text. Simply reading/writing
|
||||
|
Reference in New Issue
Block a user