* partial-stab.h: Remove GDB_TARGET_IS_HPPA kludge.
[deliverable/binutils-gdb.git] / gdb / nlm / gdbserve.c
index 3c364c8995c9a2b89388f1fc565e62d9442d2a62..62adf3a8d1bc75470c4263ecc249ade6d2131017 100644 (file)
@@ -1,4 +1,4 @@
-/* i386-nlmstub.c -- NLM debugging stub for the i386.
+/* gdbserve.c -- NLM debugging stub for Novell NetWare.
 
    This is originally based on an m68k software stub written by Glenn
    Engel at HP, but has changed quite a bit.  It was modified for the
@@ -6,10 +6,10 @@
    NetWare by Ian Lance Taylor, Cygnus Support.
 
    This code is intended to produce an NLM (a NetWare Loadable Module)
-   to run under NetWare on an i386 platform.  To create the NLM,
-   compile this code into an object file using the NLM SDK on any i386
-   host, and use the nlmconv program (available in the GNU binutils)
-   to transform the resulting object file into an NLM.  */
+   to run under Novell NetWare.  To create the NLM, compile this code
+   into an object file using the NLM SDK on any i386 host, and use the
+   nlmconv program (available in the GNU binutils) to transform the
+   resulting object file into an NLM.  */
 
 /****************************************************************************
 
  *
  ****************************************************************************/
 
-#include <nwdfs.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-/*#include <ctype.h>*/
+#include <ctype.h>
+#include <errno.h>
 #include <time.h>
-/*#include <aio.h>*/
+
+#ifdef __i386__
+#include <dfs.h>
+#include <conio.h>
+#include <advanced.h>
+#include <debugapi.h>
+#include <process.h>
+#else
+#include <nwtypes.h>
+#include <nwdfs.h>
 #include <nwconio.h>
 #include <nwadv.h>
 #include <nwdbgapi.h>
-/*#include <process.h>*/
-#include <errno.h>
 #include <nwthread.h>
-#include "alpha-patch.h"
+#endif
+
+#include <aio.h>
+#include "cpu.h"
+
 
 /****************************************************/
 /* This information is from Novell.  It is not in any of the standard
@@ -107,20 +118,20 @@ struct DBG_LoadDefinitionStructure
 #define LO_AUTO_LOAD           0x0008
 
 /* Loader returned error codes */
-#define LOAD_COULD_NOT_FIND_FILE                       1
-#define LOAD_ERROR_READING_FILE                                2
-#define LOAD_NOT_NLM_FILE_FORMAT                       3
-#define LOAD_WRONG_NLM_FILE_VERSION                    4
+#define LOAD_COULD_NOT_FIND_FILE               1
+#define LOAD_ERROR_READING_FILE                        2
+#define LOAD_NOT_NLM_FILE_FORMAT               3
+#define LOAD_WRONG_NLM_FILE_VERSION            4
 #define LOAD_REENTRANT_INITIALIZE_FAILURE      5
 #define LOAD_CAN_NOT_LOAD_MULTIPLE_COPIES      6
-#define LOAD_ALREADY_IN_PROGRESS                       7
-#define LOAD_NOT_ENOUGH_MEMORY                         8
-#define LOAD_INITIALIZE_FAILURE                                9
+#define LOAD_ALREADY_IN_PROGRESS               7
+#define LOAD_NOT_ENOUGH_MEMORY                 8
+#define LOAD_INITIALIZE_FAILURE                        9
 #define LOAD_INCONSISTENT_FILE_FORMAT          10
 #define LOAD_CAN_NOT_LOAD_AT_STARTUP           11
 #define LOAD_AUTO_LOAD_MODULES_NOT_LOADED      12
-#define LOAD_UNRESOLVED_EXTERNAL                       13
-#define LOAD_PUBLIC_ALREADY_DEFINED                    14
+#define LOAD_UNRESOLVED_EXTERNAL               13
+#define LOAD_PUBLIC_ALREADY_DEFINED            14
 /****************************************************/
 
 /* The main thread ID.  */
@@ -142,23 +153,14 @@ static int remote_debug = 1;
 
 static const char hexchars[] = "0123456789abcdef";
 
-/* Register values.  All of these values *MUST* agree with tm.h */
-#define RA_REGNUM 26           /* Contains return address value */
-#define SP_REGNUM 30           /* Contains address of top of stack */
-#define PC_REGNUM 64           /* Contains program counter */
-#define FP_REGNUM 65           /* Virtual frame pointer */
-#define V0_REGNUM 0            /* Function integer return value */
-#define NUM_REGS 66            /* Number of machine registers */
-#define REGISTER_BYTES (NUM_REGS * 8) /* Total size of registers array */
+unsigned char breakpoint_insn[] = BREAKPOINT;
 
-/*#define flush_i_cache() asm("call_pal 0x86")*/
+char *mem2hex (void *mem, char *buf, int count, int may_fault);
+char *hex2mem (char *buf, void *mem, int count, int may_fault);
+extern void set_step_traps (struct StackFrame *);
+extern void clear_step_traps (struct StackFrame *);
 
-static char *mem2hex (void *mem, char *buf, int count, int may_fault);
-static char *hex2mem (char *buf, void *mem, int count, int may_fault);
-
-#if 0
-__main() {};
-#endif
+static int __main() {};
 
 /* Read a character from the serial port.  This must busy wait, but
    that's OK because we will be the only thread running anyhow.  */
@@ -205,30 +207,6 @@ putDebugChar (c)
   return 1;
 }
 
-/* Get the registers out of the frame information.  */
-
-static void
-frame_to_registers (frame, regs)
-     struct StackFrame *frame;
-     char *regs;
-{
-  mem2hex (&frame->ExceptionRegs[SF_REG_PC], &regs[PC_REGNUM * 8 * 2], 8 * 1, 0);
-
-  mem2hex (&frame->ExceptionRegs[SF_IREG_OFFSET], &regs[V0_REGNUM * 8 * 2], 8 * 64, 0);
-}
-
-/* Put the registers back into the frame information.  */
-
-static void
-registers_to_frame (regs, frame)
-     char *regs;
-     struct StackFrame *frame;
-{
-  hex2mem (&regs[PC_REGNUM * 8 * 2], &frame->ExceptionRegs[SF_REG_PC], 8 * 1, 0);
-
-  hex2mem (&regs[V0_REGNUM * 8 * 2], &frame->ExceptionRegs[SF_IREG_OFFSET], 8 * 64, 0);
-}
-
 /* Turn a hex character into a number.  */
 
 static int
@@ -395,48 +373,36 @@ static int mem_may_fault;
 
 /* Indicate to caller of mem2hex or hex2mem that there has been an
    error.  */
-static volatile int mem_err = 0;
+volatile int mem_err = 0;
 
+#ifndef ALTERNATE_MEM_FUNCS
 /* These are separate functions so that they are so short and sweet
    that the compiler won't save any registers (if there is a fault
    to mem_fault, they won't get restored, so there better not be any
    saved).  */
 
-static int
+int
 get_char (addr)
      char *addr;
 {
   return *addr;
 }
 
-static void
+void
 set_char (addr, val)
      char *addr;
      int val;
 {
   *addr = val;
 }
-
-/* This bit of assembly language just returns from a function.  If a
-   memory error occurs within get_char or set_char, the debugger
-   handler points EIP at these instructions to get out.  */
-
-extern void just_return ();
-#if 0
-asm (".globl just_return");
-asm (".globl _just_return");
-asm ("just_return:");
-asm ("_just_return:");
-asm ("leave");
-asm ("ret");
-#endif
+#endif /* ALTERNATE_MEM_FUNCS */
 
 /* convert the memory pointed to by mem into hex, placing result in buf */
 /* return a pointer to the last char put in buf (null) */
 /* If MAY_FAULT is non-zero, then we should set mem_err in response to
    a fault; if zero treat a fault like any other fault in the stub.  */
 
-static char *
+char *
 mem2hex (mem, buf, count, may_fault)
      void *mem;
      char *buf;
@@ -464,7 +430,7 @@ mem2hex (mem, buf, count, may_fault)
 /* convert the hex array pointed to by buf into binary to be placed in mem */
 /* return a pointer to the character AFTER the last byte written */
 
-static char *
+char *
 hex2mem (buf, mem, count, may_fault)
      char *buf;
      void *mem;
@@ -491,7 +457,7 @@ hex2mem (buf, mem, count, may_fault)
 /* This function takes the 386 exception vector and attempts to
    translate this number into a unix compatible signal value.  */
 
-static int
+int
 computeSignal (exceptionVector)
      int exceptionVector;
 {
@@ -550,132 +516,6 @@ hexToInt(ptr, intValue)
   return (numChars);
 }
 
-union inst
-{
-  LONG l;
-
-  struct
-    {
-      union
-       {
-         struct
-           {
-             unsigned hint : 16;
-             unsigned rb : 5;
-             unsigned ra : 5;
-             unsigned opcode : 6;
-           } jump;
-         struct
-           {
-             signed disp : 21;
-             unsigned ra : 5;
-             unsigned opcode : 6;
-           } branch;
-       } variant;
-    } inst;
-};
-
-static LONG saved_inst;
-static LONG *saved_inst_pc = 0;
-static LONG saved_target_inst;
-static LONG *saved_target_inst_pc = 0;
-
-static void
-set_step_breakpoint (pc, frame)
-     LONG *pc;
-     struct StackFrame *frame;
-{
-  union inst inst;
-  LONG *target;
-  int opcode;
-  int ra, rb;
-
-  inst.l = *pc++;
-
-  opcode = inst.inst.variant.branch.opcode;
-
-  if ((opcode & 0x30) == 0x30) /* A branch of some sort */
-    target = inst.inst.variant.branch.disp + pc;
-  else if (opcode == 0x1a)     /* jmp, ret, etc... */
-    target = (LONG *)(frame->ExceptionRegs[SF_IREG_OFFSET
-                                          + inst.inst.variant.jump.rb].lo
-                     & ~3);
-  else
-    target = pc;
-
-  saved_inst = *pc;
-  *pc = 0x80;                  /* call_pal bpt */
-  saved_inst_pc = pc;
-
-  if (target != pc)
-    {
-      saved_target_inst = *target;
-      *target = 0x80;          /* call_pal bpt */
-      saved_target_inst_pc = target;
-    }
-}
-
-/* Remove step breakpoints.  Returns non-zero if pc was at a step breakpoint,
-   zero otherwise.  This routine works even if there were no step breakpoints
-   set.  */
-
-static int
-clear_step_breakpoint (pc)
-     LONG *pc;
-{
-  int retcode;
-
-  if (saved_inst_pc == pc || saved_target_inst_pc == pc)
-    retcode = 1;
-  else
-    retcode = 0;
-
-  if (saved_inst_pc)
-    {
-      *saved_inst_pc = saved_inst;
-      saved_inst_pc = 0;
-    }
-
-  if (saved_target_inst_pc)
-    {
-      *saved_target_inst_pc = saved_target_inst;
-      saved_target_inst_pc = 0;
-    }
-
-  return retcode;
-}
-
-static void
-do_status (ptr, frame)
-     char *ptr;
-     struct StackFrame *frame;
-{
-  int sigval;
-
-  sigval = computeSignal (frame->ExceptionNumber);
-
-  sprintf (ptr, "T%02x", sigval);
-  ptr += 3;
-
-  sprintf (ptr, "%02x:", PC_REGNUM);
-  ptr = mem2hex (&frame->ExceptionRegs[SF_REG_PC], ptr + 3, 8, 0);
-  *ptr++ = ';';
-
-  sprintf (ptr, "%02x:", SP_REGNUM);
-  ptr = mem2hex (&frame->ExceptionRegs[SF_IREG_OFFSET + SP_REGNUM], ptr + 3, 8, 0);
-  *ptr++ = ';';
-
-  sprintf (ptr, "%02x:", RA_REGNUM);
-  ptr = mem2hex (&frame->ExceptionRegs[SF_IREG_OFFSET + RA_REGNUM], ptr + 3, 8, 0);
-  *ptr++ = ';';
-
-  sprintf (ptr, "%02x:", FP_REGNUM);
-  ptr = mem2hex (&frame->ExceptionRegs[SF_IREG_OFFSET + FP_REGNUM], ptr + 3, 8, 0);
-  *ptr++ = ';';
-
-  *ptr = '\000';
-}
-
 /* This function does all command processing for interfacing to gdb.
    It is called whenever an exception occurs in the module being
    debugged.  */
@@ -687,18 +527,22 @@ handle_exception (frame)
   int addr, length;
   char *ptr;
   static struct DBG_LoadDefinitionStructure *ldinfo = 0;
-  static LONG first_insn;      /* The first instruction in the program.  */
+  static unsigned char first_insn[BREAKPOINT_SIZE]; /* The first instruction in the program.  */
+
+#if 0
+  /* According to some documentation from Novell, the bell sometimes
+     may be ringing at this point.  This can be stopped on Netware 4
+     systems by calling the undocumented StopBell() function. */
 
-  /* Apparently the bell can sometimes be ringing at this point, and
-     should be stopped.  */
   StopBell ();
+#endif
 
   if (remote_debug)
     {
       ConsolePrintf ("vector=%d: %s, pc=%08x, thread=%08x\r\n",
                     frame->ExceptionNumber,
                     frame->ExceptionDescription,
-                    frame->ExceptionRegs[SF_REG_PC].lo,
+                    frame->ExceptionPC,
                     GetThreadID ());
     }
 
@@ -711,8 +555,10 @@ handle_exception (frame)
 
       ldinfo = ((struct DBG_LoadDefinitionStructure *)
                frame->ExceptionErrorCode);
-      first_insn = *(LONG *)ldinfo->LDInitializationProcedure;
-      *(LONG *)ldinfo->LDInitializationProcedure = 0x80; /* call_pal bpt */
+      memcpy (first_insn, ldinfo->LDInitializationProcedure,
+             BREAKPOINT_SIZE);
+      memcpy (ldinfo->LDInitializationProcedure, breakpoint_insn,
+             BREAKPOINT_SIZE);
       flush_i_cache ();
       return RETURN_TO_PROGRAM;
 
@@ -724,10 +570,13 @@ handle_exception (frame)
 
     case 3:                    /* Breakpoint */
       /* After we've reached the initial breakpoint, reset it.  */
-      if (frame->ExceptionRegs[SF_REG_PC].lo == (LONG) ldinfo->LDInitializationProcedure
-         && *(LONG *) ldinfo->LDInitializationProcedure == 0x80)
+      if (frame->ExceptionPC - DECR_PC_AFTER_BREAK == (LONG) ldinfo->LDInitializationProcedure
+         && memcmp (ldinfo->LDInitializationProcedure, breakpoint_insn,
+                    BREAKPOINT_SIZE) == 0)
        {
-         *(LONG *) ldinfo->LDInitializationProcedure = first_insn;
+         memcpy (ldinfo->LDInitializationProcedure, first_insn,
+                 BREAKPOINT_SIZE);
+         frame->ExceptionPC -= DECR_PC_AFTER_BREAK;
          flush_i_cache ();
        }
       /* Normal breakpoints end up here */
@@ -751,16 +600,16 @@ handle_exception (frame)
         instruction pointer is near set_char or get_char, then we caused
         the fault ourselves accessing an illegal memory location.  */
       if (mem_may_fault
-         && ((frame->ExceptionRegs[SF_REG_PC].lo >= (long) &set_char
-              && frame->ExceptionRegs[SF_REG_PC].lo < (long) &set_char + 50)
-             || (frame->ExceptionRegs[SF_REG_PC].lo >= (long) &get_char
-                 && frame->ExceptionRegs[SF_REG_PC].lo < (long) &get_char + 50)))
+         && ((frame->ExceptionPC >= (long) &set_char
+              && frame->ExceptionPC < (long) &set_char + 50)
+             || (frame->ExceptionPC >= (long) &get_char
+                 && frame->ExceptionPC < (long) &get_char + 50)))
        {
          mem_err = 1;
          /* Point the instruction pointer at an assembly language stub
             which just returns from the function.  */
 
-         frame->ExceptionRegs[SF_REG_PC].lo += 4; /* Skip the load or store */
+         frame->ExceptionPC += 4; /* Skip the load or store */
 
          /* Keep going.  This will act as though it returned from
             set_char or get_char.  The calling routine will check
@@ -782,7 +631,7 @@ handle_exception (frame)
      the range of the module we are debugging, but that doesn't help
      much since an error could occur in a library routine.  */
 
-  clear_step_breakpoint (frame->ExceptionRegs[SF_REG_PC]);
+  clear_step_traps (frame);
 
   if (! putpacket(remcomOutBuffer))
     return RETURN_TO_NEXT_DEBUGGER;
@@ -887,7 +736,7 @@ handle_exception (frame)
            }
 
          if (remcomInBuffer[0] == 's')
-           set_step_breakpoint (frame->ExceptionRegs[SF_REG_PC].lo);
+           set_step_traps (frame);
 
          flush_i_cache ();
          return RETURN_TO_PROGRAM;
@@ -917,13 +766,40 @@ handle_exception (frame)
     }
 }
 
-char *baudRates[] = { "50", "75", "110", "134.5", "150", "300", "600", "1200",
-                       "1800", "2000", "2400", "3600", "4800", "7200", "9600",
-                       "19200", "38400", "57600", "115200" };
+char *progname;
 
-char dataBits[] = "5678";
+struct bitRate {
+  BYTE bitRate;
+  const char *bitRateString;
+};
 
-char *stopBits[] = { "1", "1.5", "2" };
+struct bitRate bitRateTable[] = 
+{
+  { AIO_BAUD_50    ,      "50" },
+  { AIO_BAUD_75    ,      "75" },
+  { AIO_BAUD_110   ,     "110" },
+  { AIO_BAUD_134p5 ,   "134.5" },
+  { AIO_BAUD_150   ,     "150" },
+  { AIO_BAUD_300   ,     "300" },
+  { AIO_BAUD_600   ,     "600" },
+  { AIO_BAUD_1200  ,    "1200" },
+  { AIO_BAUD_1800  ,    "1800" },
+  { AIO_BAUD_2000  ,    "2000" },
+  { AIO_BAUD_2400  ,    "2400" },
+  { AIO_BAUD_3600  ,    "3600" },
+  { AIO_BAUD_4800  ,    "4800" },
+  { AIO_BAUD_7200  ,    "7200" },
+  { AIO_BAUD_9600  ,    "9600" },
+  { AIO_BAUD_19200 ,   "19200" },
+  { AIO_BAUD_38400 ,   "38400" },
+  { AIO_BAUD_57600 ,   "57600" },
+  { AIO_BAUD_115200,  "115200" },
+  { -1, NULL }
+};
+
+char dataBitsTable[] = "5678";
+
+char *stopBitsTable[] = { "1", "1.5", "2" };
 
 char parity[] = "NOEMS";
 
@@ -939,30 +815,107 @@ main (argc, argv)
      char **argv;
 {
   int hardware, board, port;
+  BYTE bitRate;
+  BYTE dataBits;
+  BYTE stopBits;
+  BYTE parityMode;
   LONG err;
   struct debuggerStructure s;
+  int cmdindx;
   char *cmdlin;
   int i;
 
-/* Use the -B option to invoke the NID if you want to debug the stub. */
+  /* set progname */
+  progname = "gdbserve";
 
-  if (argc > 1 && strcmp(argv[1], "-B") == 0)
+  /* set default serial line */
+  hardware = -1;
+  board = 0;
+  port = 0;
+
+  /* set default serial line characteristics */
+  bitRate  = AIO_BAUD_9600;
+  dataBits = AIO_DATA_BITS_8;
+  stopBits = AIO_STOP_BITS_1;
+  parityMode = AIO_PARITY_NONE;
+
+  cmdindx = 0;
+  for (argc--, argv++; *argv; argc--, argv++) 
     {
-      Breakpoint(argc);
-      ++argv, --argc;
+      char *bp;
+      char *ep;
+
+      if (strnicmp(*argv, "BAUD=", 5) == 0) 
+       {
+         struct bitRate *brp;
+
+         bp = *argv + 5;
+         for (brp = bitRateTable; brp->bitRate != (BYTE) -1; brp++) 
+           {
+             if (strcmp(brp->bitRateString, bp) == 0) 
+               {
+                 bitRate = brp->bitRate;
+                 break;
+               }
+           }
+
+         if (brp->bitRateString == NULL) 
+           {
+             fprintf(stderr, "%s: %s: unknown or unsupported bit rate",
+                     progname, bp);
+             exit (1);
+           }
+       }
+      else if (strnicmp(*argv, "BOARD=", 6) == 0) 
+        {
+         bp = *argv + 6;
+         board = strtol (bp, &ep, 0);
+         if (ep == bp || *ep != '\0') 
+           {
+             fprintf (stderr, "%s: %s: expected integer argument\n", 
+                      progname, bp);
+             exit(1);
+           }
+       }
+#if 1                          /* FIXME: this option has been depricated */
+      else if (strnicmp(*argv, "NODE=", 5) == 0)
+       {
+         bp = *argv + 5;
+         board = strtol (bp, &ep, 0);
+         if (ep == bp || *ep != '\0') 
+           {
+             fprintf (stderr, "%s: %s: expected integer argument\n", 
+                      progname, bp);
+             exit(1);
+           }
+       }
+#endif
+      else if (strnicmp(*argv, "PORT=", 5) == 0)
+       {
+         bp = *argv + 5;
+         port = strtol (bp, &ep, 0);
+         if (ep == bp || *ep != '\0')
+           {
+             fprintf (stderr, "%s: %s: expected integer argument\n", 
+                      progname, bp);
+             exit(1);
+           }
+       }
+      else
+       {
+         break;
+       }
+
+      cmdindx++;
     }
 
-  if (argc < 4)
+  if (argc == 0)
     {
       fprintf (stderr,
-              "Usage: load gdbserve board port program [arguments]\n");
+              "Usage: load %s [options] program [arguments]\n", progname);
       exit (1);
     }
 
-  hardware = -1;
-  board = strtol (argv[1], (char **) NULL, 0);
-  port = strtol (argv[2], (char **) NULL, 0);
-
   err = AIOAcquirePort (&hardware, &board, &port, &AIOhandle);
   if (err != AIO_SUCCESS)
     {
@@ -985,23 +938,24 @@ main (argc, argv)
       exit (1);
     }
 
-  err = AIOConfigurePort (AIOhandle, AIO_BAUD_9600, AIO_DATA_BITS_8,
-                         AIO_STOP_BITS_1, AIO_PARITY_NONE,
+  err = AIOConfigurePort (AIOhandle, bitRate, dataBits, stopBits, parityMode,
                          AIO_HARDWARE_FLOW_CONTROL_OFF);
 
   if (err == AIO_QUALIFIED_SUCCESS)
     {
       AIOPORTCONFIG portConfig;
-      AIODVRCONFIG dvrConfig;
 
       fprintf (stderr, "Port configuration changed!\n");
-      AIOGetPortConfiguration (AIOhandle, &portConfig, &dvrConfig);
+
+      portConfig.returnLength = sizeof(portConfig);
+      AIOGetPortConfiguration (AIOhandle, &portConfig, NULL);
+
       fprintf (stderr,
               "  Bit Rate: %s, Data Bits: %c, Stop Bits: %s, Parity: %c,\
  Flow:%s\n",
-              baudRates[portConfig.bitRate],
-              dataBits[portConfig.dataBits],
-              stopBits[portConfig.stopBits],
+              bitRateTable[portConfig.bitRate].bitRateString,
+              dataBitsTable[portConfig.dataBits],
+              stopBitsTable[portConfig.stopBits],
               parity[portConfig.parityMode],
               portConfig.flowCtrlMode ? "ON" : "OFF");
     }
@@ -1050,7 +1004,7 @@ main (argc, argv)
   /* Get the command line we were invoked with, and advance it past
      our name and the board and port arguments.  */
   cmdlin = getcmd ((char *) NULL);
-  for (i = 0; i < 2; i++)
+  for (i = 0; i < cmdindx; i++)
     {
       while (! isspace (*cmdlin))
        ++cmdlin;
This page took 0.031637 seconds and 4 git commands to generate.