This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

gdbserver for arm-linux



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 (&registers[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 (&registers[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, &registers[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, &registers[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 *) &registers[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 *) &registers[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 *) &registers[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 *) &registers[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.




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]