Boston, MA 02111-1307, USA. */
#include "server.h"
-#include <sys/wait.h>
+#include "linux-low.h"
+#include <sys/wait.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
-/***************Begin MY defs*********************/
-static char my_registers[REGISTER_BYTES];
-char *registers = my_registers;
-/***************End MY defs*********************/
+static CORE_ADDR linux_bp_reinsert;
-#ifdef HAVE_SYS_REG_H
-#include <sys/reg.h>
-#endif
+static void linux_resume (int step, int signal);
#define PTRACE_ARG3_TYPE long
-#define PTRACE_XFER_TYPE int
+#define PTRACE_XFER_TYPE long
+
+#ifdef HAVE_LINUX_REGSETS
+static int use_regsets_p = 1;
+#endif
extern int errno;
-static void initialize_arch (void);
+static int inferior_pid;
+
+struct inferior_linux_data
+{
+ int pid;
+};
/* Start an inferior process and returns its pid.
ALLARGS is a vector of program-name and args. */
-int
-create_inferior (char *program, char **allargs)
+static int
+linux_create_inferior (char *program, char **allargs)
{
+ struct inferior_linux_data *tdata;
int pid;
pid = fork ();
_exit (0177);
}
- return pid;
+ add_inferior (pid);
+ tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata));
+ tdata->pid = pid;
+ set_inferior_target_data (current_inferior, tdata);
+
+ /* FIXME remove */
+ inferior_pid = pid;
+ return 0;
}
/* Attach to an inferior process. */
-int
-myattach (int pid)
+static int
+linux_attach (int pid)
{
+ struct inferior_linux_data *tdata;
+
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
{
fprintf (stderr, "Cannot attach to process %d: %s (%d)\n", pid,
_exit (0177);
}
+ add_inferior (pid);
+ tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata));
+ tdata->pid = pid;
+ set_inferior_target_data (current_inferior, tdata);
return 0;
}
/* Kill the inferior process. Make us have no inferior. */
-void
-kill_inferior (void)
+static void
+linux_kill (void)
{
if (inferior_pid == 0)
return;
ptrace (PTRACE_KILL, inferior_pid, 0, 0);
wait (0);
+ clear_inferiors ();
}
/* Return nonzero if the given thread is still alive. */
-int
-mythread_alive (int pid)
+static int
+linux_thread_alive (int pid)
{
return 1;
}
+static int
+linux_wait_for_one_inferior (struct inferior_info *child)
+{
+ struct inferior_linux_data *child_data = inferior_target_data (child);
+ int pid, wstat;
+
+ while (1)
+ {
+ pid = waitpid (child_data->pid, &wstat, 0);
+
+ if (pid != child_data->pid)
+ perror_with_name ("wait");
+
+ /* If this target supports breakpoints, see if we hit one. */
+ if (the_low_target.stop_pc != NULL
+ && WIFSTOPPED (wstat)
+ && WSTOPSIG (wstat) == SIGTRAP)
+ {
+ CORE_ADDR stop_pc;
+
+ if (linux_bp_reinsert != 0)
+ {
+ reinsert_breakpoint (linux_bp_reinsert);
+ linux_bp_reinsert = 0;
+ linux_resume (0, 0);
+ continue;
+ }
+
+ fetch_inferior_registers (0);
+ stop_pc = (*the_low_target.stop_pc) ();
+
+ if (check_breakpoints (stop_pc) != 0)
+ {
+ if (the_low_target.set_pc != NULL)
+ (*the_low_target.set_pc) (stop_pc);
+
+ if (the_low_target.breakpoint_reinsert_addr == NULL)
+ {
+ linux_bp_reinsert = stop_pc;
+ uninsert_breakpoint (stop_pc);
+ linux_resume (1, 0);
+ }
+ else
+ {
+ reinsert_breakpoint_by_bp
+ (stop_pc, (*the_low_target.breakpoint_reinsert_addr) ());
+ linux_resume (0, 0);
+ }
+
+ continue;
+ }
+ }
+
+ return wstat;
+ }
+ /* NOTREACHED */
+ return 0;
+}
+
/* Wait for process, returns status */
-unsigned char
-mywait (char *status)
+static unsigned char
+linux_wait (char *status)
{
- int pid;
- union wait w;
+ int w;
enable_async_io ();
- pid = waitpid (inferior_pid, (int *)&w, 0);
+ w = linux_wait_for_one_inferior (current_inferior);
disable_async_io ();
- if (pid != inferior_pid)
- perror_with_name ("wait");
if (WIFEXITED (w))
{
fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
*status = 'W';
+ clear_inferiors ();
return ((unsigned char) WEXITSTATUS (w));
}
else if (!WIFSTOPPED (w))
{
fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ clear_inferiors ();
*status = 'X';
return ((unsigned char) WTERMSIG (w));
}
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
-void
-myresume (int step, int signal)
+static void
+linux_resume (int step, int signal)
{
errno = 0;
ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
}
-#if !defined (offsetof)
-#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
-#endif
+#ifdef HAVE_LINUX_USRREGS
-/* U_REGS_OFFSET is the offset of the registers within the u area. */
-#if !defined (U_REGS_OFFSET)
-#define U_REGS_OFFSET \
- ptrace (PT_READ_U, inferior_pid, \
- (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
- - KERNEL_U_ADDR
-#endif
-
-#ifdef I386_GNULINUX_TARGET
-/* This module only supports access to the general purpose registers.
- Adjust the relevant constants accordingly.
-
- FIXME: kettenis/2001-03-28: We should really use PTRACE_GETREGS to
- get at the registers. Better yet, we should try to share code with
- i386-linux-nat.c. */
-#undef NUM_FREGS
-#define NUM_FREGS 0
-#undef NUM_REGS
-#define NUM_REGS NUM_GREGS
-
-/* This stuff comes from i386-tdep.c. */
-
-/* i386_register_byte[i] is the offset into the register file of the
- start of register number i. We initialize this from
- i386_register_raw_size. */
-int i386_register_byte[MAX_NUM_REGS];
-
-/* i386_register_raw_size[i] is the number of bytes of storage in
- GDB's register array occupied by register i. */
-int i386_register_raw_size[MAX_NUM_REGS] = {
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 10, 10, 10, 10,
- 10, 10, 10, 10,
- 4, 4, 4, 4,
- 4, 4, 4, 4,
- 16, 16, 16, 16,
- 16, 16, 16, 16,
- 4
-};
-
-static void
-initialize_arch (void)
-{
- /* Initialize the table saying where each register starts in the
- register file. */
- {
- int i, offset;
-
- offset = 0;
- for (i = 0; i < MAX_NUM_REGS; i++)
- {
- i386_register_byte[i] = offset;
- offset += i386_register_raw_size[i];
- }
- }
-}
-
-/* This stuff comes from i386-linux-nat.c. */
-
-/* Mapping between the general-purpose registers in `struct user'
- format and GDB's register array layout. */
-static int regmap[] =
-{
- EAX, ECX, EDX, EBX,
- UESP, EBP, ESI, EDI,
- EIP, EFL, CS, SS,
- DS, ES, FS, GS
-};
-
-/* Return the address of register REGNUM. BLOCKEND is the value of
- u.u_ar0, which should point to the registers. */
-
-CORE_ADDR
-register_u_addr (CORE_ADDR blockend, int regnum)
-{
- return (blockend + 4 * regmap[regnum]);
-}
-#elif defined(TARGET_M68K)
-static void
-initialize_arch (void)
-{
- return;
-}
-
-/* This table must line up with REGISTER_NAMES in tm-m68k.h */
-static int regmap[] =
-{
-#ifdef PT_D0
- PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7,
- PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP,
- PT_SR, PT_PC,
-#else
- 14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15,
- 17, 18,
-#endif
-#ifdef PT_FP0
- PT_FP0, PT_FP1, PT_FP2, PT_FP3, PT_FP4, PT_FP5, PT_FP6, PT_FP7,
- PT_FPCR, PT_FPSR, PT_FPIAR
-#else
- 21, 24, 27, 30, 33, 36, 39, 42, 45, 46, 47
-#endif
-};
-
-/* BLOCKEND is the value of u.u_ar0, and points to the place where GS
- is stored. */
+#define REGISTER_RAW_SIZE(regno) register_size((regno))
int
-m68k_linux_register_u_addr (int blockend, int regnum)
-{
- return (blockend + 4 * regmap[regnum]);
-}
-#elif defined(IA64_GNULINUX_TARGET)
-#undef NUM_FREGS
-#define NUM_FREGS 0
-
-#include <asm/ptrace_offsets.h>
-
-static int u_offsets[] =
- {
- /* general registers */
- -1, /* gr0 not available; i.e, it's always zero */
- PT_R1,
- PT_R2,
- PT_R3,
- PT_R4,
- PT_R5,
- PT_R6,
- PT_R7,
- PT_R8,
- PT_R9,
- PT_R10,
- PT_R11,
- PT_R12,
- PT_R13,
- PT_R14,
- PT_R15,
- PT_R16,
- PT_R17,
- PT_R18,
- PT_R19,
- PT_R20,
- PT_R21,
- PT_R22,
- PT_R23,
- PT_R24,
- PT_R25,
- PT_R26,
- PT_R27,
- PT_R28,
- PT_R29,
- PT_R30,
- PT_R31,
- /* gr32 through gr127 not directly available via the ptrace interface */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- /* Floating point registers */
- -1, -1, /* f0 and f1 not available (f0 is +0.0 and f1 is +1.0) */
- PT_F2,
- PT_F3,
- PT_F4,
- PT_F5,
- PT_F6,
- PT_F7,
- PT_F8,
- PT_F9,
- PT_F10,
- PT_F11,
- PT_F12,
- PT_F13,
- PT_F14,
- PT_F15,
- PT_F16,
- PT_F17,
- PT_F18,
- PT_F19,
- PT_F20,
- PT_F21,
- PT_F22,
- PT_F23,
- PT_F24,
- PT_F25,
- PT_F26,
- PT_F27,
- PT_F28,
- PT_F29,
- PT_F30,
- PT_F31,
- PT_F32,
- PT_F33,
- PT_F34,
- PT_F35,
- PT_F36,
- PT_F37,
- PT_F38,
- PT_F39,
- PT_F40,
- PT_F41,
- PT_F42,
- PT_F43,
- PT_F44,
- PT_F45,
- PT_F46,
- PT_F47,
- PT_F48,
- PT_F49,
- PT_F50,
- PT_F51,
- PT_F52,
- PT_F53,
- PT_F54,
- PT_F55,
- PT_F56,
- PT_F57,
- PT_F58,
- PT_F59,
- PT_F60,
- PT_F61,
- PT_F62,
- PT_F63,
- PT_F64,
- PT_F65,
- PT_F66,
- PT_F67,
- PT_F68,
- PT_F69,
- PT_F70,
- PT_F71,
- PT_F72,
- PT_F73,
- PT_F74,
- PT_F75,
- PT_F76,
- PT_F77,
- PT_F78,
- PT_F79,
- PT_F80,
- PT_F81,
- PT_F82,
- PT_F83,
- PT_F84,
- PT_F85,
- PT_F86,
- PT_F87,
- PT_F88,
- PT_F89,
- PT_F90,
- PT_F91,
- PT_F92,
- PT_F93,
- PT_F94,
- PT_F95,
- PT_F96,
- PT_F97,
- PT_F98,
- PT_F99,
- PT_F100,
- PT_F101,
- PT_F102,
- PT_F103,
- PT_F104,
- PT_F105,
- PT_F106,
- PT_F107,
- PT_F108,
- PT_F109,
- PT_F110,
- PT_F111,
- PT_F112,
- PT_F113,
- PT_F114,
- PT_F115,
- PT_F116,
- PT_F117,
- PT_F118,
- PT_F119,
- PT_F120,
- PT_F121,
- PT_F122,
- PT_F123,
- PT_F124,
- PT_F125,
- PT_F126,
- PT_F127,
- /* predicate registers - we don't fetch these individually */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* branch registers */
- PT_B0,
- PT_B1,
- PT_B2,
- PT_B3,
- PT_B4,
- PT_B5,
- PT_B6,
- PT_B7,
- /* virtual frame pointer and virtual return address pointer */
- -1, -1,
- /* other registers */
- PT_PR,
- PT_CR_IIP, /* ip */
- PT_CR_IPSR, /* psr */
- PT_CFM, /* cfm */
- /* kernel registers not visible via ptrace interface (?) */
- -1, -1, -1, -1, -1, -1, -1, -1,
- /* hole */
- -1, -1, -1, -1, -1, -1, -1, -1,
- PT_AR_RSC,
- PT_AR_BSP,
- PT_AR_BSPSTORE,
- PT_AR_RNAT,
- -1,
- -1, /* Not available: FCR, IA32 floating control register */
- -1, -1,
- -1, /* Not available: EFLAG */
- -1, /* Not available: CSD */
- -1, /* Not available: SSD */
- -1, /* Not available: CFLG */
- -1, /* Not available: FSR */
- -1, /* Not available: FIR */
- -1, /* Not available: FDR */
- -1,
- PT_AR_CCV,
- -1, -1, -1,
- PT_AR_UNAT,
- -1, -1, -1,
- PT_AR_FPSR,
- -1, -1, -1,
- -1, /* Not available: ITC */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1,
- PT_AR_PFS,
- PT_AR_LC,
- -1, /* Not available: EC, the Epilog Count register */
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1,
- /* nat bits - not fetched directly; instead we obtain these bits from
- either rnat or unat or from memory. */
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1,
- };
-
-int
-ia64_register_u_addr (int blockend, int regnum)
+register_addr (int regnum)
{
int addr;
- if (regnum < 0 || regnum >= NUM_REGS)
+ if (regnum < 0 || regnum >= the_low_target.num_regs)
error ("Invalid register number %d.", regnum);
- addr = u_offsets[regnum];
+ addr = the_low_target.regmap[regnum];
if (addr == -1)
addr = 0;
return addr;
}
-static void
-initialize_arch (void)
-{
- return;
-}
-
-#elif defined(ARM_GNULINUX_TARGET)
-int arm_register_u_addr(blockend, regnum)
- int blockend;
- int regnum;
-{
- return blockend + REGISTER_BYTE(regnum);
-}
-
-static void
-initialize_arch ()
-{
-}
-#endif
-
-CORE_ADDR
-register_addr (int regno, CORE_ADDR blockend)
-{
- CORE_ADDR addr;
-
- if (regno < 0 || regno >= NUM_REGS)
- error ("Invalid register number %d.", regno);
-
- REGISTER_U_ADDR (addr, blockend, regno);
-
- return addr;
-}
-
/* Fetch one register. */
-
static void
fetch_register (int regno)
{
CORE_ADDR regaddr;
register int i;
- /* Offset of registers within the u area. */
- unsigned int offset;
-
- offset = U_REGS_OFFSET;
+ if (regno >= the_low_target.num_regs)
+ return;
+ if ((*the_low_target.cannot_fetch_register) (regno))
+ return;
- regaddr = register_addr (regno, offset);
+ regaddr = register_addr (regno);
+ if (regaddr == -1)
+ return;
for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
{
errno = 0;
- *(PTRACE_XFER_TYPE *) ®isters[REGISTER_BYTE (regno) + i] =
+ *(PTRACE_XFER_TYPE *) (register_data (regno) + i) =
ptrace (PTRACE_PEEKUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, 0);
regaddr += sizeof (PTRACE_XFER_TYPE);
if (errno != 0)
}
/* Fetch all registers, or just one, from the child process. */
-
-void
-fetch_inferior_registers (int regno)
+static void
+usr_fetch_inferior_registers (int regno)
{
if (regno == -1 || regno == 0)
- for (regno = 0; regno < NUM_REGS - NUM_FREGS; regno++)
+ for (regno = 0; regno < the_low_target.num_regs; regno++)
fetch_register (regno);
else
fetch_register (regno);
/* 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 (int regno)
+static void
+usr_store_inferior_registers (int regno)
{
CORE_ADDR regaddr;
int i;
- unsigned int offset = U_REGS_OFFSET;
if (regno >= 0)
{
-#if 0
- if (CANNOT_STORE_REGISTER (regno))
+ if (regno >= the_low_target.num_regs)
+ return;
+
+ if ((*the_low_target.cannot_store_register) (regno) == 1)
+ return;
+
+ regaddr = register_addr (regno);
+ if (regaddr == -1)
return;
-#endif
- regaddr = register_addr (regno, offset);
errno = 0;
-#if 0
- if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
{
- scratch = *(int *) ®isters[REGISTER_BYTE (regno)] | 0x3;
- ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
- scratch, 0);
+ errno = 0;
+ ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) (register_data (regno) + i));
if (errno != 0)
{
- /* Error, even if attached. Failing to write these two
- registers is pretty serious. */
- sprintf (buf, "writing register number %d", regno);
- perror_with_name (buf);
+ if ((*the_low_target.cannot_store_register) (regno) == 0)
+ {
+ char *err = strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "writing register %d: %s",
+ regno, err);
+ error (msg);
+ return;
+ }
}
+ regaddr += sizeof (int);
}
- else
-#endif
- for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
- {
- errno = 0;
- ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
- *(int *) ®isters[REGISTER_BYTE (regno) + i]);
- if (errno != 0)
- {
- /* Warning, not error, in case we are attached; sometimes the
- kernel doesn't let us at the registers. */
- char *err = strerror (errno);
- char *msg = alloca (strlen (err) + 128);
- sprintf (msg, "writing register %d: %s",
- regno, err);
- error (msg);
- return;
- }
- regaddr += sizeof (int);
- }
}
else
- for (regno = 0; regno < NUM_REGS - NUM_FREGS; regno++)
+ for (regno = 0; regno < the_low_target.num_regs; regno++)
store_inferior_registers (regno);
}
+#endif /* HAVE_LINUX_USRREGS */
+
+
+
+#ifdef HAVE_LINUX_REGSETS
+
+static int
+regsets_fetch_inferior_registers (void)
+{
+ struct regset_info *regset;
+
+ regset = target_regsets;
+
+ while (regset->size >= 0)
+ {
+ void *buf;
+ int res;
+
+ if (regset->size == 0)
+ {
+ regset ++;
+ continue;
+ }
+
+ buf = malloc (regset->size);
+ res = ptrace (regset->get_request, inferior_pid, 0, (int) buf);
+ if (res < 0)
+ {
+ if (errno == EIO)
+ {
+ /* If we get EIO on the first regset, do not try regsets again.
+ If we get EIO on a later regset, disable that regset. */
+ if (regset == target_regsets)
+ {
+ use_regsets_p = 0;
+ return -1;
+ }
+ else
+ {
+ regset->size = 0;
+ continue;
+ }
+ }
+ else
+ {
+ perror ("Warning: ptrace(regsets_fetch_inferior_registers)");
+ }
+ }
+ regset->store_function (buf);
+ regset ++;
+ }
+ return 0;
+}
+
+static int
+regsets_store_inferior_registers (void)
+{
+ struct regset_info *regset;
+
+ regset = target_regsets;
+
+ while (regset->size >= 0)
+ {
+ void *buf;
+ int res;
+
+ if (regset->size == 0)
+ {
+ regset ++;
+ continue;
+ }
+
+ buf = malloc (regset->size);
+ regset->fill_function (buf);
+ res = ptrace (regset->set_request, inferior_pid, 0, (int) buf);
+ if (res < 0)
+ {
+ if (errno == EIO)
+ {
+ /* If we get EIO on the first regset, do not try regsets again.
+ If we get EIO on a later regset, disable that regset. */
+ if (regset == target_regsets)
+ {
+ use_regsets_p = 0;
+ return -1;
+ }
+ else
+ {
+ regset->size = 0;
+ continue;
+ }
+ }
+ else
+ {
+ perror ("Warning: ptrace(regsets_store_inferior_registers)");
+ }
+ }
+ regset ++;
+ }
+ return 0;
+}
+
+#endif /* HAVE_LINUX_REGSETS */
+
+
+void
+linux_fetch_registers (int regno)
+{
+#ifdef HAVE_LINUX_REGSETS
+ if (use_regsets_p)
+ {
+ if (regsets_fetch_inferior_registers () == 0)
+ return;
+ }
+#endif
+#ifdef HAVE_LINUX_USRREGS
+ usr_fetch_inferior_registers (regno);
+#endif
+}
+
+void
+linux_store_registers (int regno)
+{
+#ifdef HAVE_LINUX_REGSETS
+ if (use_regsets_p)
+ {
+ if (regsets_store_inferior_registers () == 0)
+ return;
+ }
+#endif
+#ifdef HAVE_LINUX_USRREGS
+ usr_store_inferior_registers (regno);
+#endif
+}
-/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
- in the NEW_SUN_PTRACE case.
- It ought to be straightforward. But it appears that writing did
- not write the data that I specified. I cannot understand where
- it got the data that it actually did write. */
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. */
-void
-read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
+static void
+linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
register int i;
/* Round starting address down to longword boundary. */
On failure (cannot write the inferior)
returns the value of errno. */
-int
-write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
+static int
+linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
{
register int i;
/* Round starting address down to longword boundary. */
return 0;
}
+
+static void
+linux_look_up_symbols (void)
+{
+ /* Don't need to look up any symbols yet. */
+}
+
\f
+static struct target_ops linux_target_ops = {
+ linux_create_inferior,
+ linux_attach,
+ linux_kill,
+ linux_thread_alive,
+ linux_resume,
+ linux_wait,
+ linux_fetch_registers,
+ linux_store_registers,
+ linux_read_memory,
+ linux_write_memory,
+ linux_look_up_symbols,
+};
+
void
initialize_low (void)
{
- initialize_arch ();
+ set_target_ops (&linux_target_ops);
+ set_breakpoint_data (the_low_target.breakpoint,
+ the_low_target.breakpoint_len);
+ init_registers ();
}