/* IBM RS/6000 host-dependent code for GDB, the GNU debugger.
- Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#include <stdio.h>
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "target.h"
+#ifdef IBM6000_TARGET
+
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/core.h>
-#include <sys/ldr.h>
extern int errno;
-extern int attach_flag;
+
+static void
+exec_one_dummy_insn PARAMS ((void));
/* Conversion from gdb-to-system special purpose register numbers.. */
XER, /* XER_REGNUM */
MQ /* MQ_REGNUM */
};
-
-
-/* Nonzero if we just simulated a single step break. */
-extern int one_stepped;
-
\f
+void
fetch_inferior_registers (regno)
- int regno;
+ int regno;
{
int ii;
extern char registers[];
- /* read 32 general purpose registers. */
+ if (regno < 0) { /* for all registers */
+
+ /* read 32 general purpose registers. */
+
+ for (ii=0; ii < 32; ++ii)
+ *(int*)®isters[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) ®isters [REGISTER_BYTE (FP0_REGNUM+ii)],
+ FPR0+ii, 0);
+
+ /* read special registers. */
+ for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii)
+ *(int*)®isters[REGISTER_BYTE (FIRST_SP_REGNUM+ii)] =
+ ptrace (PT_READ_GPR, inferior_pid, (PTRACE_ARG3_TYPE) special_regs[ii],
+ 0, 0);
- for (ii=0; ii < 32; ++ii)
- *(int*)®isters[REGISTER_BYTE (ii)] =
- ptrace (PT_READ_GPR, inferior_pid, ii, 0, 0);
+ registers_fetched ();
+ return;
+ }
- /* read general purpose floating point registers. */
+ /* else an individual register is addressed. */
- for (ii=0; ii < 32; ++ii)
- ptrace (PT_READ_FPR, inferior_pid,
- (int*)®isters [REGISTER_BYTE (FP0_REGNUM+ii)], FPR0+ii, 0);
+ else if (regno < FP0_REGNUM) { /* a GPR */
+ *(int*)®isters[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) ®isters [REGISTER_BYTE (regno)],
+ (regno-FP0_REGNUM+FPR0), 0);
+ }
+ else if (regno <= LAST_SP_REGNUM) { /* a special register */
+ *(int*)®isters[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);
- /* read special registers. */
- for (ii=0; ii <= LAST_SP_REGNUM-FIRST_SP_REGNUM; ++ii)
- *(int*)®isters[REGISTER_BYTE (FIRST_SP_REGNUM+ii)] =
- ptrace (PT_READ_GPR, inferior_pid, special_regs[ii], 0, 0);
+ register_valid [regno] = 1;
}
/* Store our register values back into the inferior.
/* write general purpose registers first! */
for ( ii=GPR0; ii<=GPR31; ++ii) {
- ptrace (PT_WRITE_GPR, inferior_pid, ii,
+ ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) ii,
*(int*)®isters[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,
- (int*)®isters[REGISTER_BYTE (FP0_REGNUM+ii)], FPR0+ii, 0);
+ (PTRACE_ARG3_TYPE) ®isters[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, special_regs[ii],
- *(int*)®isters[REGISTER_BYTE (FIRST_SP_REGNUM+ii)], 0);
+ ptrace (PT_WRITE_GPR, inferior_pid,
+ (PTRACE_ARG3_TYPE) special_regs[ii],
+ *(int*)®isters[REGISTER_BYTE (FIRST_SP_REGNUM+ii)], 0);
if ( errno ) {
perror ("ptrace write_gpr"); errno = 0;
}
else if (regno < FP0_REGNUM) { /* a GPR */
- ptrace (PT_WRITE_GPR, inferior_pid, regno,
+ ptrace (PT_WRITE_GPR, inferior_pid, (PTRACE_ARG3_TYPE) regno,
*(int*)®isters[REGISTER_BYTE (regno)], 0);
}
else if (regno <= FPLAST_REGNUM) { /* a FPR */
ptrace (PT_WRITE_FPR, inferior_pid,
- (int*)®isters[REGISTER_BYTE (regno)], regno-FP0_REGNUM+FPR0, 0);
+ (PTRACE_ARG3_TYPE) ®isters[REGISTER_BYTE (regno)],
+ regno-FP0_REGNUM+FPR0, 0);
}
else if (regno <= LAST_SP_REGNUM) { /* a special register */
- ptrace (PT_WRITE_GPR, inferior_pid, special_regs [regno-FIRST_SP_REGNUM],
- *(int*)®isters[REGISTER_BYTE (regno)], 0);
+ ptrace (PT_WRITE_GPR, inferior_pid,
+ (PTRACE_ARG3_TYPE) special_regs [regno-FIRST_SP_REGNUM],
+ *(int*)®isters[REGISTER_BYTE (regno)], 0);
}
else
}
-frameless_function_invocation (fi)
-struct frame_info *fi;
-{
- int ret;
- CORE_ADDR func_start, after_prologue;
-
-#if 0
- func_start = (LOAD_ADDR (get_pc_function_start (fi->pc)) +
- FUNCTION_START_OFFSET);
-#else
- func_start = get_pc_function_start (fi->pc) + FUNCTION_START_OFFSET;
-#endif
- if (func_start)
- {
- after_prologue = func_start;
- SKIP_PROLOGUE (after_prologue);
- ret = (after_prologue == func_start);
- }
- else
- /* If we can't find the start of the function, we don't really */
- /* know whether the function is frameless, but we should be */
- /* able to get a reasonable (i.e. best we can do under the */
- /* circumstances) backtrace by saying that it isn't. */
- ret = 0;
-
- return ret;
-
-}
-
-
-/* aixcoff_relocate_symtab - hook for symbol table relocation.
- also reads shared libraries.. */
-
-aixcoff_relocate_symtab (pid)
-unsigned int pid;
-{
-#define MAX_LOAD_SEGS 64 /* maximum number of load segments */
-
- struct ld_info *ldi;
- int temp;
-
- ldi = (void *) alloca(MAX_LOAD_SEGS * sizeof (*ldi));
-
- /* According to my humble theory, aixcoff has some timing problems and
- when the user stack grows, kernel doesn't update stack info in time
- and ptrace calls step on user stack. That is why we sleep here a little,
- and give kernel to update its internals. */
-
- usleep (36000);
-
- errno = 0;
- ptrace(PT_LDINFO, pid, ldi, MAX_LOAD_SEGS * sizeof(*ldi), ldi);
- if (errno)
- perror_with_name ("ptrace ldinfo");
-
- vmap_ldinfo(ldi);
-
- do {
- add_text_to_loadinfo (ldi->ldinfo_textorg, ldi->ldinfo_dataorg);
- } while (ldi->ldinfo_next
- && (ldi = (void *) (ldi->ldinfo_next + (char *) ldi)));
-
- /* Now that we've jumbled things around, re-sort them. */
- sort_minimal_symbols ();
-
- /* relocate the exec and core sections as well. */
- vmap_exec ();
-}
-
-
-/* Keep an array of load segment information and their TOC table addresses.
- This info will be useful when calling a shared library function by hand. */
-
-typedef struct {
- unsigned long textorg, dataorg, toc_offset;
-} LoadInfo;
-
-#define LOADINFOLEN 10
-
-static LoadInfo *loadInfo = NULL;
-static int loadInfoLen = 0;
-static int loadInfoTocIndex = 0;
-static int loadInfoTextIndex = 0;
-
-
-xcoff_init_loadinfo ()
-{
- loadInfoTocIndex = 0;
- loadInfoTextIndex = 0;
-
- if (loadInfoLen == 0) {
- loadInfo = (void*) xmalloc (sizeof (LoadInfo) * LOADINFOLEN);
- loadInfoLen = LOADINFOLEN;
- }
-}
-
-
-free_loadinfo ()
-{
- if (loadInfo)
- free (loadInfo);
- loadInfo = NULL;
- loadInfoLen = 0;
- loadInfoTocIndex = 0;
- loadInfoTextIndex = 0;
-}
-
-
-xcoff_add_toc_to_loadinfo (unsigned long tocaddr)
-{
- while (loadInfoTocIndex >= loadInfoLen) {
- loadInfoLen += LOADINFOLEN;
- loadInfo = (void*) xrealloc (loadInfo, sizeof(LoadInfo) * loadInfoLen);
- }
- loadInfo [loadInfoTocIndex++].toc_offset = tocaddr;
-}
-
-
-add_text_to_loadinfo (unsigned long textaddr, unsigned long dataaddr)
-{
- while (loadInfoTextIndex >= loadInfoLen) {
- loadInfoLen += LOADINFOLEN;
- loadInfo = (void*) xrealloc (loadInfo, sizeof(LoadInfo) * loadInfoLen);
- }
- loadInfo [loadInfoTextIndex].textorg = textaddr;
- loadInfo [loadInfoTextIndex].dataorg = dataaddr;
- ++loadInfoTextIndex;
-}
-
-
-unsigned long
-find_toc_address (unsigned long pc)
-{
- int ii, toc_entry;
-
- for (ii=0; ii < loadInfoTextIndex; ++ii)
- if (pc > loadInfo [ii].textorg)
- toc_entry = ii;
-
- return loadInfo [toc_entry].dataorg + loadInfo [toc_entry].toc_offset;
-}
-
-
-/* execute one dummy breakpoint instruction. This way we give kernel
+/* 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 0x10000200
+#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, DUMMY_INSN_ADDR, 0, 0);
+ ptrace (PT_CONTINUE, inferior_pid, (PTRACE_ARG3_TYPE) DUMMY_INSN_ADDR, 0, 0);
if (errno)
perror ("pt_continue");
target_remove_breakpoint (DUMMY_INSN_ADDR, &shadow);
}
+
+#else /* IBM6000_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 /* IBM6000_TARGET */