This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project. See the GDB home page for more information.


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

Native DJGPP (go32) support for gdb 4.17


That's now a patch to make in gdb the native support
for DJGPP available. This big patch consits of patching
multiple files which deals mainly with the configuring
things and the main source file go32-nat.c. This is a
new file which handles all the native debugging support
for DJGPP. Naming it go32-nat.c and not djgpp-nat.c has
historical reasons. It is tested already in many cases,
since we (the DJGPP people) used most of it already in
our DJGPP port of gdb 4.16 and I added now also some
gdb 4.17 new features.

The patches for configure.host configure.tgt enable now
the use of the new go32 target which is selected by the
main configure script.

here now the Changelog entry for directory gdb-4.17/gdb:

Mon Jan 10 1999 Robert Hoehne (robert.hoehne@gmx.net)

        * configure.host: Add the go32 host
        * configure.tgt: Add the go32 target
        * go32-nat.c: new file for the native DJGPP support
        * config/i386/go32.mh: completely rewritten for the DJGPP (go32)
        host
        * config/i386/go32.mt: new file for the DJGPP (go32) target
        * config/i386/nm-go32.h: new file
        * config/i386/tm-go32.h: new file
        * config/i386/xm-go32.h: completely rewritten


Robert
-- 
******************************************************
* email:   Robert Hoehne <robert.hoehne@gmx.net>     *
* Post:    Am Berg 3, D-09573 Dittmannsdorf, Germany *
* WWW:     http://www.tu-chemnitz.de/~sho/rho        *
******************************************************


and now the patch (all is against the gdb 4.17 version)

Index: gdb-4.17/gdb/configure.host
===================================================================
RCS file: Q:/gnu/gdb-4.17/gdb/configure.host,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 configure.host
--- gdb/configure.host	1998-10-06 09:16:13+00	1.1.1.1
+++ gdb/configure.host	1998-10-06 10:19:04+00
@@ -54,6 +54,7 @@
 i[3456]86-*-freebsd*)	gdb_host=fbsd ;;
 i[3456]86-*-netbsd*)	gdb_host=nbsd ;;
 i[3456]86-*-go32*)	gdb_host=go32 ;;
+i[3456]86-*-msdosdjgpp*) gdb_host=go32 ;;
 i[3456]86-*-linux*)	gdb_host=linux ;;
 i[3456]86-*-lynxos*)	gdb_host=i386lynx ;;
 i[3456]86-*-mach3*)	gdb_host=i386m3 ;;
Index: gdb-4.17/gdb/configure.tgt
===================================================================
RCS file: Q:/gnu/gdb-4.17/gdb/configure.tgt,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 configure.tgt
--- gdb/configure.tgt	1998-10-06 09:16:13+00	1.1.1.1
+++ gdb/configure.tgt	1998-10-06 10:19:50+00
@@ -88,6 +88,7 @@
 i[3456]86-*-netbsd*)	gdb_target=nbsd ;;
 i[3456]86-*-os9k)	gdb_target=i386os9k ;;
 i[3456]86-*-go32*)	gdb_target=i386aout ;;
+i[3456]86-*-msdosdjgpp*) gdb_target=go32 ;;
 i[3456]86-*-lynxos*)	gdb_target=i386lynx
 		configdirs="${configdirs} gdbserver" ;;
 i[3456]86-*-solaris*)	gdb_target=i386sol2 ;;
Index: gdb-4.17/gdb/go32-nat.c
===================================================================
RCS file: go32-nat.c
diff -N go32-nat.c
--- /dev/null	Sun Jan 10 21:39:50 1999
+++ go32-nat.c	Sun Jan 10 21:38:04 1999
@@ -0,0 +1,715 @@
+/* Target-vector operations for controlling DJGPP processes, for GDB.
+   Copyright 1997 Free Software Foundation, Inc.
+   Written by Robert Hoehne
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <fcntl.h>
+
+#include "defs.h"
+#include "frame.h"  /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "floatformat.h"
+
+extern char **environ;
+
+/* Forward declaration */
+extern struct target_ops go32_ops;
+
+#define SOME_PID 42
+
+static int prog_has_started = 0;
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <debug/v2load.h>
+#include <debug/dbgcom.h>
+
+struct env387
+{
+  unsigned short control;
+  unsigned short r0;
+  unsigned short status;
+  unsigned short r1;
+  unsigned short tag;
+  unsigned short r2;
+  unsigned long eip;
+  unsigned short code_seg;
+  unsigned short opcode;
+  unsigned long operand;
+  unsigned short operand_seg;
+  unsigned short r3;
+  unsigned char regs[8][10];
+};
+
+static void
+print_387_status (unsigned short status, struct env387 *ep)
+{
+  int i;
+  int bothstatus;
+  int top;
+  int fpreg;
+  
+  bothstatus = ((status != 0) && (ep->status != 0));
+  if (status != 0) 
+    {
+      if (bothstatus)
+        printf_unfiltered ("u: ");
+      print_387_status_word (status);
+    }
+  
+  if (ep->status != 0) 
+    {
+      if (bothstatus)
+        printf_unfiltered ("e: ");
+      print_387_status_word (ep->status);
+    }
+  
+  print_387_control_word (ep->control & 0xffff);
+  printf_unfiltered ("last exception: ");
+  printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
+  printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
+  printf_unfiltered ("%s; ", local_hex_string(ep->eip));
+  printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
+  printf_unfiltered (":%s\n", local_hex_string(ep->operand));
+
+  top = (ep->status >> 11) & 7;
+  
+  printf_unfiltered ("regno tag   msb          lsb  value\n");
+  for (fpreg = 0; fpreg < 8; fpreg++)
+    {
+      long double val;
+      
+      printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : "  ", fpreg); 
+
+      switch ((ep->tag >> (fpreg * 2)) & 3) 
+        {
+        case 0: printf_unfiltered ("valid "); break;
+        case 1: printf_unfiltered ("zero  "); break;
+        case 2: printf_unfiltered ("trap  "); break;
+        case 3: printf_unfiltered ("empty "); break;
+        }
+      for (i = 0; i < 8; i++)
+        printf_unfiltered ("%02x", ep->regs[fpreg][i]);
+
+      REGISTER_CONVERT_TO_VIRTUAL(FP0_REGNUM+fpreg, builtin_type_long_double,
+                                  &ep->regs[fpreg], &val);
+                                  
+      printf_unfiltered ("  %LG\n", val);
+    }
+}
+
+void
+i386_go32_float_info ()
+{
+  print_387_status (0, (struct env387 *)&npx);
+}
+
+#define r_ofs(x) ((int)(&(((TSS *)0)->x)))
+static struct {
+  int tss_ofs;
+  int size;
+} regno_mapping[] = {
+  r_ofs(tss_eax), 4,
+  r_ofs(tss_ecx), 4,
+  r_ofs(tss_edx), 4,
+  r_ofs(tss_ebx), 4,
+  r_ofs(tss_esp), 4,
+  r_ofs(tss_ebp), 4,
+  r_ofs(tss_esi), 4,
+  r_ofs(tss_edi), 4,
+  r_ofs(tss_eip), 4,
+  r_ofs(tss_eflags), 4,
+  r_ofs(tss_cs), 2,
+  r_ofs(tss_ss), 2,
+  r_ofs(tss_ds), 2,
+  r_ofs(tss_es), 2,
+  r_ofs(tss_fs), 2,
+  r_ofs(tss_gs), 2,
+  0, 10,
+  1, 10,
+  2, 10,
+  3, 10,
+  4, 10,
+  5, 10,
+  6, 10,
+  7, 10,
+  0, 2,
+  4, 2,
+  8, 2,
+  12, 4,
+  16, 2,
+  20, 4,
+  24, 2
+};
+
+static struct {
+  int go32_sig;
+  int gdb_sig;
+} sig_map[] = {
+  0, TARGET_SIGNAL_FPE,
+  1, TARGET_SIGNAL_TRAP,
+  2, TARGET_SIGNAL_UNKNOWN,
+  3, TARGET_SIGNAL_TRAP,
+  4, TARGET_SIGNAL_FPE,
+  5, TARGET_SIGNAL_SEGV,
+  6, TARGET_SIGNAL_ILL,
+  7, TARGET_SIGNAL_FPE,
+  8, TARGET_SIGNAL_SEGV,
+  9, TARGET_SIGNAL_SEGV,
+  10, TARGET_SIGNAL_BUS,
+  11, TARGET_SIGNAL_SEGV,
+  12, TARGET_SIGNAL_SEGV,
+  13, TARGET_SIGNAL_ABRT,
+  14, TARGET_SIGNAL_SEGV,
+  16, TARGET_SIGNAL_FPE,
+  31, TARGET_SIGNAL_ILL,
+0x75, TARGET_SIGNAL_FPE,
+0x79, TARGET_SIGNAL_INT,
+0x1b, TARGET_SIGNAL_INT,
+  -1,-1
+};
+
+static void
+go32_open(char *name, int from_tty)
+{
+  printf_unfiltered("Use the `run' command to run go32 programs\n");
+}
+
+static void
+go32_close(int quitting)
+{
+  /*printf_unfiltered("go32_close called\n");*/
+}
+
+static void
+go32_attach(char *args, int from_tty)
+{
+  printf_unfiltered("Use the `run' command to run go32 programs\n");
+}
+
+static void
+go32_detach(char *args, int from_tty)
+{
+  /*printf_unfiltered("go32_detach called\n");*/
+}
+
+static int resume_is_step;
+
+static void
+go32_resume(int pid, int step, enum target_signal siggnal)
+{
+  resume_is_step = step;
+}
+
+static int
+go32_wait(int pid, struct target_waitstatus *status)
+{
+  if (resume_is_step)
+    a_tss.tss_eflags |= 0x0100;
+  else
+    a_tss.tss_eflags &= 0xfeff;
+  run_child();
+  if (a_tss.tss_irqn == 0x21)
+  {
+    status->kind = TARGET_WAITKIND_EXITED;
+    status->value.integer = a_tss.tss_eax & 0xff;
+  }
+  else
+  {
+    int i;
+    status->value.sig = TARGET_SIGNAL_UNKNOWN;
+    status->kind = TARGET_WAITKIND_STOPPED;
+    for (i=0; sig_map[i].go32_sig != -1; i++)
+    {
+      if (a_tss.tss_irqn == sig_map[i].go32_sig)
+      {
+        if ( (status->value.sig = sig_map[i].gdb_sig) !=
+            TARGET_SIGNAL_TRAP)
+          status->kind = TARGET_WAITKIND_SIGNALLED;
+        break;
+      }
+    }
+  }
+  return SOME_PID;
+}
+
+static void
+go32_fetch_registers(int regno)
+{
+/*JHW*/
+  int end_reg=regno+1;  /*just one reg initially*/
+  if (regno < 0)        /*do the all registers*/
+  {
+    regno=0;   /*start at first register*/
+    end_reg=sizeof(regno_mapping)/sizeof(regno_mapping[0]);    /*# regs in table*/
+  }
+  for (; regno<end_reg; regno++)
+  {
+    if (regno < 16)
+      supply_register(regno, (char *)&a_tss + regno_mapping[regno].tss_ofs);
+    else if (regno < 24)
+      supply_register(regno, (char *)&npx.reg[regno_mapping[regno].tss_ofs]);
+    else if (regno < 31)
+      supply_register(regno, (char *)&npx.reg+ regno_mapping[regno].tss_ofs);
+    else /*unknown register size*/
+    {
+      printf_unfiltered("Invalid register in go32_fetch_register(%d)", regno);
+      exit(1);
+    }
+  }
+}
+
+static void
+store_register(int regno)
+{
+  void *rp;
+  void *v = (void *)&registers[REGISTER_BYTE(regno)];
+  if (regno < 16)
+    rp = (char *)&a_tss + regno_mapping[regno].tss_ofs;
+  else if (regno < 24)
+    rp = (char *)&npx.reg[regno_mapping[regno].tss_ofs];
+  else if (regno > 31)
+    rp = (char *)&npx + regno_mapping[regno].tss_ofs;
+  else
+  {
+    printf_unfiltered("Invalid register in store_register(%d)", regno);
+    exit(1);
+  }
+  memcpy(rp, v, regno_mapping[regno].size);
+}
+
+static void
+go32_store_registers(int regno)
+{
+  if (regno >= 0)
+    store_register(regno);
+  else
+  {
+    int r;
+    for (r=0; r<sizeof(regno_mapping)/sizeof(regno_mapping[0]); r++)
+      store_register(r);
+  }
+}
+
+static void
+go32_prepare_to_store(void)
+{
+}
+
+static int
+go32_xfer_memory(CORE_ADDR memaddr, char *myaddr, int len, int write,
+                 struct target_ops *target)
+{
+  if (write)
+  {
+    if (write_child(memaddr, myaddr, len))
+    {
+      return(0);
+    }
+    else
+    {
+      return(len);
+    }
+  }
+  else
+  {
+    if (read_child(memaddr, myaddr, len))
+    {
+      return(0);
+    }
+    else
+    {
+      return(len);
+    }
+  }
+}
+
+static void
+go32_files_info(struct target_ops *target)
+{
+  printf_unfiltered("You are running a DJGPP V2 program\n");
+}
+
+static void go32_stop()
+{
+  normal_stop();
+  cleanup_client();
+  inferior_pid = 0;
+  prog_has_started = 0;
+}
+
+static void
+go32_kill_inferior(void)
+{
+  go32_stop();
+  unpush_target(&go32_ops);
+}
+
+extern char **environ;
+
+static void
+go32_create_inferior(char *exec_file, char *args, char **env)
+{
+  jmp_buf start_state;
+  char *cmdline;
+  char **env_save = environ;
+  if (prog_has_started)
+  {
+    go32_kill_inferior();
+  }
+
+  cmdline = (char *)alloca(strlen(args)+4);
+  cmdline[0] = strlen(args);
+  strcpy(cmdline+1, args);
+  cmdline[strlen(args)+1] = 13;
+
+  environ = env;
+
+  if (v2loadimage(exec_file, cmdline, start_state))
+  {
+    environ = env_save;
+    printf_unfiltered("Load failed for image %s\n", exec_file);
+    exit(1);
+  }
+  environ = env_save;
+
+  edi_init(start_state);
+
+  inferior_pid = SOME_PID;
+  push_target(&go32_ops);
+  clear_proceed_status();
+  insert_breakpoints();
+  proceed((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
+}
+
+static void
+go32_mourn_inferior(void)
+{
+  go32_kill_inferior();
+  generic_mourn_inferior();
+}
+
+static int go32_can_run(void)
+{
+  return 1;
+}
+
+static void ignore(void) {}
+static void ignore2(char *a,int b) {}
+
+struct target_ops go32_ops = {
+  "djgpp",                      /* to_shortname */
+  "djgpp target process",       /* to_longname */
+  "Program loaded by djgpp, when gdb is used as an external debugger",  /* to_doc */
+  go32_open,                    /* to_open */
+  go32_close,                   /* to_close */
+  go32_attach,                  /* to_attach */
+  go32_detach,                  /* to_detach */
+  go32_resume,                  /* to_resume */
+  go32_wait,                    /* to_wait */
+  go32_fetch_registers,         /* to_fetch_registers */
+  go32_store_registers,         /* to_store_registers */
+  go32_prepare_to_store,        /* to_prepare_to_store */
+  go32_xfer_memory,             /* to_xfer_memory */
+  go32_files_info,              /* to_files_info */
+  memory_insert_breakpoint,     /* to_insert_breakpoint */
+  memory_remove_breakpoint,     /* to_remove_breakpoint */
+  ignore,                       /* to_terminal_init */
+  ignore,                       /* to_terminal_inferior */
+  ignore,                       /* to_terminal_ours_for_output */
+  ignore,                       /* to_terminal_ours */
+  ignore2,                      /* to_terminal_info */
+  go32_kill_inferior,           /* to_kill */
+  0,                            /* to_load */
+  0,                            /* to_lookup_symbol */
+  go32_create_inferior,         /* to_create_inferior */
+  go32_mourn_inferior,          /* to_mourn_inferior */
+  go32_can_run,                 /* to_can_run */
+  0,                            /* to_notice_signals */
+  0,                            /* to_thread_alive */
+  go32_stop,                    /* to_stop */
+  process_stratum,              /* to_stratum */
+  0,                            /* to_next */
+  1,                            /* to_has_all_memory */
+  1,                            /* to_has_memory */
+  1,                            /* to_has_stack */
+  1,                            /* to_has_registers */
+  1,                            /* to_has_execution */
+  0,                            /* sections */
+  0,                            /* sections_end */
+  OPS_MAGIC                     /* to_magic */
+};
+
+void
+_initialize_inftarg ()
+{
+  add_target (&go32_ops);
+}
+
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+
+#define DR_STATUS 6
+#define DR_CONTROL 7
+#define DR_ENABLE_SIZE 2
+#define DR_LOCAL_ENABLE_SHIFT 0
+#define DR_GLOBAL_ENABLE_SHIFT 1
+#define DR_LOCAL_SLOWDOWN 0x100
+#define DR_GLOBAL_SLOWDOWN 0x200
+#define DR_CONTROL_SHIFT 16
+#define DR_CONTROL_SIZE 4
+#define DR_RW_READ 0x3
+#define DR_RW_WRITE 0x1
+#define DR_CONTROL_MASK 0xf
+#define DR_ENABLE_MASK 0x3
+#define DR_LEN_1 0x0
+#define DR_LEN_2 0x4
+#define DR_LEN_4 0xc
+
+#define D_REGS edi.dr
+#define CONTROL D_REGS[DR_CONTROL]
+#define STATUS D_REGS[DR_STATUS]
+
+#define IS_REG_FREE(index) \
+  (!(CONTROL & (3 << (DR_ENABLE_SIZE * index))))
+#define LOCAL_ENABLE_REG(index) \
+  (CONTROL |= (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * index)))
+#define GLOBAL_ENABLE_REG(index) \
+  (CONTROL |= (1 << (DR_GLOBAL_ENABLE_SHIFT + DR_ENABLE_SIZE * index)))
+#define DISABLE_REG(index) \
+  (CONTROL &= ~(3 << (DR_ENABLE_SIZE * index)))
+#define SET_LOCAL_EXACT() \
+  (CONTROL |= DR_LOCAL_SLOWDOWN)
+#define SET_GLOBAL_EXACT() \
+  (CONTROL |= DR_GLOBAL_SLOWDOWN)
+#define SET_BREAK(index,address) \
+  do {\
+    CONTROL &= ~(DR_CONTROL_MASK << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * index));\
+    D_REGS[index] = address;\
+  } while(0)
+#define SET_WATCH(index,address,rw,len) \
+  do {\
+    SET_BREAK(index,address);\
+    CONTROL |= (len | rw) << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * index);\
+  } while (0)
+  
+#define WATCH_HIT(index) \
+  (\
+   (STATUS & (1 << index)) && \
+   (CONTROL & (DR_CONTROL_MASK << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * index)))\
+  )
+
+static int
+go32_insert_aligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
+                                           int));
+
+static int
+go32_insert_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
+                                           int));
+
+/* Insert a watchpoint.  */
+
+#define SHOW_DR(text) \
+do {\
+  fprintf(stderr,"%08x %08x ",edi.dr[7],edi.dr[6]);\
+  fprintf(stderr,"%08x %08x ",edi.dr[0],edi.dr[1]);\
+  fprintf(stderr,"%08x %08x ",edi.dr[2],edi.dr[3]);\
+  fprintf(stderr,"(%s)\n",#text);\
+} while (0)
+
+#define _SHOW_DR(x) do {} while(0)
+
+int
+go32_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
+{
+  int ret = go32_insert_aligned_watchpoint (pid, addr, addr, len, rw);
+_SHOW_DR(insert_watch);
+  return ret;
+}
+
+static int
+go32_insert_aligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr,
+                                int len, int rw)
+{
+  int i;
+  int read_write_bits, len_bits;
+  
+  /* Look for a free debug register.  */
+  for (i = 0; i <= 3; i++)
+  {
+    if (IS_REG_FREE(i))
+      break;
+  }
+
+  /* No more debug registers!  */
+  if (i > 3)
+    return -1;
+
+  read_write_bits = ((rw & 1) ? DR_RW_READ : 0) | ((rw & 2) ? DR_RW_WRITE : 0);
+
+  if (len == 1)
+    len_bits = DR_LEN_1;
+  else if (len == 2)
+  {
+    if (addr % 2)
+      return go32_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+    len_bits = DR_LEN_2;
+  }
+
+  else if (len == 4)
+  {
+    if (addr % 4)
+      return go32_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+    len_bits = DR_LEN_4;
+  }
+
+  else
+    return go32_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+  
+  SET_WATCH(i,addr,read_write_bits,len_bits);
+  LOCAL_ENABLE_REG(i);
+  SET_LOCAL_EXACT();
+}
+
+static int
+go32_insert_nonaligned_watchpoint (int pid, CORE_ADDR waddr, CORE_ADDR addr,
+                                   int len, int rw)
+{
+  int align;
+  int size;
+  int rv;
+
+  static int size_try_array[16] = {
+    1, 1, 1, 1,                 /* trying size one */
+    2, 1, 2, 1,                 /* trying size two */
+    2, 1, 2, 1,                 /* trying size three */
+    4, 1, 2, 1                  /* trying size four */
+  };
+
+  rv = 0;
+  while (len > 0)
+  {
+    align = addr % 4;
+    /* Four is the maximum length for 386.  */
+    size = (len > 4) ? 3 : len - 1;
+    size = size_try_array[size * 4 + align];
+    rv = go32_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
+    if (rv)
+    {
+      go32_remove_watchpoint (pid, waddr, size);
+      return rv;
+    }
+    addr += size;
+    len -= size;
+  }
+  return rv;
+}
+
+/* Remove a watchpoint.  */
+
+int
+go32_remove_watchpoint (int pid, CORE_ADDR addr, int len)
+{
+  int i;
+  for (i = 0; i <= 3; i++)
+  {
+    if (D_REGS[i] == addr)
+    {
+      DISABLE_REG(i);
+    }
+  }
+_SHOW_DR(remove_watch);
+  return 0;
+}
+
+/* Check if stopped by a watchpoint.  */
+
+CORE_ADDR
+go32_stopped_by_watchpoint (int pid)
+{
+  int i,ret=0;
+  int status;
+
+  status = edi.dr[DR_STATUS];
+_SHOW_DR(stopped_by);
+  for (i = 0; i <= 3; i++)
+  {
+    if (WATCH_HIT(i))
+    {
+_SHOW_DR(HIT);
+      ret = D_REGS[i];
+    }
+  }
+/* this is a hack to GDB. If we stopped at a hardware breakpoint,
+   the stop_pc must incremented by DECR_PC_AFTER_BREAK. I tried everything
+   with the DECR_PC_AFTER_HW_BREAK, but nothing works. */
+  if (STATUS && !ret)
+    stop_pc += DECR_PC_AFTER_BREAK;
+  STATUS = 0;
+  return ret;
+}
+
+/* Remove a breakpoint.  */
+
+int
+go32_remove_hw_breakpoint (CORE_ADDR addr, CORE_ADDR shadow)
+{
+  int i;
+  for (i = 0; i <= 3; i++)
+  {
+    if (D_REGS[i] == addr)
+    {
+      DISABLE_REG(i);
+    }
+  }
+_SHOW_DR(remove_hw);
+  return 0;
+}
+
+int
+go32_insert_hw_breakpoint (CORE_ADDR addr, CORE_ADDR shadow)
+{
+  int i;
+  int read_write_bits, len_bits;
+  int free_debug_register;
+  int register_number;
+  
+  /* Look for a free debug register.  */
+  for (i = 0; i <= 3; i++)
+  {
+    if (IS_REG_FREE(i))
+      break;
+  }
+
+  /* No more debug registers!  */
+  if (i > 3)
+    return -1;
+
+  SET_BREAK(i,addr);
+  LOCAL_ENABLE_REG(i);
+_SHOW_DR(insert_hw);
+  return 0;
+}
+
+#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
+
Index: gdb-4.17/gdb/config/i386/go32.mh
===================================================================
RCS file: Q:/gnu/gdb-4.17/gdb/config/i386/go32.mh,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 go32.mh
--- go32.mh	1998-10-06 09:16:45+00	1.1.1.1
+++ go32.mh	1998-10-06 10:16:32+00
@@ -1,9 +1,13 @@
-MH_CFLAGS=-D__GO32__ -D__MSDOS__
-XDEPFILES= go32-xdep.o
+# we don't need mmalloc on DJGPP
+MH_CFLAGS= -DNO_MMALLOC
+MMALLOC=
+MMALLOC_CFLAGS=
+XDEPFILES=
 XM_FILE= xm-go32.h
+NAT_FILE= nm-go32.h
+NATDEPFILES= go32-nat.o
 TERMCAP= 
-HOST_IPC=-DDOS_IPC
+HOST_IPC=
 SER_HARDWIRE= ser-go32.o
-CC=i386-go32-gcc -O2 -fno-omit-frame-pointer
-
-
+CC= gcc
+XM_CLIBS= -ldbg
Index: gdb-4.17/gdb/config/i386/go32.mt
===================================================================
RCS file: go32.mt
diff -N go32.mt
--- /dev/null	Sun Jan 10 21:40:07 1999
+++ go32.mt	Tue Oct  6 11:16:56 1998
@@ -0,0 +1,3 @@
+# Target: Intel 386 run DJGPP
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-go32.h
Index: gdb-4.17/gdb/config/i386/nm-go32.h
===================================================================
RCS file: nm-go32.h
diff -N nm-go32.h
--- /dev/null	Sun Jan 10 21:40:09 1999
+++ nm-go32.h	Sun Jan 10 17:23:44 1999
@@ -0,0 +1,39 @@
+#define NO_PTRACE_H
+
+#include <i386/nm-i386v.h>
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1
+
+/* After a watchpoint trap, the PC points to the instruction after
+   the one that caused the trap.  Therefore we don't need to step over it.
+   But we do need to reset the status register to avoid another trap.  */
+#define HAVE_CONTINUABLE_WATCHPOINT
+
+#define STOPPED_BY_WATCHPOINT(W)  \
+  go32_stopped_by_watchpoint (inferior_pid)
+
+/* Use these macros for watchpoint insertion/removal.  */
+
+#define target_insert_watchpoint(addr, len, type)  \
+  go32_insert_watchpoint (inferior_pid, addr, len, 2)
+
+#define target_remove_watchpoint(addr, len, type)  \
+  go32_remove_watchpoint (inferior_pid, addr, len)
+
+
+#define target_insert_hw_breakpoint(addr, shadow)  \
+  go32_insert_hw_breakpoint(addr, shadow)
+  
+#define target_remove_hw_breakpoint(addr, shadow)  \
+  go32_remove_hw_breakpoint(addr, shadow)
+
+#define DECR_PC_AFTER_HW_BREAK 0
+
+#undef FLOAT_INFO
+#define FLOAT_INFO { i386_go32_float_info(); }
+
+extern void i387_go32_float_info PARAMS ((void));
+
+
Index: gdb-4.17/gdb/config/i386/tm-go32.h
===================================================================
RCS file: tm-go32.h
diff -N tm-go32.h
--- /dev/null	Sun Jan 10 21:40:10 1999
+++ tm-go32.h	Sun Jan 10 19:35:14 1999
@@ -0,0 +1,214 @@
+/* Macro definitions for i386 running under DJGPP.
+   Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+#include "i386/tm-i386v.h"
+
+/* Number of machine registers */
+#undef NUM_FREGS
+#define NUM_FREGS 15
+#undef NUM_REGS
+#define NUM_REGS (16+NUM_FREGS)
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+/* the order of the first 8 registers must match the compiler's 
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "eax",  "ecx",   "edx",  "ebx",  \
+			 "esp",  "ebp",   "esi",  "edi",  \
+			 "eip",  "eflags","cs",   "ss",   \
+			 "ds",   "es",    "fs",   "gs",   \
+			 "st0",  "st1",   "st2",  "st3",  \
+                         "st4",  "st5",   "st6",  "st7",  \
+			 "fctrl","fstat", "ftag", "fcs",  \
+			 "fopsel","fip",  "fopoff" }
+
+#undef FP_REGNUM
+#define FP_REGNUM  5	/* (ebp) Contains address of executing stack frame */
+#undef  SP_REGNUM
+#define SP_REGNUM  4	/* (usp) Contains address of top of stack */
+#undef  PS_REGNUM
+#define PS_REGNUM  9	/* (ps)  Contains processor status */
+#undef  PC_REGNUM
+#define PC_REGNUM  8	/* (eip) Contains program counter */
+#undef  FP0_REGNUM
+#define FP0_REGNUM 16	/* Floating point register 0 */
+#undef  FPC_REGNUM
+#define FPC_REGNUM 24	/* 80387 control register */
+#undef  FPCWD_REGNUM
+#define FPCWD_REGNUM FPC_REGNUM
+#undef  FPSWD_REGNUM
+#define FPSWD_REGNUM 25	/* 80387 status register */
+#undef  FPTWD_REGNUM
+#define FPTWD_REGNUM 26 /* 80387 tag register */
+#undef  FPIPO_REGNUM
+#define FPIPO_REGNUM 29	/* 80387 instruction pointer offset register */
+#undef  FPIPS_REGNUM
+#define FPIPS_REGNUM 27	/* 80387 instruction pointer selector egister */
+#undef  FPOOS_REGNUM
+#define FPOOS_REGNUM 30	/* 80387 operand pointer offset register */
+#undef  FPOPS_REGNUM
+#define FPOPS_REGNUM 28 /* 80387 operand pointer selector register */
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES (10*4 + 6*2 + 8*10 + 5*2 + 2*4)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#undef REGISTER_BYTE
+#define REGBYTE_0  0
+#define REGBYTE_10 (REGBYTE_0+10*4)
+#define REGBYTE_16 (REGBYTE_10+6*2)
+#define REGBYTE_24 (REGBYTE_16+8*10)
+#define REGBYTE_29 (REGBYTE_24+5*2)
+#define REGISTER_BYTE(N) (((N) < 10) ? (N) * 4 : \
+                          (N) < 16 ? REGBYTE_10 +((N) - 10) * 2 : \
+                          (N) < 24 ? REGBYTE_16 +((N) - 16) * 10 : \
+                          (N) < 29 ? REGBYTE_24 +((N) - 24) * 2 : \
+                          REGBYTE_29 + ((N) - 29) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) ((N) < 10 ? 4 : (N) < 16 ? 2 : (N) < 24 ? 10 :\
+                              (N) < 29 ? 2 : 4)
+
+/* Number of bytes of storage in the program's representation
+   for register N. */
+
+#undef REGISTER_VIRTUAL_SIZE
+#define REGISTER_VIRTUAL_SIZE(N) REGISTER_RAW_SIZE(N)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#undef MAX_REGISTER_RAW_SIZE
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#undef MAX_REGISTER_VIRTUAL_SIZE
+#define MAX_REGISTER_VIRTUAL_SIZE 10
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) ((N) < FP0_REGNUM ? 0 :\
+                                 (N) < FPC_REGNUM ? 1 : 0)
+
+#if defined(HAVE_LONG_DOUBLE) && defined(HOST_I386)
+/* The host and target are i386 machines and the compiler supports
+   long doubles. Long doubles on the host therefore have the same
+   layout as a 387 FPU stack register. */
+#undef LD_I387
+#define LD_I387
+#endif
+
+#ifdef LD_I387
+/* Allow floating point numbers to be specified by
+   a raw long double 10 hex bytes number,
+   e.g. 1.0 can be input as 0x3fff8000000000000000
+   */
+extern int i387_hex_long_double_input(char *p, long double *putithere);
+#define HEX_LONG_DOUBLE_INPUT(base,p,len,target) \
+  ((base) == 16 && (len) == 20 \
+   && i387_hex_long_double_input ((p), (target)))
+#endif
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#ifdef LD_I387
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+  if (TYPE == REGISTER_VIRTUAL_TYPE (REGNUM)) \
+    { \
+      memcpy (TO, FROM, TYPE_LENGTH (TYPE)); \
+    } \
+  else \
+    { \
+      long double val = *((long double *)FROM); \
+      store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+    } \
+}
+#else
+/* Convert data from raw format for register REGNUM in buffer FROM
+   to virtual format with type TYPE in buffer TO.  */
+extern void i387_to_double PARAMS ((char *, char *));
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+  double val; \
+  i387_to_double ((FROM), (char *)&val); \
+  store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+#endif
+
+#undef REGISTER_CONVERT_TO_RAW
+#ifdef LD_I387
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+  if (TYPE == REGISTER_VIRTUAL_TYPE (REGNUM)) \
+    { \
+      memcpy (TO, FROM, TYPE_LENGTH (TYPE)); \
+    } \
+  else \
+    { \
+      long double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+      *((long double *)TO) = val; \
+    } \
+}
+#else
+extern void double_to_i387 PARAMS ((char *, char *));
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+  double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+  double_to_i387((char *)&val, (TO)); \
+}
+#endif
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#undef REGISTER_VIRTUAL_TYPE
+#ifdef LD_I387
+#define REGISTER_VIRTUAL_TYPE(N) \
+  ((N < FP0_REGNUM) ? builtin_type_int : \
+   (N < FPC_REGNUM) ? builtin_type_long_double : builtin_type_int)
+#else
+#define REGISTER_VIRTUAL_TYPE(N) \
+  ((N < FP0_REGNUM) ? builtin_type_int : \
+   (N < FPC_REGNUM) ? builtin_type_double : builtin_type_int)
+#endif
+
+#undef TARGET_LONG_DOUBLE_BIT
+#define TARGET_LONG_DOUBLE_BIT 96
+
+#define NAMES_HAVE_UNDERSCORE
+
+
Index: gdb-4.17/gdb/config/i386/xm-go32.h
===================================================================
RCS file: Q:/gnu/gdb-4.17/gdb/config/i386/xm-go32.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 xm-go32.h
--- xm-go32.h	1998-10-06 09:16:49+00	1.1.1.1
+++ xm-go32.h	1999-01-10 17:45:54+00
@@ -1,5 +1,5 @@
-/* Definitions for hosting on GO32, for GDB.
-   Copyright 1991, 1992 Free Software Foundation, Inc.
+/* Definitions for hosting on DJGPP, for GDB.
+   Copyright 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -18,14 +18,17 @@
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #define HOST_BYTE_ORDER LITTLE_ENDIAN
-#include "fopen-bin.h"
 
-/* Define this lseek(n) != nth byte of file */
-#define LSEEK_NOT_LINEAR
+#include "fopen-bin.h"
 
-#define CANT_FORK
+#define GDBINIT_FILENAME "gdb.ini"
 
-#undef QUIT
-#define QUIT  { pollquit(); }
+#define SLASH_P(X) ((X)=='\\' || (X) == '/')
+#define ROOTED_P(X) ((SLASH_P((X)[0]))|| ((X)[1] ==':'))
+#define SLASH_CHAR '/'
+#define SLASH_STRING "/"
+
+#define CRLF_SOURCE_FILES
+#define DIRNAME_SEPARATOR ';'
+#define HOST_I386
 
-#define GDBINIT_FILENAME "gdb.ini"