This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
gdbserver for arm-linux
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: gdbserver for arm-linux
- From: Mark Salter <msalter at redhat dot com>
- Date: Fri, 11 Aug 2000 12:58:38 -0400
The following patch adds gdbserver support for arm-linux.
--Mark
2000-08-11 Mark Salter <msalter@redhat.com>
* gdbserver/low-linux.c: Added arm-linux support.
Index: low-linux.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/low-linux.c,v
retrieving revision 1.4
diff -p -c -r1.4 low-linux.c
*** low-linux.c 2000/07/30 01:48:28 1.4
--- low-linux.c 2000/08/11 16:46:28
*************** initialize_arch (void)
*** 545,550 ****
--- 545,707 ----
{
return;
}
+ #elif defined(__arm__)
+
+ #define typeNone 0x00
+ #define typeSingle 0x01
+ #define typeDouble 0x02
+ #define typeExtended 0x03
+
+ typedef union tagFPREG
+ {
+ unsigned int fSingle;
+ unsigned int fDouble[2];
+ unsigned int fExtended[3];
+ }
+ FPREG;
+
+ typedef struct tagFPA11
+ {
+ FPREG fpreg[8]; /* 8 floating point registers */
+ unsigned int fpsr; /* floating point status register */
+ unsigned int fpcr; /* floating point control register */
+ unsigned char fType[8]; /* type of floating point value held in
+ floating point registers. */
+ int initflag; /* NWFPE initialization flag. */
+ }
+ FPA11;
+
+
+ /* Only used for integer registers.
+ * Have top handle PS_REGNUM specially because the offset in GDB's
+ * register file is different than the ptrace user offset.
+ */
+ int
+ arm_linux_register_u_addr (int blockend, int regnum)
+ {
+ if (regnum == PS_REGNUM)
+ regnum = NUM_GREGS;
+
+ return blockend + REGISTER_BYTE (regnum);
+ }
+
+ #define REGISTER_U_ADDR(addr, blockend, regno) \
+ addr = arm_linux_register_u_addr(blockend, regno)
+
+ /* Get the whole floating point state of the process and store the
+ floating point stack into registers[]. */
+
+ static void
+ fetch_fpregs (void)
+ {
+ int ret, regno;
+ FPA11 fp;
+
+ /* Read the floating point state. */
+ ret = ptrace (PT_GETFPREGS, inferior_pid, 0, &fp);
+ if (ret < 0)
+ {
+ fprintf (stderr, "Unable to fetch the floating point state.");
+ return;
+ }
+
+ /* Fetch fpsr. */
+ memcpy (®isters[REGISTER_BYTE (FPS_REGNUM)], (char *) &fp.fpsr,
+ REGISTER_RAW_SIZE (FPS_REGNUM));
+
+ /* Fetch the floating point registers. */
+ for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
+ {
+ unsigned int mem[3];
+ int fn = regno - F0_REGNUM;
+
+ switch (fp.fType[fn])
+ {
+ case typeSingle:
+ mem[0] = fp.fpreg[fn].fSingle;
+ mem[1] = 0;
+ mem[2] = 0;
+ break;
+
+ case typeDouble:
+ mem[0] = fp.fpreg[fn].fDouble[1];
+ mem[1] = fp.fpreg[fn].fDouble[0];
+ mem[2] = 0;
+ break;
+
+ case typeExtended:
+ mem[0] = fp.fpreg[fn].fExtended[0]; /* sign & exponent */
+ mem[1] = fp.fpreg[fn].fExtended[2]; /* ls bits */
+ mem[2] = fp.fpreg[fn].fExtended[1]; /* ms bits */
+ break;
+
+ default:
+ mem[0] = 0;
+ mem[1] = 0;
+ mem[2] = 0;
+ }
+ memcpy (®isters[REGISTER_BYTE (regno)], (char *) mem,
+ REGISTER_RAW_SIZE (regno));
+ }
+ }
+
+ /* Save the whole floating point state of the process using
+ the contents from registers[]. */
+
+ static void
+ store_fpregs (void)
+ {
+ int ret, regno;
+ FPA11 fp;
+
+ /* Store fpsr. */
+ memcpy ((char *) &fp.fpsr, ®isters[REGISTER_BYTE (FPS_REGNUM)],
+ REGISTER_RAW_SIZE (FPS_REGNUM));
+
+ /* Store the floating point registers. */
+ for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
+ {
+ unsigned int mem[3];
+ unsigned int fn = regno - F0_REGNUM;
+
+ memcpy ((char *) mem, ®isters[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno));
+
+ switch (fp.fType[fn])
+ {
+ case typeSingle:
+ fp.fpreg[fn].fSingle = mem[0];
+ fp.fType[fn] = typeSingle;
+ break;
+
+ case typeDouble:
+ fp.fpreg[fn].fDouble[1] = mem[0];
+ fp.fpreg[fn].fDouble[0] = mem[1];
+ fp.fType[fn] = typeDouble;
+ break;
+
+ case typeExtended:
+ fp.fpreg[fn].fExtended[0] = mem[0]; /* sign & exponent */
+ fp.fpreg[fn].fExtended[2] = mem[1]; /* ls bits */
+ fp.fpreg[fn].fExtended[1] = mem[2]; /* ms bits */
+ fp.fType[fn] = typeDouble;
+ break;
+ }
+ }
+
+ ret = ptrace (PTRACE_SETFPREGS, inferior_pid, 0, &fp);
+ if (ret < 0)
+ {
+ fprintf (stderr, "Unable to store floating point state.");
+ return;
+ }
+ }
+
+ static void
+ initialize_arch ()
+ {
+ return;
+ }
#endif
CORE_ADDR
*************** error_exit:;
*** 596,669 ****
/* Fetch all registers, or just one, from the child process. */
void
fetch_inferior_registers (int regno)
{
if (regno == -1 || regno == 0)
for (regno = 0; regno < NUM_REGS - NUM_FREGS; 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)
{
CORE_ADDR regaddr;
int i;
unsigned int offset = U_REGS_OFFSET;
- if (regno >= 0)
- {
#if 0
! if (CANNOT_STORE_REGISTER (regno))
! return;
#endif
! regaddr = register_addr (regno, offset);
! errno = 0;
#if 0
! if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
{
! scratch = *(int *) ®isters[REGISTER_BYTE (regno)] | 0x3;
! ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
! scratch, 0);
! 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);
! }
}
! 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++)
! store_inferior_registers (regno);
}
/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
in the NEW_SUN_PTRACE case.
--- 753,890 ----
/* Fetch all registers, or just one, from the child process. */
+ #if defined(__arm__)
+ void
+ fetch_inferior_registers (int regno)
+ {
+ int rlimit, gotfp = 0;
+
+ if (regno == -1 || regno == 0)
+ {
+ regno = 0;
+ rlimit = NUM_REGS;
+ }
+ else
+ rlimit = regno+1;
+
+ while (regno < rlimit)
+ {
+ if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
+ fetch_register (regno);
+ else if (!gotfp)
+ {
+ fetch_fpregs ();
+ gotfp = 1;
+ }
+ regno++;
+ }
+ }
+ #else
void
fetch_inferior_registers (int regno)
{
+
if (regno == -1 || regno == 0)
for (regno = 0; regno < NUM_REGS - NUM_FREGS; regno++)
fetch_register (regno);
else
fetch_register (regno);
}
+ #endif
! /* Store one register. */
void
! store_register (int regno)
{
CORE_ADDR regaddr;
int i;
unsigned int offset = U_REGS_OFFSET;
#if 0
! if (CANNOT_STORE_REGISTER (regno))
! return;
#endif
! regaddr = register_addr (regno, offset);
! errno = 0;
#if 0
! if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
! {
! scratch = *(int *) ®isters[REGISTER_BYTE (regno)] | 0x3;
! ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
! scratch, 0);
! 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);
}
! }
! 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);*/
! fprintf(stderr, "%s\n", msg);
! return;
! }
! regaddr += sizeof (int);
}
+ }
+
+ /* 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). */
+
+ #if defined(__arm__)
+ void
+ store_inferior_registers (int regno)
+ {
+ int rlimit, fpdone = 0;
+
+ if (regno == -1)
+ {
+ regno = 0;
+ rlimit = NUM_REGS;
+ }
else
+ rlimit = regno+1;
+
+ while (regno < rlimit)
+ {
+ if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
+ store_register (regno);
+ else if (!fpdone)
+ {
+ store_fpregs ();
+ fpdone = 1;
+ }
+ regno++;
+ }
+ }
+ #else
+ void
+ store_inferior_registers (int regno)
+ {
+ if (regno >= 0)
+ store_register(regno);
+ else
for (regno = 0; regno < NUM_REGS - NUM_FREGS; regno++)
! store_register (regno);
}
+ #endif
+
/* NOTE! I tried using PTRACE_READDATA, etc., to read and write memory
in the NEW_SUN_PTRACE case.