* 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:
Peter Schauer 1994-12-17 10:46:32 +00:00
parent 091f3a62a8
commit 84bdfea6aa
6 changed files with 301 additions and 92 deletions

View file

@ -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> Thu Dec 15 16:55:35 1994 Stan Shebs <shebs@andros.cygnus.com>
* defs.h: Include progress.h. * defs.h: Include progress.h.

View file

@ -1,5 +1,6 @@
/* Support for printing C and C++ types for GDB, the GNU debugger. /* 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. 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) else if (!is_constructor && !is_full_physname_constructor)
{ {
type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
"", stream, 0); "", stream, -1);
fputs_filtered (" ", stream); fputs_filtered (" ", stream);
} }
if (TYPE_FN_FIELD_STUB (f, j)) if (TYPE_FN_FIELD_STUB (f, j))

View file

@ -39,3 +39,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Use the alternate method of determining valid frame chains. */ /* Use the alternate method of determining valid frame chains. */
#define FRAME_CHAIN_VALID_ALTERNATE #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)

View file

@ -1,5 +1,5 @@
/* Macro definitions for GDB for a Sun 4 running sunos 4. /* 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. 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 "sparc/tm-sparc.h"
#include "tm-sunos.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 /* Offsets into jmp_buf. Not defined by Sun, but at least documented in a
comment in <machine/setjmp.h>! */ comment in <machine/setjmp.h>! */

View file

@ -192,6 +192,11 @@ typedef unsigned int DIE_REF; /* Reference to a DIE */
#define CHILL_PRODUCER "GNU Chill " #define CHILL_PRODUCER "GNU Chill "
#endif #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 /* 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 expected to be signed. Used, for example, when fetching a signed
integer in the target environment which is used as a signed integer integer in the target environment which is used as a signed integer
@ -2210,8 +2215,10 @@ locval (loc)
break; break;
case OP_REG: case OP_REG:
/* push register (number) */ /* push register (number) */
stack[++stacki] = target_to_host (loc, loc_value_size, stack[++stacki]
GET_UNSIGNED, current_objfile); = DWARF_REG_TO_REGNUM (target_to_host (loc, loc_value_size,
GET_UNSIGNED,
current_objfile));
loc += loc_value_size; loc += loc_value_size;
isreg = 1; isreg = 1;
break; break;

View file

@ -31,6 +31,30 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "gdbcore.h" #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 */ /* From infrun.c */
extern int stop_after_trap; 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 CORE_ADDR
sparc_frame_chain (thisframe) sparc_frame_chain (frame)
FRAME thisframe; struct frame_info *frame;
{ {
char buf[MAX_REGISTER_RAW_SIZE]; char buf[MAX_REGISTER_RAW_SIZE];
int err; int err;
CORE_ADDR addr; CORE_ADDR addr;
addr = thisframe->frame + FRAME_SAVED_I0 + if (frame->flat)
REGISTER_RAW_SIZE (FP_REGNUM) * (FP_REGNUM - I0_REGNUM); 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)); err = target_read_memory (addr, buf, REGISTER_RAW_SIZE (FP_REGNUM));
if (err) if (err)
return 0; return 0;
@ -157,7 +243,7 @@ sparc_extract_struct_value_address (regbuf)
CORE_ADDR CORE_ADDR
sparc_frame_saved_pc (frame) sparc_frame_saved_pc (frame)
FRAME frame; struct frame_info *frame;
{ {
char buf[MAX_REGISTER_RAW_SIZE]; char buf[MAX_REGISTER_RAW_SIZE];
CORE_ADDR addr; CORE_ADDR addr;
@ -194,39 +280,41 @@ sparc_frame_saved_pc (frame)
scbuf, sizeof (scbuf)); scbuf, sizeof (scbuf));
return extract_address (scbuf, sizeof (scbuf)); return extract_address (scbuf, sizeof (scbuf));
} }
addr = (frame->bottom + FRAME_SAVED_I0 + if (frame->flat)
REGISTER_RAW_SIZE (I7_REGNUM) * (I7_REGNUM - I0_REGNUM)); 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)); read_memory (addr, buf, REGISTER_RAW_SIZE (I7_REGNUM));
return PC_ADJUST (extract_address (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
* Since an individual frame in the frame cache is defined by two arguments (a frame pointer and a stack pointer), we need two
* arguments (a frame pointer and a stack pointer), we need two arguments to get info for an arbitrary stack frame. This routine
* arguments to get info for an arbitrary stack frame. This routine takes two arguments and makes the cached frames look as if these
* takes two arguments and makes the cached frames look as if these two arguments defined a frame on the cache. This allows the rest
* two arguments defined a frame on the cache. This allows the rest of info frame to extract the important arguments without
* of info frame to extract the important arguments without difficulty. */
* difficulty.
*/ struct frame_info *
FRAME
setup_arbitrary_frame (argc, argv) setup_arbitrary_frame (argc, argv)
int argc; int argc;
FRAME_ADDR *argv; CORE_ADDR *argv;
{ {
FRAME fid; struct frame_info *frame;
if (argc != 2) if (argc != 2)
error ("Sparc frame specifications require two arguments: fp and sp"); 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) if (!frame)
fatal ("internal: create_new_frame returned invalid frame id"); fatal ("internal: create_new_frame returned invalid frame");
fid->bottom = argv[1]; frame->bottom = argv[1];
fid->pc = FRAME_SAVED_PC (fid); frame->pc = FRAME_SAVED_PC (frame);
return fid; return frame;
} }
/* Given a pc value, skip it forward past the function prologue by /* 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 This routine should be more specific in its actions; making sure
that it uses the same register in the initial prologue section. */ that it uses the same register in the initial prologue section. */
CORE_ADDR CORE_ADDR
skip_prologue (start_pc, frameless_p) skip_prologue (start_pc, frameless_p)
CORE_ADDR start_pc; CORE_ADDR start_pc;
int frameless_p; int frameless_p;
{ {
union union sparc_insn_layout x;
{
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;
int dest = -1; int dest = -1;
CORE_ADDR pc = start_pc; CORE_ADDR pc = start_pc;
int is_flat = 0;
x.i = read_memory_integer (pc, 4); x.i = read_memory_integer (pc, 4);
@ -298,33 +368,50 @@ skip_prologue (start_pc, frameless_p)
return pc; /* return before doing more work */ return pc; /* return before doing more work */
x.i = read_memory_integer (pc, 4); 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. */ pc += 4;
return start_pc; 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 /* Now we need to recognize stores into the frame from the input
registers. This recognizes all non alternate stores of input registers. This recognizes all non alternate stores of input
register, into a location offset from the frame pointer. */ register, into a location offset from the frame pointer. */
while (x.add.op == 3 while ((x.add.op == 3
&& (x.add.op3 & 0x3c) == 4 /* Store, non-alternate. */ && (x.add.op3 & 0x3c) == 4 /* Store, non-alternate. */
&& (x.add.rd & 0x18) == 0x18 /* Input register. */ && (x.add.rd & 0x18) == 0x18 /* Input register. */
&& x.add.i /* Immediate mode. */ && x.add.i /* Immediate mode. */
&& x.add.rs1 == 30 /* Off of frame pointer. */ && x.add.rs1 == 30 /* Off of frame pointer. */
/* Into reserved stack space. */ /* Into reserved stack space. */
&& x.add.simm13 >= 0x44 && x.add.simm13 >= 0x44
&& x.add.simm13 < 0x5b) && x.add.simm13 < 0x5b)
|| (is_flat
&& x.add.op == 3
&& x.add.op3 == 4
&& x.add.rs1 == 14
))
{ {
pc += 4; pc += 4;
x.i = read_memory_integer (pc, 4); x.i = read_memory_integer (pc, 4);
} }
return pc; return pc;
} }
/* Check instruction at ADDR to see if it is an annulled branch. /* Check instruction at ADDR to see if it is an annulled branch.
All other instructions will go to NPC or will trap. 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 branch_type
isannulled (instruction, addr, target) isannulled (instruction, addr, target)
@ -395,10 +482,9 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr)
struct frame_saved_regs *saved_regs_addr; struct frame_saved_regs *saved_regs_addr;
{ {
register int regnum; register int regnum;
FRAME_ADDR frame = FRAME_FP(fi); CORE_ADDR frame_addr = FRAME_FP (fi);
FRAME fid = FRAME_INFO_ID (fi);
if (!fid) if (!fi)
fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS"); fatal ("Bad frame info struct in FRAME_FIND_SAVED_REGS");
memset (saved_regs_addr, 0, sizeof (*saved_regs_addr)); 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. */ /* Dummy frame. All but the window regs are in there somewhere. */
for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++) for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++)
saved_regs_addr->regs[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++) for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
saved_regs_addr->regs[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++) for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++)
saved_regs_addr->regs[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++) for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
saved_regs_addr->regs[regnum] = saved_regs_addr->regs[regnum] =
frame + (regnum - Y_REGNUM) * 4 - 0xe0; frame_addr + (regnum - Y_REGNUM) * 4 - 0xe0;
frame = fi->bottom ? frame_addr = fi->bottom ?
fi->bottom : read_register (SP_REGNUM); 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 else
{ {
/* Normal frame. Just Local and In registers */ /* Normal frame. Just Local and In registers */
frame = fi->bottom ? frame_addr = fi->bottom ?
fi->bottom : read_register (SP_REGNUM); 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] = 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) if (fi->next)
{ {
/* Pull off either the next frame pointer or the stack pointer */ if (fi->flat)
FRAME_ADDR next_next_frame = {
(fi->next->bottom ? saved_regs_addr->regs[O7_REGNUM] = fi->pc_addr;
fi->next->bottom : }
read_register (SP_REGNUM)); else
for (regnum = O0_REGNUM; regnum < O0_REGNUM+8; regnum++) {
saved_regs_addr->regs[regnum] = /* Pull off either the next frame pointer or the stack pointer */
next_next_frame + regnum * REGISTER_RAW_SIZE (O0_REGNUM); 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 */ /* Otherwise, whatever we would get from ptrace(GETREGS) is accurate */
saved_regs_addr->regs[SP_REGNUM] = FRAME_FP (fi); saved_regs_addr->regs[SP_REGNUM] = FRAME_FP (fi);
@ -505,14 +612,13 @@ sparc_push_dummy_frame ()
void void
sparc_pop_frame () sparc_pop_frame ()
{ {
register FRAME frame = get_current_frame (); register struct frame_info *frame = get_current_frame ();
register CORE_ADDR pc; register CORE_ADDR pc;
struct frame_saved_regs fsr; struct frame_saved_regs fsr;
struct frame_info *fi;
char raw_buffer[REGISTER_BYTES]; char raw_buffer[REGISTER_BYTES];
int regnum;
fi = get_frame_info (frame); get_frame_saved_regs (frame, &fsr);
get_frame_saved_regs (fi, &fsr);
if (fsr.regs[FP0_REGNUM]) if (fsr.regs[FP0_REGNUM])
{ {
read_memory (fsr.regs[FP0_REGNUM], raw_buffer, 32 * 4); 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); read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * 4);
write_register_bytes (REGISTER_BYTE (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; CORE_ADDR sp;
@ -569,6 +690,12 @@ sparc_pop_frame ()
write_register (NPC_REGNUM, write_register (NPC_REGNUM,
read_memory_integer (fsr.regs[NPC_REGNUM], 4)); 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]) else if (fsr.regs[I7_REGNUM])
{ {
/* Return address in %i7 -- adjust it, then restore PC and NPC from it */ /* Return address in %i7 -- adjust it, then restore PC and NPC from it */
@ -598,6 +725,48 @@ sparc_pc_adjust(pc)
else else
return pc+8; 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 */ #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 *), /* 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 unpack the register contents and supply them as gdb's idea of the current
register values. */ register values. */
@ -761,17 +929,17 @@ int regno;
This routine returns true on success */ This routine returns true on success */
int int
get_longjmp_target(pc) get_longjmp_target (pc)
CORE_ADDR *pc; CORE_ADDR *pc;
{ {
CORE_ADDR jb_addr; CORE_ADDR jb_addr;
#define LONGJMP_TARGET_SIZE 4 #define LONGJMP_TARGET_SIZE 4
char buf[LONGJMP_TARGET_SIZE]; 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, if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
LONGJMP_TARGET_SIZE)) LONGJMP_TARGET_SIZE))
return 0; return 0;
*pc = extract_address (buf, LONGJMP_TARGET_SIZE); *pc = extract_address (buf, LONGJMP_TARGET_SIZE);