* c-typeprint.c (c_type_print_base): Use `show' of -1 to print
the return type of methods to avoid infinite loops with anonymous types. * valops.c (search_struct_field): Handle anonymous unions. * sparc-tdep.c (sunos4_skip_trampoline_code): New function to correctly handle steps into -g compiled PIC objects in the main executable. * config/sparc/tm-sun4os4.h (SKIP_TRAMPOLINE_CODE): Redefine to use sunos4_skip_trampoline_code. * dwarfread.c (DWARF_REG_TO_REGNUM): Provide a default mapping from DWARF to GDB register numbering. * dwarfread.c (locval): Use DWARF_REG_TO_REGNUM to map the register value. * config/mips/tm-mipsv4.h (DWARF_REG_TO_REGNUM): Define.
This commit is contained in:
parent
091f3a62a8
commit
84bdfea6aa
|
@ -1,3 +1,26 @@
|
|||
Sat Dec 17 02:33:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
|
||||
|
||||
* c-typeprint.c (c_type_print_base): Use `show' of -1 to print
|
||||
the return type of methods to avoid infinite loops with anonymous
|
||||
types.
|
||||
* valops.c (search_struct_field): Handle anonymous unions.
|
||||
|
||||
* sparc-tdep.c (sunos4_skip_trampoline_code): New function
|
||||
to correctly handle steps into -g compiled PIC objects in the
|
||||
main executable.
|
||||
* config/sparc/tm-sun4os4.h (SKIP_TRAMPOLINE_CODE):
|
||||
Redefine to use sunos4_skip_trampoline_code.
|
||||
|
||||
* dwarfread.c (DWARF_REG_TO_REGNUM): Provide a default mapping
|
||||
from DWARF to GDB register numbering.
|
||||
* dwarfread.c (locval): Use DWARF_REG_TO_REGNUM to map the
|
||||
register value.
|
||||
* config/mips/tm-mipsv4.h (DWARF_REG_TO_REGNUM): Define.
|
||||
|
||||
Fri Dec 16 10:56:29 1994 J.T. Conklin <jtc@rtl.cygnus.com>
|
||||
|
||||
* Makefile.in (uninstall): transform file names.
|
||||
|
||||
Thu Dec 15 16:55:35 1994 Stan Shebs <shebs@andros.cygnus.com>
|
||||
|
||||
* defs.h: Include progress.h.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* Support for printing C and C++ types for GDB, the GNU debugger.
|
||||
Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
|
||||
Copyright 1986, 1988, 1989, 1991, 1993, 1994
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
@ -692,7 +693,7 @@ c_type_print_base (type, stream, show, level)
|
|||
else if (!is_constructor && !is_full_physname_constructor)
|
||||
{
|
||||
type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
|
||||
"", stream, 0);
|
||||
"", stream, -1);
|
||||
fputs_filtered (" ", stream);
|
||||
}
|
||||
if (TYPE_FN_FIELD_STUB (f, j))
|
||||
|
|
|
@ -39,3 +39,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
|
||||
/* Use the alternate method of determining valid frame chains. */
|
||||
#define FRAME_CHAIN_VALID_ALTERNATE
|
||||
|
||||
/* Convert a DWARF register number to a gdb REGNUM. */
|
||||
#define DWARF_REG_TO_REGNUM(num) ((num) < 32 ? (num) : (num)+FP0_REGNUM-32)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* Macro definitions for GDB for a Sun 4 running sunos 4.
|
||||
Copyright 1989, 1992 Free Software Foundation, Inc.
|
||||
Copyright 1989, 1992, 1994 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
@ -20,6 +20,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include "sparc/tm-sparc.h"
|
||||
#include "tm-sunos.h"
|
||||
|
||||
/* Redefine SKIP_TRAMPOLINE_CODE to handle PIC compiled modules
|
||||
in main executables. */
|
||||
|
||||
#undef SKIP_TRAMPOLINE_CODE
|
||||
#define SKIP_TRAMPOLINE_CODE(pc) sunos4_skip_trampoline_code (pc)
|
||||
extern CORE_ADDR sunos4_skip_trampoline_code PARAMS ((CORE_ADDR));
|
||||
|
||||
/* Offsets into jmp_buf. Not defined by Sun, but at least documented in a
|
||||
comment in <machine/setjmp.h>! */
|
||||
|
||||
|
|
|
@ -192,6 +192,11 @@ typedef unsigned int DIE_REF; /* Reference to a DIE */
|
|||
#define CHILL_PRODUCER "GNU Chill "
|
||||
#endif
|
||||
|
||||
/* Provide a default mapping from a DWARF register number to a gdb REGNUM. */
|
||||
#ifndef DWARF_REG_TO_REGNUM
|
||||
#define DWARF_REG_TO_REGNUM(num) (num)
|
||||
#endif
|
||||
|
||||
/* Flags to target_to_host() that tell whether or not the data object is
|
||||
expected to be signed. Used, for example, when fetching a signed
|
||||
integer in the target environment which is used as a signed integer
|
||||
|
@ -2210,8 +2215,10 @@ locval (loc)
|
|||
break;
|
||||
case OP_REG:
|
||||
/* push register (number) */
|
||||
stack[++stacki] = target_to_host (loc, loc_value_size,
|
||||
GET_UNSIGNED, current_objfile);
|
||||
stack[++stacki]
|
||||
= DWARF_REG_TO_REGNUM (target_to_host (loc, loc_value_size,
|
||||
GET_UNSIGNED,
|
||||
current_objfile));
|
||||
loc += loc_value_size;
|
||||
isreg = 1;
|
||||
break;
|
||||
|
|
342
gdb/sparc-tdep.c
342
gdb/sparc-tdep.c
|
@ -31,6 +31,30 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
|
||||
#include "gdbcore.h"
|
||||
|
||||
/* Definition of SPARC instruction layouts. */
|
||||
|
||||
union sparc_insn_layout
|
||||
{
|
||||
unsigned long int code;
|
||||
struct
|
||||
{
|
||||
unsigned int op:2;
|
||||
unsigned int rd:5;
|
||||
unsigned int op2:3;
|
||||
unsigned int imm22:22;
|
||||
} sethi;
|
||||
struct
|
||||
{
|
||||
unsigned int op:2;
|
||||
unsigned int rd:5;
|
||||
unsigned int op3:6;
|
||||
unsigned int rs1:5;
|
||||
unsigned int i:1;
|
||||
unsigned int simm13:13;
|
||||
} add;
|
||||
int i;
|
||||
};
|
||||
|
||||
/* From infrun.c */
|
||||
extern int stop_after_trap;
|
||||
|
||||
|
@ -129,16 +153,78 @@ single_step (ignore)
|
|||
}
|
||||
}
|
||||
|
||||
/* Call this for each newly created frame. For SPARC, we need to calculate
|
||||
the bottom of the frame, and do some extra work if the prologue
|
||||
has been generated via the -mflat option to GCC. In particular,
|
||||
we need to know where the previous fp and the pc have been stashed,
|
||||
since their exact position within the frame may vary. */
|
||||
|
||||
void
|
||||
sparc_init_extra_frame_info (fromleaf, fi)
|
||||
int fromleaf;
|
||||
struct frame_info *fi;
|
||||
{
|
||||
char *name;
|
||||
CORE_ADDR addr;
|
||||
union sparc_insn_layout x;
|
||||
|
||||
fi->bottom =
|
||||
(fi->next ?
|
||||
(fi->frame == fi->next->frame ? fi->next->bottom : fi->next->frame) :
|
||||
read_register (SP_REGNUM));
|
||||
|
||||
/* Decide whether this is a function with a ``flat register window''
|
||||
frame. For such functions, the frame pointer is actually in %i7. */
|
||||
fi->flat = 0;
|
||||
if (find_pc_partial_function (fi->pc, &name, &addr, NULL))
|
||||
{
|
||||
/* See if the function starts with an add (which will be of a
|
||||
negative number if a flat frame) to the sp. */
|
||||
x.i = read_memory_integer (addr, 4);
|
||||
if (x.add.op == 2 && x.add.rd == 14 && x.add.op3 == 0)
|
||||
{
|
||||
/* Then look for a save of %i7 into the frame. */
|
||||
x.i = read_memory_integer (addr + 4, 4);
|
||||
if (x.add.op == 3
|
||||
&& x.add.rd == 31
|
||||
&& x.add.op3 == 4
|
||||
&& x.add.rs1 == 14)
|
||||
{
|
||||
/* We definitely have a flat frame now. */
|
||||
fi->flat = 1;
|
||||
/* Overwrite the frame's address with the value in %i7. */
|
||||
fi->frame =
|
||||
(fi->next ?
|
||||
(fi->frame == fi->next->frame ? fi->bottom : fi->frame) :
|
||||
read_register (I7_REGNUM));
|
||||
/* Record where the fp got saved. */
|
||||
fi->fp_addr = fi->bottom + x.add.simm13;
|
||||
/* Also try to collect where the pc got saved to. */
|
||||
fi->pc_addr = 0;
|
||||
x.i = read_memory_integer (addr + 12, 4);
|
||||
if (x.add.op == 3
|
||||
&& x.add.rd == 15
|
||||
&& x.add.op3 == 4
|
||||
&& x.add.rs1 == 14)
|
||||
fi->pc_addr = fi->bottom + x.add.simm13;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CORE_ADDR
|
||||
sparc_frame_chain (thisframe)
|
||||
FRAME thisframe;
|
||||
sparc_frame_chain (frame)
|
||||
struct frame_info *frame;
|
||||
{
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
int err;
|
||||
CORE_ADDR addr;
|
||||
|
||||
addr = thisframe->frame + FRAME_SAVED_I0 +
|
||||
REGISTER_RAW_SIZE (FP_REGNUM) * (FP_REGNUM - I0_REGNUM);
|
||||
if (frame->flat)
|
||||
addr = frame->fp_addr;
|
||||
else
|
||||
addr = frame->frame + FRAME_SAVED_I0 +
|
||||
REGISTER_RAW_SIZE (FP_REGNUM) * (FP_REGNUM - I0_REGNUM);
|
||||
err = target_read_memory (addr, buf, REGISTER_RAW_SIZE (FP_REGNUM));
|
||||
if (err)
|
||||
return 0;
|
||||
|
@ -157,7 +243,7 @@ sparc_extract_struct_value_address (regbuf)
|
|||
|
||||
CORE_ADDR
|
||||
sparc_frame_saved_pc (frame)
|
||||
FRAME frame;
|
||||
struct frame_info *frame;
|
||||
{
|
||||
char buf[MAX_REGISTER_RAW_SIZE];
|
||||
CORE_ADDR addr;
|
||||
|
@ -194,39 +280,41 @@ sparc_frame_saved_pc (frame)
|
|||
scbuf, sizeof (scbuf));
|
||||
return extract_address (scbuf, sizeof (scbuf));
|
||||
}
|
||||
addr = (frame->bottom + FRAME_SAVED_I0 +
|
||||
REGISTER_RAW_SIZE (I7_REGNUM) * (I7_REGNUM - I0_REGNUM));
|
||||
if (frame->flat)
|
||||
addr = frame->pc_addr;
|
||||
else
|
||||
addr = frame->bottom + FRAME_SAVED_I0 +
|
||||
REGISTER_RAW_SIZE (I7_REGNUM) * (I7_REGNUM - I0_REGNUM);
|
||||
read_memory (addr, buf, REGISTER_RAW_SIZE (I7_REGNUM));
|
||||
return PC_ADJUST (extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Since an individual frame in the frame cache is defined by two
|
||||
* arguments (a frame pointer and a stack pointer), we need two
|
||||
* arguments to get info for an arbitrary stack frame. This routine
|
||||
* takes two arguments and makes the cached frames look as if these
|
||||
* two arguments defined a frame on the cache. This allows the rest
|
||||
* of info frame to extract the important arguments without
|
||||
* difficulty.
|
||||
*/
|
||||
FRAME
|
||||
/* Since an individual frame in the frame cache is defined by two
|
||||
arguments (a frame pointer and a stack pointer), we need two
|
||||
arguments to get info for an arbitrary stack frame. This routine
|
||||
takes two arguments and makes the cached frames look as if these
|
||||
two arguments defined a frame on the cache. This allows the rest
|
||||
of info frame to extract the important arguments without
|
||||
difficulty. */
|
||||
|
||||
struct frame_info *
|
||||
setup_arbitrary_frame (argc, argv)
|
||||
int argc;
|
||||
FRAME_ADDR *argv;
|
||||
CORE_ADDR *argv;
|
||||
{
|
||||
FRAME fid;
|
||||
struct frame_info *frame;
|
||||
|
||||
if (argc != 2)
|
||||
error ("Sparc frame specifications require two arguments: fp and sp");
|
||||
|
||||
fid = create_new_frame (argv[0], 0);
|
||||
frame = create_new_frame (argv[0], 0);
|
||||
|
||||
if (!fid)
|
||||
fatal ("internal: create_new_frame returned invalid frame id");
|
||||
if (!frame)
|
||||
fatal ("internal: create_new_frame returned invalid frame");
|
||||
|
||||
fid->bottom = argv[1];
|
||||
fid->pc = FRAME_SAVED_PC (fid);
|
||||
return fid;
|
||||
frame->bottom = argv[1];
|
||||
frame->pc = FRAME_SAVED_PC (frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
/* Given a pc value, skip it forward past the function prologue by
|
||||
|
@ -237,34 +325,16 @@ setup_arbitrary_frame (argc, argv)
|
|||
|
||||
This routine should be more specific in its actions; making sure
|
||||
that it uses the same register in the initial prologue section. */
|
||||
|
||||
CORE_ADDR
|
||||
skip_prologue (start_pc, frameless_p)
|
||||
CORE_ADDR start_pc;
|
||||
int frameless_p;
|
||||
{
|
||||
union
|
||||
{
|
||||
unsigned long int code;
|
||||
struct
|
||||
{
|
||||
unsigned int op:2;
|
||||
unsigned int rd:5;
|
||||
unsigned int op2:3;
|
||||
unsigned int imm22:22;
|
||||
} sethi;
|
||||
struct
|
||||
{
|
||||
unsigned int op:2;
|
||||
unsigned int rd:5;
|
||||
unsigned int op3:6;
|
||||
unsigned int rs1:5;
|
||||
unsigned int i:1;
|
||||
unsigned int simm13:13;
|
||||
} add;
|
||||
int i;
|
||||
} x;
|
||||
union sparc_insn_layout x;
|
||||
int dest = -1;
|
||||
CORE_ADDR pc = start_pc;
|
||||
int is_flat = 0;
|
||||
|
||||
x.i = read_memory_integer (pc, 4);
|
||||
|
||||
|
@ -298,33 +368,50 @@ skip_prologue (start_pc, frameless_p)
|
|||
return pc; /* return before doing more work */
|
||||
x.i = read_memory_integer (pc, 4);
|
||||
}
|
||||
else
|
||||
else if (x.add.op == 2 && x.add.rd == 14 && x.add.op3 == 0)
|
||||
{
|
||||
/* Without a save instruction, it's not a prologue. */
|
||||
return start_pc;
|
||||
pc += 4;
|
||||
if (frameless_p) /* If the add is all we care about, */
|
||||
return pc; /* return before doing more work */
|
||||
/* FIXME test that the following instructions are the right ones
|
||||
for a flat frame */
|
||||
x.i = read_memory_integer (pc, 4);
|
||||
pc += 4;
|
||||
x.i = read_memory_integer (pc, 4);
|
||||
pc += 4;
|
||||
x.i = read_memory_integer (pc, 4);
|
||||
}
|
||||
else
|
||||
/* Without a save or add instruction, it's not a prologue. */
|
||||
return start_pc;
|
||||
|
||||
/* Now we need to recognize stores into the frame from the input
|
||||
registers. This recognizes all non alternate stores of input
|
||||
register, into a location offset from the frame pointer. */
|
||||
while (x.add.op == 3
|
||||
&& (x.add.op3 & 0x3c) == 4 /* Store, non-alternate. */
|
||||
&& (x.add.rd & 0x18) == 0x18 /* Input register. */
|
||||
&& x.add.i /* Immediate mode. */
|
||||
&& x.add.rs1 == 30 /* Off of frame pointer. */
|
||||
/* Into reserved stack space. */
|
||||
&& x.add.simm13 >= 0x44
|
||||
&& x.add.simm13 < 0x5b)
|
||||
while ((x.add.op == 3
|
||||
&& (x.add.op3 & 0x3c) == 4 /* Store, non-alternate. */
|
||||
&& (x.add.rd & 0x18) == 0x18 /* Input register. */
|
||||
&& x.add.i /* Immediate mode. */
|
||||
&& x.add.rs1 == 30 /* Off of frame pointer. */
|
||||
/* Into reserved stack space. */
|
||||
&& x.add.simm13 >= 0x44
|
||||
&& x.add.simm13 < 0x5b)
|
||||
|| (is_flat
|
||||
&& x.add.op == 3
|
||||
&& x.add.op3 == 4
|
||||
&& x.add.rs1 == 14
|
||||
))
|
||||
{
|
||||
pc += 4;
|
||||
x.i = read_memory_integer (pc, 4);
|
||||
}
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
||||
/* Check instruction at ADDR to see if it is an annulled branch.
|
||||
All other instructions will go to NPC or will trap.
|
||||
Set *TARGET if we find a canidate branch; set to zero if not. */
|
||||
Set *TARGET if we find a candidate branch; set to zero if not. */
|
||||
|
||||
branch_type
|
||||
isannulled (instruction, addr, target)
|
||||
|
@ -395,10 +482,9 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
|
|||
struct frame_saved_regs *saved_regs_addr;
|
||||
{
|
||||
register int regnum;
|
||||
FRAME_ADDR frame = FRAME_FP(fi);
|
||||
FRAME fid = FRAME_INFO_ID (fi);
|
||||
CORE_ADDR frame_addr = FRAME_FP (fi);
|
||||
|
||||
if (!fid)
|
||||
if (!fi)
|
||||
fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS");
|
||||
|
||||
memset (saved_regs_addr, 0, sizeof (*saved_regs_addr));
|
||||
|
@ -410,38 +496,59 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
|
|||
/* Dummy frame. All but the window regs are in there somewhere. */
|
||||
for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++)
|
||||
saved_regs_addr->regs[regnum] =
|
||||
frame + (regnum - G0_REGNUM) * 4 - 0xa0;
|
||||
frame_addr + (regnum - G0_REGNUM) * 4 - 0xa0;
|
||||
for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
|
||||
saved_regs_addr->regs[regnum] =
|
||||
frame + (regnum - I0_REGNUM) * 4 - 0xc0;
|
||||
frame_addr + (regnum - I0_REGNUM) * 4 - 0xc0;
|
||||
for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++)
|
||||
saved_regs_addr->regs[regnum] =
|
||||
frame + (regnum - FP0_REGNUM) * 4 - 0x80;
|
||||
frame_addr + (regnum - FP0_REGNUM) * 4 - 0x80;
|
||||
for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
|
||||
saved_regs_addr->regs[regnum] =
|
||||
frame + (regnum - Y_REGNUM) * 4 - 0xe0;
|
||||
frame = fi->bottom ?
|
||||
frame_addr + (regnum - Y_REGNUM) * 4 - 0xe0;
|
||||
frame_addr = fi->bottom ?
|
||||
fi->bottom : read_register (SP_REGNUM);
|
||||
}
|
||||
else if (fi->flat)
|
||||
{
|
||||
/* Flat register window frame. */
|
||||
saved_regs_addr->regs[RP_REGNUM] = fi->pc_addr;
|
||||
saved_regs_addr->regs[I7_REGNUM] = fi->fp_addr;
|
||||
frame_addr = fi->bottom ? fi->bottom : read_register (SP_REGNUM);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normal frame. Just Local and In registers */
|
||||
frame = fi->bottom ?
|
||||
frame_addr = fi->bottom ?
|
||||
fi->bottom : read_register (SP_REGNUM);
|
||||
for (regnum = L0_REGNUM; regnum < L0_REGNUM+16; regnum++)
|
||||
for (regnum = L0_REGNUM; regnum < L0_REGNUM+8; regnum++)
|
||||
saved_regs_addr->regs[regnum] =
|
||||
frame + (regnum - L0_REGNUM) * REGISTER_RAW_SIZE (L0_REGNUM);
|
||||
(frame_addr + (regnum - L0_REGNUM) * REGISTER_RAW_SIZE (L0_REGNUM)
|
||||
+ FRAME_SAVED_L0);
|
||||
for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
|
||||
saved_regs_addr->regs[regnum] =
|
||||
(frame_addr + (regnum - I0_REGNUM) * REGISTER_RAW_SIZE (I0_REGNUM)
|
||||
+ FRAME_SAVED_I0);
|
||||
}
|
||||
if (fi->next)
|
||||
{
|
||||
/* Pull off either the next frame pointer or the stack pointer */
|
||||
FRAME_ADDR next_next_frame =
|
||||
(fi->next->bottom ?
|
||||
fi->next->bottom :
|
||||
read_register (SP_REGNUM));
|
||||
for (regnum = O0_REGNUM; regnum < O0_REGNUM+8; regnum++)
|
||||
saved_regs_addr->regs[regnum] =
|
||||
next_next_frame + regnum * REGISTER_RAW_SIZE (O0_REGNUM);
|
||||
if (fi->flat)
|
||||
{
|
||||
saved_regs_addr->regs[O7_REGNUM] = fi->pc_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Pull off either the next frame pointer or the stack pointer */
|
||||
CORE_ADDR next_next_frame_addr =
|
||||
(fi->next->bottom ?
|
||||
fi->next->bottom :
|
||||
read_register (SP_REGNUM));
|
||||
for (regnum = O0_REGNUM; regnum < O0_REGNUM+8; regnum++)
|
||||
saved_regs_addr->regs[regnum] =
|
||||
(next_next_frame_addr
|
||||
+ (regnum - O0_REGNUM) * REGISTER_RAW_SIZE (O0_REGNUM)
|
||||
+ FRAME_SAVED_I0);
|
||||
}
|
||||
}
|
||||
/* Otherwise, whatever we would get from ptrace(GETREGS) is accurate */
|
||||
saved_regs_addr->regs[SP_REGNUM] = FRAME_FP (fi);
|
||||
|
@ -505,14 +612,13 @@ sparc_push_dummy_frame ()
|
|||
void
|
||||
sparc_pop_frame ()
|
||||
{
|
||||
register FRAME frame = get_current_frame ();
|
||||
register struct frame_info *frame = get_current_frame ();
|
||||
register CORE_ADDR pc;
|
||||
struct frame_saved_regs fsr;
|
||||
struct frame_info *fi;
|
||||
char raw_buffer[REGISTER_BYTES];
|
||||
int regnum;
|
||||
|
||||
fi = get_frame_info (frame);
|
||||
get_frame_saved_regs (fi, &fsr);
|
||||
get_frame_saved_regs (frame, &fsr);
|
||||
if (fsr.regs[FP0_REGNUM])
|
||||
{
|
||||
read_memory (fsr.regs[FP0_REGNUM], raw_buffer, 32 * 4);
|
||||
|
@ -533,7 +639,22 @@ sparc_pop_frame ()
|
|||
read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * 4);
|
||||
write_register_bytes (REGISTER_BYTE (G1_REGNUM), raw_buffer, 7 * 4);
|
||||
}
|
||||
if (fsr.regs[I0_REGNUM])
|
||||
|
||||
if (frame->flat)
|
||||
{
|
||||
/* Each register might or might not have been saved, need to test
|
||||
individually. */
|
||||
for (regnum = L0_REGNUM; regnum < L0_REGNUM + 8; ++regnum)
|
||||
if (fsr.regs[regnum])
|
||||
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
|
||||
for (regnum = I0_REGNUM; regnum < I0_REGNUM + 8; ++regnum)
|
||||
if (fsr.regs[regnum])
|
||||
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
|
||||
for (regnum = O0_REGNUM; regnum < O0_REGNUM + 8; ++regnum)
|
||||
if (fsr.regs[regnum])
|
||||
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
|
||||
}
|
||||
else if (fsr.regs[I0_REGNUM])
|
||||
{
|
||||
CORE_ADDR sp;
|
||||
|
||||
|
@ -569,6 +690,12 @@ sparc_pop_frame ()
|
|||
write_register (NPC_REGNUM,
|
||||
read_memory_integer (fsr.regs[NPC_REGNUM], 4));
|
||||
}
|
||||
else if (frame->flat && frame->pc_addr)
|
||||
{
|
||||
pc = PC_ADJUST ((CORE_ADDR) read_memory_integer (frame->pc_addr, 4));
|
||||
write_register (PC_REGNUM, pc);
|
||||
write_register (NPC_REGNUM, pc + 4);
|
||||
}
|
||||
else if (fsr.regs[I7_REGNUM])
|
||||
{
|
||||
/* Return address in %i7 -- adjust it, then restore PC and NPC from it */
|
||||
|
@ -598,6 +725,48 @@ sparc_pc_adjust(pc)
|
|||
else
|
||||
return pc+8;
|
||||
}
|
||||
|
||||
/* If pc is in a shared library trampoline, return its target.
|
||||
The SunOs 4.x linker rewrites the jump table entries for PIC
|
||||
compiled modules in the main executable to bypass the dynamic linker
|
||||
with jumps of the form
|
||||
sethi %hi(addr),%g1
|
||||
jmp %g1+%lo(addr)
|
||||
and removes the corresponding jump table relocation entry in the
|
||||
dynamic relocations.
|
||||
find_solib_trampoline_target relies on the presence of the jump
|
||||
table relocation entry, so we have to detect these jump instructions
|
||||
by hand. */
|
||||
|
||||
CORE_ADDR
|
||||
sunos4_skip_trampoline_code (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
unsigned long insn1;
|
||||
char buf[4];
|
||||
int err;
|
||||
|
||||
err = target_read_memory (pc, buf, 4);
|
||||
insn1 = extract_unsigned_integer (buf, 4);
|
||||
if (err == 0 && (insn1 & 0xffc00000) == 0x03000000)
|
||||
{
|
||||
unsigned long insn2;
|
||||
|
||||
err = target_read_memory (pc + 4, buf, 4);
|
||||
insn2 = extract_unsigned_integer (buf, 4);
|
||||
if (err == 0 && (insn2 & 0xffffe000) == 0x81c06000)
|
||||
{
|
||||
CORE_ADDR target_pc = (insn1 & 0x3fffff) << 10;
|
||||
int delta = insn2 & 0x1fff;
|
||||
|
||||
/* Sign extend the displacement. */
|
||||
if (delta & 0x1000)
|
||||
delta |= ~0x1fff;
|
||||
return target_pc + delta;
|
||||
}
|
||||
}
|
||||
return find_solib_trampoline_target (pc);
|
||||
}
|
||||
|
||||
#ifdef USE_PROC_FS /* Target dependent support for /proc */
|
||||
|
||||
|
@ -637,7 +806,6 @@ sparc_pc_adjust(pc)
|
|||
|
||||
*/
|
||||
|
||||
|
||||
/* Given a pointer to a general register set in /proc format (gregset_t *),
|
||||
unpack the register contents and supply them as gdb's idea of the current
|
||||
register values. */
|
||||
|
@ -761,17 +929,17 @@ int regno;
|
|||
This routine returns true on success */
|
||||
|
||||
int
|
||||
get_longjmp_target(pc)
|
||||
get_longjmp_target (pc)
|
||||
CORE_ADDR *pc;
|
||||
{
|
||||
CORE_ADDR jb_addr;
|
||||
#define LONGJMP_TARGET_SIZE 4
|
||||
char buf[LONGJMP_TARGET_SIZE];
|
||||
|
||||
jb_addr = read_register(O0_REGNUM);
|
||||
jb_addr = read_register (O0_REGNUM);
|
||||
|
||||
if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
|
||||
LONGJMP_TARGET_SIZE))
|
||||
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
|
||||
LONGJMP_TARGET_SIZE))
|
||||
return 0;
|
||||
|
||||
*pc = extract_address (buf, LONGJMP_TARGET_SIZE);
|
||||
|
|
Loading…
Reference in New Issue