binutils-gdb/gdb/rs6000-xdep.c
John Gilmore 9b280a7f53 RS/6000 portability changes (for hosting cross-debuggers).
* breakpoint.c (fixup_breakpoints):  Re-kludge to IBM6000_TARGET.
* buildsym.c, rs6000-xdep.c, rs6000-tdep.c, tm-rs6000.h,
xcoffexec.c, xcoffread.c:  Rename aixcoff to xcoff everywhere.
* printcmd.c (print_frame_args):  Remove an RS/6000 dependency.
* stabsread.c (define_symbol):  Remove RS/6000 dependencies.
* tm-rs6000.h (ATTACH_DETACH):  Remove: host-dependent.
(PTRACE_ATTACH, PTRACE_DETACH):  Remove: host-dep.
(NO_SINGLE_STEP):  Add, target-dependent.
(loadinfotextindex):  Lowercase, remove "aix_".
* xm-rs6000.h:  Add <sys/ptrace.h> for infptrace.c.
(NO_SINGLE_STEP):  Remove, target-dependent.
* xcoffexec.c (vmap_symtab):  Cleanup #if 0'd code.
* xcoffread.c:  Only build file if RS/6000 native GDB.
(build_function_symbol):  Remove #if 0'd code.
* rs6000-tdep.c:  Cleanup.  Add static fn protos.
Use CORE_ADDR for addresses throughout.  Make void fns void.
(pop_dummy_frame):  Add FIXME about bogosity of design here.
(rs6000_struct_return_address):  Ditto.
(frameless_function_invocation, frame_get_cache_fsr,
frame_initial_stack_address, xcoff_relocate_symtab,
xcoff_init_loadinfo, free_loadinfo, xcoff_add_toc_to_loadinfo,
add_text_to_loadinfo, find_toc_address):  Move from xdep file.
Use CORE_ADDRs.  Change identifiers to lowercase.

* rs6000-xdep.c:  Make whole file conditional on native RS/6000,
supplying dummy routines if non-native.  Add prototype for
static exec_one_dummy_insn.  Move a mess of functions to
rs6000-tdep.c (as above).  Remove #if 0'd code.

* config/rs6000.mh (XDEPFILES):  Move xcoffexec.o to target side.
(XM_CLIBS):  Add -lm to circumvent AIX 3.2 libc ldexp bug.
* config/rs6000.mt (TDEPFILES):  Adopt xcoffexec.o.
1992-08-29 00:32:58 +00:00

282 lines
7.6 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* IBM RS/6000 host-dependent code for GDB, the GNU debugger.
Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "target.h"
#ifdef RS6000_TARGET
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <a.out.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/core.h>
extern int errno;
static void
exec_one_dummy_insn PARAMS ((void));
/* Conversion from gdb-to-system special purpose register numbers.. */
static int special_regs[] = {
IAR, /* PC_REGNUM */
MSR, /* PS_REGNUM */
CR, /* CR_REGNUM */
LR, /* LR_REGNUM */
CTR, /* CTR_REGNUM */
XER, /* XER_REGNUM */
MQ /* MQ_REGNUM */
};
void
fetch_inferior_registers (regno)
int regno;
{
int ii;
extern char registers[];
if (regno < 0) { /* for all registers */
/* read 32 general purpose registers. */
for (ii=0; ii < 32; ++ii)
*(int*)&registers[REGISTER_BYTE (ii)] =
ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii, 0, 0);
/* read general purpose floating point registers. */
for (ii=0; ii < 32; ++ii)
ptrace (PT_READ_FPR, inferior_pid,
(PTRACE_ARG3_TYPE) &registers [REGISTER_BYTE (FP0_REGNUM+ii)],
FPR0+ii, 0);
/* read special registers. */
for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii)
*(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)] =
ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs[ii],
0, 0);
registers_fetched ();
return;
}
/* else an individual register is addressed. */
else if (regno < FP0_REGNUM) { /* a GPR */
*(int*)&registers[REGISTER_BYTE (regno)] =
ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0, 0);
}
else if (regno <= FPLAST_REGNUM) { /* a FPR */
ptrace (PT_READ_FPR, inferior_pid,
(PTRACE_ARG3_TYPE) &registers [REGISTER_BYTE (regno)],
(regno-FP0_REGNUM+FPR0), 0);
}
else if (regno <= LAST_SP_REGNUM) { /* a special register */
*(int*)&registers[REGISTER_BYTE (regno)] =
ptrace (PT_READ_GPR, inferior_pid,
(PTRACE_ARG3_TYPE) special_regs[regno-FIRST_SP_REGNUM], 0, 0);
}
else
fprintf (stderr, "gdb error: register no %d not implemented.\n", regno);
register_valid [regno] = 1;
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
void
store_inferior_registers (regno)
int regno;
{
extern char registers[];
errno = 0;
if (regno == -1) { /* for all registers.. */
int ii;
/* execute one dummy instruction (which is a breakpoint) in inferior
process. So give kernel a chance to do internal house keeping.
Otherwise the following ptrace(2) calls will mess up user stack
since kernel will get confused about the bottom of the stack (%sp) */
exec_one_dummy_insn ();
/* write general purpose registers first! */
for ( ii=GPR0; ii<=GPR31; ++ii) {
ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii,
*(int*)&registers[REGISTER_BYTE (ii)], 0);
if ( errno ) {
perror ("ptrace write_gpr"); errno = 0;
}
}
/* write floating point registers now. */
for ( ii=0; ii < 32; ++ii) {
ptrace (PT_WRITE_FPR, inferior_pid,
(PTRACE_ARG3_TYPE) &registers[REGISTER_BYTE (FP0_REGNUM+ii)],
FPR0+ii, 0);
if ( errno ) {
perror ("ptrace write_fpr"); errno = 0;
}
}
/* write special registers. */
for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii) {
ptrace (PT_WRITE_GPR, inferior_pid,
(PTRACE_ARG3_TYPE) special_regs[ii],
*(int*)&registers[REGISTER_BYTE (FIRST_SP_REGNUM+ii)], 0);
if ( errno ) {
perror ("ptrace write_gpr"); errno = 0;
}
}
}
/* else, a specific register number is given... */
else if (regno < FP0_REGNUM) { /* a GPR */
ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno,
*(int*)&registers[REGISTER_BYTE (regno)], 0);
}
else if (regno <= FPLAST_REGNUM) { /* a FPR */
ptrace (PT_WRITE_FPR, inferior_pid,
(PTRACE_ARG3_TYPE) &registers[REGISTER_BYTE (regno)],
regno-FP0_REGNUM+FPR0, 0);
}
else if (regno <= LAST_SP_REGNUM) { /* a special register */
ptrace (PT_WRITE_GPR, inferior_pid,
(PTRACE_ARG3_TYPE) special_regs [regno-FIRST_SP_REGNUM],
*(int*)&registers[REGISTER_BYTE (regno)], 0);
}
else
fprintf (stderr, "Gdb error: register no %d not implemented.\n", regno);
if ( errno ) {
perror ("ptrace write"); errno = 0;
}
}
void
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned int reg_addr; /* Unused in this version */
{
/* fetch GPRs and special registers from the first register section
in core bfd. */
if (which == 0) {
/* copy GPRs first. */
bcopy (core_reg_sect, registers, 32 * 4);
/* gdb's internal register template and bfd's register section layout
should share a common include file. FIXMEmgo */
/* then comes special registes. They are supposed to be in the same
order in gdb template and bfd `.reg' section. */
core_reg_sect += (32 * 4);
bcopy (core_reg_sect, &registers [REGISTER_BYTE (FIRST_SP_REGNUM)],
(LAST_SP_REGNUM - FIRST_SP_REGNUM + 1) * 4);
}
/* fetch floating point registers from register section 2 in core bfd. */
else if (which == 2)
bcopy (core_reg_sect, &registers [REGISTER_BYTE (FP0_REGNUM)], 32 * 8);
else
fprintf (stderr, "Gdb error: unknown parameter to fetch_core_registers().\n");
}
/* Execute one dummy breakpoint instruction. This way we give the kernel
a chance to do some housekeeping and update inferior's internal data,
including u_area. */
static void
exec_one_dummy_insn ()
{
#define DUMMY_INSN_ADDR (TEXT_SEGMENT_BASE)+0x200
unsigned long shadow;
unsigned int status, pid;
/* We plant one dummy breakpoint into DUMMY_INSN_ADDR address. We assume that
this address will never be executed again by the real code. */
target_insert_breakpoint (DUMMY_INSN_ADDR, &shadow);
errno = 0;
ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) DUMMY_INSN_ADDR, 0, 0);
if (errno)
perror ("pt_continue");
do {
pid = wait (&status);
} while (pid != inferior_pid);
target_remove_breakpoint (DUMMY_INSN_ADDR, &shadow);
}
#else /* RS6000_TARGET */
/* FIXME: Kludge this til we separate host vs. target vs. native code. */
void
fetch_inferior_registers (regno)
int regno;
{
}
void
store_inferior_registers (regno)
int regno;
{
}
void
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
unsigned int reg_addr; /* Unused in this version */
{
}
#endif /* RS6000_TARGET */