* hppa-pinsn.c (print_insn): Improve handling of be and ble

branch targets to compute target address using const from previous
	instruction if necessary.
	* Add `Q' operator to print out bit position field various
	instructions.
	* hppah-nat.c:  #include sys/param.h, and sys/user.h.  General
	cleanups, use new code from Utah.
	* (store_inferior_registers):  Update to new code from Utah.
	* (initialize_kernel_u_addr):  Re-enable decl of struct user u.
	* (fetch_register):  Clear out priv level when reading PCs.
	* hppah-tdep.c:  Get rid of gobs of KERNELDEBUG stuff.
	* Remove decl of errno, #include wait.h and target.h.
	* (frame_saved_pc):  Check `flags' pseudo-register to see if we
	were inside of a kernel call.  If so, then PC is in a different
	register.  Also, mask out bottom two bits of all PCs so as not to
	confuse higher level code.
	* (push_dummy_frame):  Create from #define in tm-hppa.h.
	* (find_dummy_frame_regs):  Update from Utah.
	* (hp_pop_frame):  Create from #define in tm-hppa.h.
	* (hp_restore_pc_queue):  New, from Utah.
	* (hp_push_arguments):  Big fixes from Utah.
	* (pa_do_registers_info, pa_print_registers):  Only print out fp
	regs upon request.
	* (skip_trampoline_code):  New routine to deal with stubs that
	live in nowhereland between callers and callees.
	* i860-tdep.c:  Remove decl of attach_flag.
	* infrun.c (wait_for_inferior):  Add new macro
	INSTRUCTION_NULLIFIED, which can tell if the instruction pointed
	at by PC will be nullified.  If so, then step the target once more
	so as to avoid confusing the user.
	* (just before step_over_function:):  Use stop_func_start, not
	stop_pc when checking for the existance of line number info.
	stop_func_start will reflect the proper address of the target
	routine, not of the stub that we may be traversing to get there.
	* tm-hppa.h:  define SKIP_TRAMPOLINE_CODE and IN_SOLIB_TRAMPOLINE
	to deal with the stubs that PA compilers sometimes stick between
	callers and callees.  Also, define FLAGS_REGNUM for access to the
	`flags' pseudo-reg.
	* (REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW):  Use
	memcpy, not bcopy.
	* (CANNOT_STORE_REGISTER):  New from Utah.  Says that we can't
	write gr0, PC regs, and PSW!
	* (FRAME_FIND_SAVED_REGS):  Bug fixes from Utah.
	* (PUSH_DUMMY_FRAME, POP_FRAME):  Make into real routines in
	hppah-nat.c.
	* (CALL_DUMMY, FIX_CALL_DUMMY):  Fixes from Utah.
	* Define struct unwind_table_entry.
	* valops.c (call_function_by_hand):  Add another arg to
	FIX_CALL_DUMMY (under #ifdef GDB_TARGET_IS_HPPA).  Why is this
	necessary?
This commit is contained in:
Stu Grossman 1992-12-22 03:18:46 +00:00
parent d9a30dc6c5
commit 9f739abdac
8 changed files with 494 additions and 1123 deletions

View File

@ -1,3 +1,56 @@
Mon Dec 21 18:02:35 1992 Stu Grossman (grossman at cygnus.com)
* hppa-pinsn.c (print_insn): Improve handling of be and ble
branch targets to compute target address using const from previous
instruction if necessary.
* Add `Q' operator to print out bit position field various
instructions.
* hppah-nat.c: #include sys/param.h, and sys/user.h. General
cleanups, use new code from Utah.
* (store_inferior_registers): Update to new code from Utah.
* (initialize_kernel_u_addr): Re-enable decl of struct user u.
* (fetch_register): Clear out priv level when reading PCs.
* hppah-tdep.c: Get rid of gobs of KERNELDEBUG stuff.
* Remove decl of errno, #include wait.h and target.h.
* (frame_saved_pc): Check `flags' pseudo-register to see if we
were inside of a kernel call. If so, then PC is in a different
register. Also, mask out bottom two bits of all PCs so as not to
confuse higher level code.
* (push_dummy_frame): Create from #define in tm-hppa.h.
* (find_dummy_frame_regs): Update from Utah.
* (hp_pop_frame): Create from #define in tm-hppa.h.
* (hp_restore_pc_queue): New, from Utah.
* (hp_push_arguments): Big fixes from Utah.
* (pa_do_registers_info, pa_print_registers): Only print out fp
regs upon request.
* (skip_trampoline_code): New routine to deal with stubs that
live in nowhereland between callers and callees.
* i860-tdep.c: Remove decl of attach_flag.
* infrun.c (wait_for_inferior): Add new macro
INSTRUCTION_NULLIFIED, which can tell if the instruction pointed
at by PC will be nullified. If so, then step the target once more
so as to avoid confusing the user.
* (just before step_over_function:): Use stop_func_start, not
stop_pc when checking for the existance of line number info.
stop_func_start will reflect the proper address of the target
routine, not of the stub that we may be traversing to get there.
* tm-hppa.h: define SKIP_TRAMPOLINE_CODE and IN_SOLIB_TRAMPOLINE
to deal with the stubs that PA compilers sometimes stick between
callers and callees. Also, define FLAGS_REGNUM for access to the
`flags' pseudo-reg.
* (REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Use
memcpy, not bcopy.
* (CANNOT_STORE_REGISTER): New from Utah. Says that we can't
write gr0, PC regs, and PSW!
* (FRAME_FIND_SAVED_REGS): Bug fixes from Utah.
* (PUSH_DUMMY_FRAME, POP_FRAME): Make into real routines in
hppah-nat.c.
* (CALL_DUMMY, FIX_CALL_DUMMY): Fixes from Utah.
* Define struct unwind_table_entry.
* valops.c (call_function_by_hand): Add another arg to
FIX_CALL_DUMMY (under #ifdef GDB_TARGET_IS_HPPA). Why is this
necessary?
Mon Dec 21 02:17:57 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
* remote-vx.c: remove include of "symfile.h", replace it with "complaints.h"

View File

@ -233,13 +233,13 @@ print_insn (memaddr, stream)
print_address (memaddr + 8 + extract_12 (insn), stream);
break;
case 'W':
/* don't interpret an address if it's an external branch
instruction. */
op = GET_FIELD (insn, 0, 5);
if (op != 0x38 /* be */ && op != 0x39 /* ble */)
print_address (memaddr + 8 + extract_17 (insn), stream);
else
if (op == 0x38 /* be */ || op == 0x39 /* ble */)
fput_const (extract_17 (insn), stream);
else
print_address (memaddr + 8 + extract_17 (insn), stream);
break;
case 'B':
{
@ -257,6 +257,10 @@ print_insn (memaddr, stream)
fprintf_filtered (stream, "%d",
GET_FIELD (insn, 22, 26));
break;
case 'Q':
fprintf_filtered (stream, "%d",
GET_FIELD (insn, 11, 15));
break;
case 'T':
fprintf_filtered (stream, "%d",
32 - GET_FIELD (insn, 27, 31));
@ -340,6 +344,34 @@ print_insn (memaddr, stream)
break;
}
}
/* If this is an external branch, examine the previous instruction and see if
it was an ldil that loaded something into the same base reg. If so, then
calculate the branch target from the constants in both instructions, and
print it out. */
op = GET_FIELD (insn, 0, 5);
if (op == 0x38 /* be */ || op == 0x39 /* ble */)
{
CORE_ADDR target_address;
unsigned int prev_insn;
int basereg, basereg_prev;
target_address = extract_17 (insn);
basereg = GET_FIELD (insn, 6, 10);
if (basereg != 0)
{
read_memory (memaddr - 4, &prev_insn, sizeof(prev_insn));
basereg_prev = GET_FIELD (prev_insn, 6, 10);
if ((prev_insn & 0xfc000000) == 0x20000000 /* ldil */
&& basereg == basereg_prev)
target_address += extract_21 (prev_insn);
}
fprintf_filtered (stream, "\t! ");
print_address (target_address, stream);
}
return sizeof(insn);
}
}

View File

@ -27,6 +27,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "inferior.h"
#include "target.h"
#include <sys/ptrace.h>
#include <sys/param.h>
#include <sys/user.h>
extern CORE_ADDR text_end;
static void fetch_register ();
@ -105,42 +109,70 @@ store_inferior_registers (regno)
char buf[80];
extern char registers[];
register int i;
unsigned int offset = U_REGS_OFFSET;
int scratch;
if (regno >= 0)
{
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
errno = 0;
ptrace (PT_WUAREA, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
*(int *) &registers[REGISTER_BYTE (regno) + i], 0);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
regaddr += sizeof(int);
}
errno = 0;
if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
{
scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
scratch, 0);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
}
else
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
errno = 0;
ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
*(int *) &registers[REGISTER_BYTE (regno) + i], 0);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
regaddr += sizeof(int);
}
}
else
{
for (regno = 0; regno < NUM_REGS; regno++)
{
if (CANNOT_STORE_REGISTER (regno))
continue;
regaddr = register_addr (regno, offset);
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
errno = 0;
ptrace (PT_WUAREA, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
*(int *) &registers[REGISTER_BYTE (regno) + i], 0);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
regaddr += sizeof(int);
}
errno = 0;
if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
{
scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
scratch, 0);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
}
else
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
{
errno = 0;
ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
*(int *) &registers[REGISTER_BYTE (regno) + i], 0);
if (errno != 0)
{
sprintf (buf, "writing register number %d(%d)", regno, i);
perror_with_name (buf);
}
regaddr += sizeof(int);
}
}
}
return;
@ -165,9 +197,7 @@ static struct hpnlist nl[] = {{ "_u", -1, }, { (char *) 0, }};
/* read the value of the u area from the hp-ux kernel */
void _initialize_kernel_u_addr ()
{
#if 0
struct user u;
#endif
nlist ("/hp-ux", &nl);
kernel_u_addr = nl[0].n_value;
}
@ -213,6 +243,8 @@ fetch_register (regno)
perror_with_name (mess);
}
}
if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
buf[3] &= ~0x3;
supply_register (regno, buf);
}
@ -280,14 +312,14 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
if (addr != memaddr || len < (int)sizeof (int)) {
/* Need part of initial word -- fetch it. */
buffer[0] = ptrace (PT_RIUSER, inferior_pid,
(PTRACE_ARG3_TYPE) addr, 0, 0);
buffer[0] = ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER,
inferior_pid, (PTRACE_ARG3_TYPE) addr, 0, 0);
}
if (count > 1) /* FIXME, avoid if even boundary */
{
buffer[count - 1]
= ptrace (PT_RIUSER, inferior_pid,
= ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER, inferior_pid,
(PTRACE_ARG3_TYPE) (addr + (count - 1) * sizeof (int)),
0, 0);
}
@ -300,24 +332,15 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
for (i = 0; i < count; i++, addr += sizeof (int))
{
#if 0
/* The HP-UX kernel crashes if you use PT_WDUSER to write into the text
segment. FIXME -- does it work to write into the data segment using
WIUSER, or do these idiots really expect us to figure out which segment
the address is in, so we can use a separate system call for it??! */
errno = 0;
ptrace (PT_WDUSER, inferior_pid, (PTRACE_ARG3_TYPE) addr,
ptrace (addr < text_end ? PT_WIUSER : PT_WDUSER, inferior_pid,
(PTRACE_ARG3_TYPE) addr,
buffer[i], 0);
if (errno)
#endif
{
/* Using the appropriate one (I or D) is necessary for
Gould NP1, at least. */
errno = 0;
ptrace (PT_WIUSER, inferior_pid, (PTRACE_ARG3_TYPE) addr,
buffer[i], 0);
}
if (errno)
return 0;
}
}
@ -327,8 +350,8 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
for (i = 0; i < count; i++, addr += sizeof (int))
{
errno = 0;
buffer[i] = ptrace (PT_RIUSER, inferior_pid,
(PTRACE_ARG3_TYPE) addr, 0, 0);
buffer[i] = ptrace (addr < text_end ? PT_RIUSER : PT_RDUSER,
inferior_pid, (PTRACE_ARG3_TYPE) addr, 0, 0);
if (errno)
return 0;
QUIT;
@ -339,4 +362,3 @@ child_xfer_memory (memaddr, myaddr, len, write, target)
}
return len;
}

File diff suppressed because it is too large Load Diff

View File

@ -76,7 +76,6 @@ int ansi_conformant;
#define BTDEBUG if (btdebug) btdebug_message
extern int errno;
extern int attach_flag;
extern char registers[];
CORE_ADDR get_saved_basereg();

View File

@ -186,6 +186,16 @@ hook_stop_stub PARAMS ((char *));
#define IN_SOLIB_TRAMPOLINE(pc,name) 0
#endif
/* On some systems, the PC may be left pointing at an instruction that won't
actually be executed. This is usually indicated by a bit in the PSW. If
we find ourselves in such a state, then we step the target beyond the
nullified instruction before returning control to the user so as to avoid
confusion. */
#ifndef INSTRUCTION_NULLIFIED
#define INSTRUCTION_NULLIFIED 0
#endif
#ifdef TDESC
#include "tdesc.h"
int safe_to_init_tdesc_context = 0;
@ -576,6 +586,15 @@ wait_for_inferior ()
single_step (0); /* This actually cleans up the ss */
#endif /* NO_SINGLE_STEP */
/* If PC is pointing at a nullified instruction, then step beyond it so that
the user won't be confused when GDB appears to be ready to execute it. */
if (INSTRUCTION_NULLIFIED)
{
resume (1, 0);
continue;
}
stop_pc = read_pc ();
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
read_pc ()));
@ -973,7 +992,7 @@ wait_for_inferior ()
if (tmp != 0)
stop_func_start = tmp;
symtab = find_pc_symtab (stop_pc);
symtab = find_pc_symtab (stop_func_start);
if (symtab && LINETABLE (symtab))
goto step_into_function;

View File

@ -1,4 +1,5 @@
/* Parameters for execution on a Hewlett-Packard PA-RISC machine.
/* Parameters for execution on a Hewlett-Packard PA-RISC machine, running
HPUX or BSD.
Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
Contributed by the Center for Software Science at the
@ -71,6 +72,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
else if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000) \
(pc) += 4;}
/* 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)
/* Return non-zero if we are in some sort of a trampoline. */
#define IN_SOLIB_TRAMPOLINE(pc,name) skip_trampoline_code (pc)
/* Immediately after a function call, return the saved pc.
Can't go through the frames for this because on some machines
the new frame is not set up until the new function executes
@ -150,6 +160,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
#define FLAGS_REGNUM 0 /* Various status flags */
#define RP_REGNUM 2 /* return pointer */
#define FP_REGNUM 4 /* Contains address of executing stack */
/* frame */
@ -222,14 +233,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
{ bcopy ((FROM), (TO), (REGNUM) < FP4_REGNUM ? 4 : 8); }
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM, FROM, TO) \
{ memcpy ((TO), (FROM), (REGNUM) < FP4_REGNUM ? 4 : 8); }
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
{ bcopy ((FROM), (TO), (REGNUM) < FP4_REGNUM ? 4 : 8); }
#define REGISTER_CONVERT_TO_RAW(REGNUM, FROM, TO) \
{ memcpy ((TO), (FROM), (REGNUM) < FP4_REGNUM ? 4 : 8); }
/* Return the GDB type object for the "standard" data type
of data in register N. */
@ -263,6 +274,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)((REGBUF) + 28))
/*
* This macro defines the register numbers (from REGISTER_NAMES) that
* are effectively unavailable to the user through ptrace(). It allows
* us to include the whole register set in REGISTER_NAMES (inorder to
* better support remote debugging). If it is used in
* fetch/store_inferior_registers() gdb will not complain about I/O errors
* on fetching these registers. If all registers in REGISTER_NAMES
* are available, then return false (0).
*/
#define CANNOT_STORE_REGISTER(regno) \
((regno) == 0) || \
((regno) == PCSQ_HEAD_REGNUM) || \
((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
@ -332,7 +359,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define ADDIL_P(INSN) (((INSN) & 0xfc000000) == 0x28000000)
#define LDO_P(INSN) (((INSN) & 0xfc00c000) == 0x34000000)
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ register int regnum; \
register CORE_ADDR next_addr; \
@ -341,9 +367,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
unsigned address; \
\
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
if ((frame_info)->pc <= ((frame_info)->frame - CALL_DUMMY_LENGTH - \
FP_REGNUM * 4 - 16 * 8) \
&& (frame_info)->pc > (frame_info)->frame) \
if ((frame_info->pc >= (frame_info)->frame \
&& (frame_info)->pc <= ((frame_info)->frame + CALL_DUMMY_LENGTH \
+ 32 * 4 + (NUM_REGS - FP0_REGNUM) * 8 \
+ 6 * 4))) \
find_dummy_frame_regs ((frame_info), &(frame_saved_regs)); \
else \
{ pc = get_pc_function_start ((frame_info)->pc); \
@ -402,6 +429,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
{ regnum = GET_FIELD (this_insn, 27, 31); \
(frame_saved_regs).regs[regnum + FP0_REGNUM] = next_addr; \
next_addr += 8; \
pc += 4; \
} \
else \
break; \
@ -415,67 +443,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME \
{ register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
int int_buffer; \
char freg_buffer[8]; \
/* Space for "arguments"; the RP goes in here. */ \
sp += 48; \
int_buffer = read_register (RP_REGNUM) | 0x3; \
write_memory (sp - 20, (char *)&int_buffer, 4); \
int_buffer = read_register (FP_REGNUM); \
write_memory (sp, (char *)&int_buffer, 4); \
write_register (FP_REGNUM, sp); \
sp += 4; \
for (regnum = 1; regnum < 31; regnum++) \
if (regnum != RP_REGNUM && regnum != FP_REGNUM) \
sp = push_word (sp, read_register (regnum)); \
for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++) \
{ read_register_bytes (REGISTER_BYTE (regnum), freg_buffer, 8); \
sp = push_bytes (sp, freg_buffer, 8);} \
sp = push_word (sp, read_register (IPSW_REGNUM)); \
sp = push_word (sp, read_register (SAR_REGNUM)); \
sp = push_word (sp, read_register (PCOQ_TAIL_REGNUM)); \
sp = push_word (sp, read_register (PCSQ_TAIL_REGNUM)); \
write_register (SP_REGNUM, sp);}
#define PUSH_DUMMY_FRAME push_dummy_frame ()
/* Discard from the stack the innermost frame,
restoring all saved registers. */
#define POP_FRAME \
{ register FRAME frame = get_current_frame (); \
register CORE_ADDR fp; \
register int regnum; \
struct frame_saved_regs fsr; \
struct frame_info *fi; \
char freg_buffer[8]; \
fi = get_frame_info (frame); \
fp = fi->frame; \
get_frame_saved_regs (fi, &fsr); \
for (regnum = 31; regnum > 0; regnum--) \
if (fsr.regs[regnum]) \
write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM ; regnum--) \
if (fsr.regs[regnum]) \
{ read_memory (fsr.regs[regnum], freg_buffer, 8); \
write_register_bytes (REGISTER_BYTE (regnum), freg_buffer, 8); }\
if (fsr.regs[IPSW_REGNUM]) \
write_register (IPSW_REGNUM, \
read_memory_integer (fsr.regs[IPSW_REGNUM], 4)); \
if (fsr.regs[SAR_REGNUM]) \
write_register (SAR_REGNUM, \
read_memory_integer (fsr.regs[SAR_REGNUM], 4)); \
if (fsr.regs[PCOQ_TAIL_REGNUM]) \
write_register (PCOQ_TAIL_REGNUM, \
read_memory_integer (fsr.regs[PCOQ_TAIL_REGNUM], 4));\
if (fsr.regs[PCSQ_TAIL_REGNUM]) \
write_register (PCSQ_TAIL_REGNUM, \
read_memory_integer (fsr.regs[PCSQ_TAIL_REGNUM], 4));\
write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
write_register (SP_REGNUM, fp + 8); \
flush_cached_frames (); \
set_current_frame (create_new_frame (read_register (FP_REGNUM),\
read_pc ())); }
#define POP_FRAME hp_pop_frame ()
/* This sequence of words is the instructions
@ -498,15 +470,19 @@ call_dummy
ldsid (0,r22), r3
ldil 0, r1 ; _sr4export will be placed here.
ldo 0(r1), r1
ldsid (0,r1), r4
combt,=,n r3, r4, text_space ; If target is in data space, do a
ldsid (0,r1), r19
combt,=,n r3, r19, text_space ; If target is in data space, do a
ble 0(sr5, r22) ; "normal" procedure call
copy r31, r2
break 4, 8
mtsp r21, sr0
ble,n 0(sr0, r22)
text_space ; Otherwise, go through _sr4export,
ble (sr4, r1) ; which will return back here.
stw 31,-24(r30)
break 4, 8
mtsp r21, sr0
ble,n 0(sr0, r22)
The dummy decides if the target is in text space or data space. If
it's in data space, there's no problem because the target can
@ -517,60 +493,98 @@ text_space ; Otherwise, go through _sr4export,
know that the frame is associated with the call dummy and treat it
specially. */
#define CALL_DUMMY { 0x4bda3fb9, 0x4bd93fb1, 0x4bd83fa9, 0x4bd73fa1, \
0x37c13fb9, 0x24201004, 0x2c391005, 0x24311006, \
0x2c291007, 0x22c00000, 0x36d60000, 0x02c010a3, \
0x20200000, 0x34210000, 0x002010a4, 0x80832012, \
0xe6c06000, 0x081f0242, 0x00010004, 0xe4202000, \
0x6bdf3fd1, 0x00010004}
#define CALL_DUMMY {0x4BDA3FB9, 0x4BD93FB1, 0x4BD83FA9, 0x4BD73FA1,\
0x37C13FB9, 0x24201004, 0x2C391005, 0x24311006,\
0x2C291007, 0x22C00000, 0x36D60000, 0x02C010A3,\
0x20200000, 0x34210000, 0x002010b3, 0x82632022,\
0xe6c06000, 0x081f0242, 0x00010004, 0x00151820,\
0xe6c00002, 0xe4202000, 0x6bdf3fd1, 0x00010004,\
0x00151820, 0xe6c00002}
#define CALL_DUMMY_LENGTH 88
#define CALL_DUMMY_LENGTH 104
#define CALL_DUMMY_START_OFFSET 0
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
{ static CORE_ADDR sr4export_address = 0; \
\
if (!sr4export_address) \
{ \
struct minimal_symbol *msymbol; \
msymbol = lookup_minimal_symbol ("_sr4export", (struct objfile *) NULL);\
if (msymbol = NULL) \
error ("Can't find an address for _sr4export trampoline"); \
else \
sr4export_address = msymbol -> address; \
} \
dummyname[9] = deposit_21 (fun >> 11, dummyname[9]); \
dummyname[10] = deposit_14 (fun & MASK_11, dummyname[10]); \
dummyname[12] = deposit_21 (sr4export_address >> 11, dummyname[12]); \
dummyname[13] = deposit_14 (sr4export_address & MASK_11, dummyname[13]);\
}
/*
* Insert the specified number of args and function address
* into a call sequence of the above form stored at DUMMYNAME.
*
* On the hppa we need to call the stack dummy through $$dyncall.
* Therefore our version of FIX_CALL_DUMMY takes an extra argument,
* real_pc, which is the location where gdb should start up the
* inferior to do the function call.
*/
#define FIX_CALL_DUMMY(dummyname, pc, real_pc, fun, nargs, args, type, gcc_p) \
{ \
CORE_ADDR dyncall_addr = 0, sr4export_addr = 0; \
\
if (!dyncall_addr) \
{ \
struct minimal_symbol *msymbol; \
msymbol = lookup_minimal_symbol ("$$dyncall", (struct objfile *) NULL);\
if (msymbol == NULL) \
error ("Can't find an address for $$dyncall trampoline"); \
else \
dyncall_addr = msymbol -> address; \
msymbol = lookup_minimal_symbol ("_sr4export", (struct objfile *) NULL);\
if (msymbol == NULL) \
error ("Can't find an address for _sr4export trampoline"); \
else \
sr4export_addr = msymbol -> address; \
} \
dummyname[9] = deposit_21 (fun >> 11, dummyname[9]); \
dummyname[10] = deposit_14 (fun & MASK_11, dummyname[10]); \
dummyname[12] = deposit_21 (sr4export_addr >> 11, \
dummyname[12]); \
dummyname[13] = deposit_14 (sr4export_addr & MASK_11, \
dummyname[13]); \
write_register (22, pc); \
real_pc = dyncall_addr; \
}
#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
sp = hp_push_arguments(nargs, args, sp, struct_return, struct_addr)
/* Write the PC to a random value.
On PA-RISC, we need to be sure that the PC space queue is correct. */
#define WRITE_PC(addr) \
{ int space_reg, space = ((addr) >> 30); \
int space_val; \
if (space == 0) \
space_reg = 43; /* Space reg sr4 */ \
else if (space == 1) \
space_reg = 48; /* Space reg sr5*/ \
else \
error ("pc = %x is in illegal space.", addr); \
space_val = read_register (space_reg); \
write_register (PCOQ_HEAD_REGNUM, addr); \
write_register (PCSQ_HEAD_REGNUM, space_val); \
write_register (PCOQ_TAIL_REGNUM, addr); \
write_register (PCSQ_TAIL_REGNUM, space_val);}
/* Symbol files have two symbol tables. Rather than do this right,
like the ELF symbol reading code, massive hackery was added
to dbxread.c and partial-stab.h. This flag turns on that
hackery, which should all go away FIXME FIXME FIXME FIXME now. */
#define GDB_TARGET_IS_HPPA
/*
* Unwind table and descriptor.
*/
struct unwind_table_entry {
unsigned int region_start;
unsigned int region_end;
unsigned int Cannot_unwind : 1;
unsigned int Millicode : 1;
unsigned int Millicode_save_sr0 : 1;
unsigned int Region_description : 2;
unsigned int reserverd1 : 1;
unsigned int Entry_SR : 1;
unsigned int Entry_FR : 4; /* number saved */
unsigned int Entry_GR : 5; /* number saved */
unsigned int Args_stored : 1;
unsigned int Variable_Frame : 1;
unsigned int Separate_Package_Body : 1;
unsigned int Frame_Extension_Millicode:1;
unsigned int Stack_Overflow_Check : 1;
unsigned int Two_Instruction_SP_Increment:1;
unsigned int Ada_Region : 1;
unsigned int reserved2 : 4;
unsigned int Save_SP : 1;
unsigned int Save_RP : 1;
unsigned int Save_MRP_in_frame : 1;
unsigned int extn_ptr_defined : 1;
unsigned int Cleanup_defined : 1;
unsigned int MPE_XL_interrupt_marker: 1;
unsigned int HP_UX_interrupt_marker: 1;
unsigned int Large_frame : 1;
unsigned int reserved4 : 2;
unsigned int Total_frame_size : 27;
};

View File

@ -704,6 +704,7 @@ call_function_by_hand (function, nargs, args)
struct cleanup *old_chain;
CORE_ADDR funaddr;
int using_gcc;
CORE_ADDR real_pc;
if (!target_has_execution)
noprocess();
@ -745,8 +746,15 @@ call_function_by_hand (function, nargs, args)
memcpy (dummy1, dummy, sizeof dummy);
for (i = 0; i < sizeof dummy / sizeof (REGISTER_TYPE); i++)
SWAP_TARGET_AND_HOST (&dummy1[i], sizeof (REGISTER_TYPE));
#ifdef GDB_TARGET_IS_HPPA
FIX_CALL_DUMMY (dummy1, start_sp, real_pc, funaddr, nargs, args,
value_type, using_gcc);
#else
FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
value_type, using_gcc);
real_pc = start_sp;
#endif
#if CALL_DUMMY_LOCATION == ON_STACK
write_memory (start_sp, (char *)dummy1, sizeof dummy);
@ -891,7 +899,7 @@ call_function_by_hand (function, nargs, args)
/* Execute the stack dummy routine, calling FUNCTION.
When it is done, discard the empty frame
after storing the contents of all regs into retbuf. */
run_stack_dummy (start_sp + CALL_DUMMY_START_OFFSET, retbuf);
run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf);
do_cleanups (old_chain);
@ -1086,8 +1094,7 @@ search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
if (BASETYPE_VIA_VIRTUAL (type, i))
{
base_offset =
baseclass_offset (type, i, *arg1p, offset);
base_offset = baseclass_offset (type, i, *arg1p, offset);
if (base_offset == -1)
error ("virtual baseclass botch");
}