Allow for the possibility that the local labels won't be in the objdump output.
[deliverable/binutils-gdb.git] / gdb / go32-nat.c
index 0c133bc3e257afb4e5dcfaca244699df551cf103..dffc5d959b90727fe14cac5feaa20ad87ea010b8 100644 (file)
@@ -1,5 +1,5 @@
 /* Native debugging support for Intel x86 running DJGPP.
-   Copyright 1997, 1999 Free Software Foundation, Inc.
+   Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
    Written by Robert Hoehne.
 
    This file is part of GDB.
 #include <fcntl.h>
 
 #include "defs.h"
-#include "frame.h"             /* required by inferior.h */
 #include "inferior.h"
-#include "target.h"
-#include "wait.h"
+#include "gdb_wait.h"
 #include "gdbcore.h"
 #include "command.h"
 #include "floatformat.h"
+#include "buildsym.h"
+#include "i387-nat.h"
+#include "value.h"
+#include "regcache.h"
+#include "gdb_string.h"
 
 #include <stdio.h>             /* required for __DJGPP_MINOR__ */
 #include <stdlib.h>
-#include <string.h>
 #include <errno.h>
 #include <unistd.h>
 #include <io.h>
@@ -119,52 +121,36 @@ typedef struct {
   int redirected;
 } cmdline_t;
 
-void redir_cmdline_delete (cmdline_t *ptr) {ptr->redirected = 0;}
-int  redir_cmdline_parse (const char *args, cmdline_t *ptr)
+void
+redir_cmdline_delete (cmdline_t *ptr) {ptr->redirected = 0;}
+
+int
+redir_cmdline_parse (const char *args, cmdline_t *ptr)
 {
   return -1;
 }
-int redir_to_child (cmdline_t *ptr)
+int
+redir_to_child (cmdline_t *ptr)
 {
   return 1;
 }
-int redir_to_debugger (cmdline_t *ptr)
+int
+redir_to_debugger (cmdline_t *ptr)
 {
   return 1;
 }
-int redir_debug_init (cmdline_t *ptr) { return 0; }
+int
+redir_debug_init (cmdline_t *ptr) { return 0; }
 #endif /* __DJGPP_MINOR < 3 */
 
-extern void _initialize_go32_nat (void);
-
-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];
-  };
-
 typedef enum { wp_insert, wp_remove, wp_count } wp_op;
 
 /* This holds the current reference counts for each debug register.  */
 static int dr_ref_count[4];
 
-extern char **environ;
-
 #define SOME_PID 42
 
 static int prog_has_started = 0;
-static void print_387_status (unsigned short status, struct env387 *ep);
 static void go32_open (char *name, int from_tty);
 static void go32_close (int quitting);
 static void go32_attach (char *args, int from_tty);
@@ -176,114 +162,21 @@ static void store_register (int regno);
 static void go32_store_registers (int regno);
 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);
+                            int write,
+                            struct mem_attrib *attrib,
+                            struct target_ops *target);
 static void go32_files_info (struct target_ops *target);
 static void go32_stop (void);
 static void go32_kill_inferior (void);
 static void go32_create_inferior (char *exec_file, char *args, char **env);
-static void cleanup_dregs (void);
 static void go32_mourn_inferior (void);
 static int go32_can_run (void);
-static void ignore (void);
-static void ignore2 (char *a, int b);
-static int go32_insert_aligned_watchpoint (CORE_ADDR waddr, CORE_ADDR addr,
-                                          int len, int rw);
-static int go32_remove_aligned_watchpoint (CORE_ADDR waddr, CORE_ADDR addr,
-                                          int len, int rw);
-static int go32_handle_nonaligned_watchpoint (wp_op what, CORE_ADDR waddr,
-                                             CORE_ADDR addr, int len, int rw);
 
 static struct target_ops go32_ops;
 static void go32_terminal_init (void);
 static void go32_terminal_inferior (void);
 static void go32_terminal_ours (void);
 
-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);
-  /* Other platforms say "last exception", but that's not true: the
-     FPU stores the last non-control instruction there.  */
-  printf_unfiltered ("last FP instruction: ");
-  /* The ORing with D800h restores the upper 5 bits of the opcode that
-     are not stored by the FPU (since these bits are the same for all
-     floating-point instructions).  */
-  printf_unfiltered ("opcode %s; ",
-                    local_hex_string (ep->opcode ? (ep->opcode|0xd800) : 0));
-  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 = 7; fpreg >= 0; fpreg--)
-    {
-      /* FNSAVE saves the FP registers in their logical TOP-relative
-        order, beginning with ST(0).  Since we need to print them in
-        their physical order, we have to remap them.  */
-      int  regno = fpreg - top;
-      long double val;
-
-      if (regno < 0)
-       regno += 8;
-
-      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:
-         /* All other versions of print_387_status use TRAP here, but I
-            think this is misleading, since Intel manuals say SPECIAL.  */
-         printf_unfiltered ("special ");
-         break;
-       case 3:
-         printf_unfiltered ("empty   ");
-         break;
-       }
-      for (i = 9; i >= 0; i--)
-       printf_unfiltered ("%02x", ep->regs[regno][i]);
-
-      REGISTER_CONVERT_TO_VIRTUAL (FP0_REGNUM+regno, builtin_type_long_double,
-                                  &ep->regs[regno], &val);
-
-      printf_unfiltered ("  %.19LG\n", val);
-    }
-}
-
-void
-i386_go32_float_info (void)
-{
-  print_387_status (0, (struct env387 *) &npx);
-}
-
 #define r_ofs(x) (offsetof(TSS,x))
 
 static struct
@@ -293,95 +186,96 @@ static struct
 }
 regno_mapping[] =
 {
-  r_ofs (tss_eax), 4,  /* normal registers, from a_tss */
-    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,             /* 8 FP registers, from npx.reg[] */
-    1, 10,
-    2, 10,
-    3, 10,
-    4, 10,
-    5, 10,
-    6, 10,
-    7, 10,
+  {r_ofs (tss_eax), 4},        /* normal registers, from a_tss */
+  {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},             /* 8 FP registers, from npx.reg[] */
+  {1, 10},
+  {2, 10},
+  {3, 10},
+  {4, 10},
+  {5, 10},
+  {6, 10},
+  {7, 10},
        /* The order of the next 7 registers must be consistent
-          with their numbering in config/i386/tm-go32.h, which see.  */
-  0, 2,                        /* control word, from npx */
-  4, 2,                        /* status word, from npx */
-  8, 2,                        /* tag word, from npx */
-  16, 2,               /* last FP exception CS from npx */
-  24, 2,               /* last FP exception operand selector from npx */
-  12, 4,               /* last FP exception EIP from npx */
-  20, 4                        /* last FP exception operand offset from npx */
+          with their numbering in config/i386/tm-i386.h, which see.  */
+  {0, 2},              /* control word, from npx */
+  {4, 2},              /* status word, from npx */
+  {8, 2},              /* tag word, from npx */
+  {16, 2},             /* last FP exception CS from npx */
+  {12, 4},             /* last FP exception EIP from npx */
+  {24, 2},             /* last FP exception operand selector from npx */
+  {20, 4},             /* last FP exception operand offset from npx */
+  {18, 2}              /* last FP opcode from npx */
 };
 
 static struct
   {
     int go32_sig;
-    int gdb_sig;
+    enum target_signal gdb_sig;
   }
 sig_map[] =
 {
-  0, TARGET_SIGNAL_FPE,
-    1, TARGET_SIGNAL_TRAP,
+  {0, TARGET_SIGNAL_FPE},
+  {1, TARGET_SIGNAL_TRAP},
   /* Exception 2 is triggered by the NMI.  DJGPP handles it as SIGILL,
      but I think SIGBUS is better, since the NMI is usually activated
      as a result of a memory parity check failure.  */
-    2, TARGET_SIGNAL_BUS,
-    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_SEGV,
-    14, TARGET_SIGNAL_SEGV,
-    16, TARGET_SIGNAL_FPE,
-    17, TARGET_SIGNAL_BUS,
-    31, TARGET_SIGNAL_ILL,
-    0x1b, TARGET_SIGNAL_INT,
-    0x75, TARGET_SIGNAL_FPE,
-    0x78, TARGET_SIGNAL_ALRM,
-    0x79, TARGET_SIGNAL_INT,
-    0x7a, TARGET_SIGNAL_QUIT,
-    -1, -1
+  {2, TARGET_SIGNAL_BUS},
+  {3, TARGET_SIGNAL_TRAP},
+  {4, TARGET_SIGNAL_FPE},
+  {5, TARGET_SIGNAL_SEGV},
+  {6, TARGET_SIGNAL_ILL},
+  {7, TARGET_SIGNAL_EMT},      /* no-coprocessor exception */
+  {8, TARGET_SIGNAL_SEGV},
+  {9, TARGET_SIGNAL_SEGV},
+  {10, TARGET_SIGNAL_BUS},
+  {11, TARGET_SIGNAL_SEGV},
+  {12, TARGET_SIGNAL_SEGV},
+  {13, TARGET_SIGNAL_SEGV},
+  {14, TARGET_SIGNAL_SEGV},
+  {16, TARGET_SIGNAL_FPE},
+  {17, TARGET_SIGNAL_BUS},
+  {31, TARGET_SIGNAL_ILL},
+  {0x1b, TARGET_SIGNAL_INT},
+  {0x75, TARGET_SIGNAL_FPE},
+  {0x78, TARGET_SIGNAL_ALRM},
+  {0x79, TARGET_SIGNAL_INT},
+  {0x7a, TARGET_SIGNAL_QUIT},
+  {-1, TARGET_SIGNAL_LAST}
 };
 
 static struct {
   enum target_signal gdb_sig;
   int djgpp_excepno;
 } excepn_map[] = {
-  TARGET_SIGNAL_0, -1,
-  TARGET_SIGNAL_ILL, 6,                /* Invalid Opcode */
-  TARGET_SIGNAL_EMT, 7,                /* triggers SIGNOFP */
-  TARGET_SIGNAL_SEGV, 13,      /* GPF */
-  TARGET_SIGNAL_BUS, 17,       /* Alignment Check */
+  {TARGET_SIGNAL_0, -1},
+  {TARGET_SIGNAL_ILL, 6},      /* Invalid Opcode */
+  {TARGET_SIGNAL_EMT, 7},      /* triggers SIGNOFP */
+  {TARGET_SIGNAL_SEGV, 13},    /* GPF */
+  {TARGET_SIGNAL_BUS, 17},     /* Alignment Check */
   /* The rest are fake exceptions, see dpmiexcp.c in djlsr*.zip for
      details.  */
-  TARGET_SIGNAL_TERM, 0x1b,    /* triggers Ctrl-Break type of SIGINT */
-  TARGET_SIGNAL_FPE, 0x75,
-  TARGET_SIGNAL_INT, 0x79,
-  TARGET_SIGNAL_QUIT, 0x7a,
-  TARGET_SIGNAL_ALRM, 0x78,    /* triggers SIGTIMR */
-  TARGET_SIGNAL_PROF, 0x78,
-  -1, -1
+  {TARGET_SIGNAL_TERM, 0x1b},  /* triggers Ctrl-Break type of SIGINT */
+  {TARGET_SIGNAL_FPE, 0x75},
+  {TARGET_SIGNAL_INT, 0x79},
+  {TARGET_SIGNAL_QUIT, 0x7a},
+  {TARGET_SIGNAL_ALRM, 0x78},  /* triggers SIGTIMR */
+  {TARGET_SIGNAL_PROF, 0x78},
+  {TARGET_SIGNAL_LAST, -1}
 };
 
 static void
@@ -420,7 +314,8 @@ go32_resume (int pid, int step, enum target_signal siggnal)
 
   if (siggnal != TARGET_SIGNAL_0 && siggnal != TARGET_SIGNAL_TRAP)
   {
-    for (i = 0, resume_signal = -1; excepn_map[i].gdb_sig != -1; i++)
+    for (i = 0, resume_signal = -1;
+        excepn_map[i].gdb_sig != TARGET_SIGNAL_LAST; i++)
       if (excepn_map[i].gdb_sig == siggnal)
       {
        resume_signal = excepn_map[i].djgpp_excepno;
@@ -439,7 +334,7 @@ go32_wait (int pid, struct target_waitstatus *status)
 {
   int i;
   unsigned char saved_opcode;
-  unsigned long INT3_addr;
+  unsigned long INT3_addr = 0;
   int stepping_over_INT = 0;
 
   a_tss.tss_eflags &= 0xfeff;  /* reset the single-step flag (TF) */
@@ -494,6 +389,13 @@ go32_wait (int pid, struct target_waitstatus *status)
      point of changing back to where GDB thinks is its cwd, when we
      return control to the debugger, but restore child's cwd before we
      run it.  */
+  /* Initialize child_cwd, before the first call to run_child and not
+     in the initialization, so the child get also the changed directory
+     set with the gdb-command "cd ..." */
+  if (!*child_cwd)
+    /* Initialize child's cwd with the current one.  */
+    getcwd (child_cwd, sizeof (child_cwd));
+
   chdir (child_cwd);
 
 #if __DJGPP_MINOR__ < 3
@@ -546,31 +448,27 @@ go32_wait (int pid, struct target_waitstatus *status)
 }
 
 static void
-go32_fetch_registers (int regno)
+fetch_register (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 */
-      /* # regs in table */
-      end_reg = sizeof (regno_mapping) / sizeof (regno_mapping[0]);
-    }
+  if (regno < FP0_REGNUM)
+    supply_register (regno, (char *) &a_tss + regno_mapping[regno].tss_ofs);
+  else if (regno <= LAST_FPU_CTRL_REGNUM)
+    i387_supply_register (regno, (char *) &npx);
+  else
+    internal_error (__FILE__, __LINE__,
+                   "Invalid register no. %d in fetch_register.", regno);
+}
 
-  for (; regno < end_reg; regno++)
+static void
+go32_fetch_registers (int regno)
+{
+  if (regno >= 0)
+    fetch_register (regno);
+  else
     {
-      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 + regno_mapping[regno].tss_ofs);
-      else
-       fatal ("Invalid register no. %d in go32_fetch_register.", regno);
+      for (regno = 0; regno < FP0_REGNUM; regno++)
+       fetch_register (regno);
+      i387_supply_fsave ((char *) &npx);
     }
 }
 
@@ -578,30 +476,30 @@ 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;
+  void *v = (void *) register_buffer (regno);
+
+  if (regno < FP0_REGNUM)
+    memcpy ((char *) &a_tss + regno_mapping[regno].tss_ofs,
+           v, regno_mapping[regno].size);
+  else if (regno <= LAST_FPU_CTRL_REGNUM)
+    i387_fill_fsave ((char *)&npx, regno);
   else
-    fatal ("Invalid register no. %d in store_register.", regno);
-  memcpy (rp, v, regno_mapping[regno].size);
+    internal_error (__FILE__, __LINE__,
+                   "Invalid register no. %d in store_register.", regno);
 }
 
 static void
 go32_store_registers (int regno)
 {
-  int r;
+  unsigned r;
 
   if (regno >= 0)
     store_register (regno);
   else
     {
-      for (r = 0; r < sizeof (regno_mapping) / sizeof (regno_mapping[0]); r++)
+      for (r = 0; r < FP0_REGNUM; r++)
        store_register (r);
+      i387_fill_fsave ((char *) &npx, -1);
     }
 }
 
@@ -612,7 +510,7 @@ go32_prepare_to_store (void)
 
 static int
 go32_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
-                 struct target_ops *target)
+                 struct mem_attrib *attrib, struct target_ops *target)
 {
   if (write)
     {
@@ -667,10 +565,16 @@ go32_kill_inferior (void)
 static void
 go32_create_inferior (char *exec_file, char *args, char **env)
 {
+  extern char **environ;
   jmp_buf start_state;
   char *cmdline;
   char **env_save = environ;
 
+  /* If no exec file handed to us, get it from the exec-file command -- with
+     a good, common error message if none is specified.  */
+  if (exec_file == 0)
+    exec_file = get_exec_file (1);
+
   if (prog_has_started)
     {
       go32_stop ();
@@ -678,9 +582,15 @@ go32_create_inferior (char *exec_file, char *args, char **env)
     }
   resume_signal = -1;
   resume_is_step = 0;
+
+  /* Initialize child's cwd as empty to be initialized when starting
+     the child.  */
+  *child_cwd = 0;
+
   /* Init command line storage.  */
   if (redir_debug_init (&child_cmd) == -1)
-    fatal ("Cannot allocate redirection storage: not enough memory.\n");
+    internal_error (__FILE__, __LINE__,
+                   "Cannot allocate redirection storage: not enough memory.\n");
 
   /* Parse the command line and create redirections.  */
   if (strpbrk (args, "<>"))
@@ -691,7 +601,7 @@ go32_create_inferior (char *exec_file, char *args, char **env)
        error ("Syntax error in command line.");
     }
   else
-    child_cmd.command = strdup (args);
+    child_cmd.command = xstrdup (args);
 
   cmdline = (char *) alloca (strlen (args) + 4);
   cmdline[0] = strlen (args);
@@ -717,7 +627,7 @@ go32_create_inferior (char *exec_file, char *args, char **env)
   push_target (&go32_ops);
   clear_proceed_status ();
   insert_breakpoints ();
-  proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
+  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
   prog_has_started = 1;
 }
 
@@ -731,7 +641,7 @@ go32_mourn_inferior (void)
      be nice if GDB itself would take care to remove all breakpoints
      at all times, but it doesn't, probably under an assumption that
      the OS cleans up when the debuggee exits.  */
-  cleanup_dregs ();
+  i386_cleanup_dregs ();
   go32_kill_inferior ();
   generic_mourn_inferior ();
 }
@@ -742,411 +652,42 @@ go32_can_run (void)
   return 1;
 }
 
-static void
-ignore (void)
-{
-}
-
 /* Hardware watchpoint support.  */
 
-#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_READWRITE 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 RESET_LOCAL_EXACT() \
-   (CONTROL &= ~(DR_LOCAL_SLOWDOWN))
-
-#define RESET_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 IS_WATCH(index) \
-  (CONTROL & (DR_CONTROL_MASK << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE*(index))))
-
-#define WATCH_HIT(index) \
-  (\
-   (STATUS & (1 << index)) && \
-   (CONTROL & (DR_CONTROL_MASK << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * index)))\
-  )
-
-#define DR_DEF(index) \
-  ((CONTROL >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (index))) & 0x0f)
-    
-
-#if 0 /* use debugging macro */
-#define SHOW_DR(text,len) \
-do { \
-  if (!getenv ("GDB_SHOW_DR")) break; \
-  fprintf(stderr,"%08x %08x ",edi.dr[7],edi.dr[6]); \
-  fprintf(stderr,"%08x %d %08x %d ", \
-         edi.dr[0],dr_ref_count[0],edi.dr[1],dr_ref_count[1]); \
-  fprintf(stderr,"%08x %d %08x %d ", \
-         edi.dr[2],dr_ref_count[2],edi.dr[3],dr_ref_count[3]); \
-  fprintf(stderr,(len)?"(%s:%d)\n":"(%s)\n",#text,len); \
-} while (0)
-#else
-#define SHOW_DR(text,len) do {} while (0)
-#endif
-
-static void
-cleanup_dregs (void)
-{
-  int i;
-
-  CONTROL = 0;
-  STATUS = 0;
-  for (i = 0; i < 4; i++)
-    {
-      D_REGS[i] = 0;
-      dr_ref_count[i] = 0;
-    }
-}
-
-/* Insert a watchpoint.  */
-
-int
-go32_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
-{
-  int ret = go32_insert_aligned_watchpoint (addr, addr, len, rw);
-
-  SHOW_DR (insert_watch, len);
-  return ret;
-}
-
-static int
-go32_insert_aligned_watchpoint (CORE_ADDR waddr, CORE_ADDR addr,
-                               int len, int rw)
-{
-  int i;
-  int read_write_bits, len_bits;
+#define CONTROL D_REGS[7]
+#define STATUS D_REGS[6]
 
-  /* Values of rw: 0 - write, 1 - read, 2 - access (read and write).
-     However, x86 doesn't support read-only data breakpoints.  */
-  read_write_bits = rw ? DR_RW_READWRITE : DR_RW_WRITE;
-
-  switch (len)
-  {
-  case 4:
-    len_bits = DR_LEN_4;
-    break;
-  case 2:
-    len_bits = DR_LEN_2;
-    break;
-  case 1:
-    len_bits = DR_LEN_1;
-    break;
-  default:
-    /* The debug registers only have 2 bits for the length, so
-       so this value will always fail the loop below.  */
-    len_bits = 0x10;
-  }
-
-  /* Look for an occupied debug register with the same address and the
-     same RW and LEN definitions.  If we find one, we can use it for
-     this watchpoint as well (and save a register).  */
-  for (i = 0; i < 4; i++)
-  {
-    if (!IS_REG_FREE (i) && D_REGS[i] == addr
-       && DR_DEF (i) == (len_bits | read_write_bits))
-    {
-      dr_ref_count[i]++;
-      return 0;
-    }
-  }
-
-  /* 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;
-
-  if (len == 2)
-  {
-    if (addr % 2)
-      return go32_handle_nonaligned_watchpoint (wp_insert, waddr, addr,
-                                               len, rw);
-  }
-  else if (len == 4)
-  {
-    if (addr % 4)
-      return go32_handle_nonaligned_watchpoint (wp_insert, waddr, addr,
-                                               len, rw);
-  }
-  else if (len != 1)
-    return go32_handle_nonaligned_watchpoint (wp_insert, waddr, addr, len, rw);
-
-  SET_WATCH (i, addr, read_write_bits, len_bits);
-  LOCAL_ENABLE_REG (i);
-  SET_LOCAL_EXACT ();
-  SET_GLOBAL_EXACT ();
-  return 0;
-}
-
-static int
-go32_handle_nonaligned_watchpoint (wp_op what, CORE_ADDR waddr, CORE_ADDR addr,
-                                  int len, int rw)
-{
-  int align;
-  int size;
-  int rv = 0, status = 0;
-
-  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 */
-  };
-
-  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];
-      if (what == wp_insert)
-       status = go32_insert_aligned_watchpoint (waddr, addr, size, rw);
-      else if (what == wp_remove)
-       status = go32_remove_aligned_watchpoint (waddr, addr, size, rw);
-      else if (what == wp_count)
-       rv++;
-      else
-       status = -1;
-      /* We keep the loop going even after a failure, because some of
-        the other aligned watchpoints might still succeed, e.g. if
-        they watch addresses that are already watched, and thus just
-        increment the reference counts of occupied debug registers.
-        If we break out of the loop too early, we could cause those
-        addresses watched by other watchpoints to be disabled when
-        GDB reacts to our failure to insert this watchpoint and tries
-        to remove it.  */
-      if (status)
-       rv = status;
-      addr += size;
-      len -= size;
-    }
-  return rv;
-}
-
-/* Remove a watchpoint.  */
-
-int
-go32_remove_watchpoint (int pid, CORE_ADDR addr, int len, int rw)
-{
-  int ret = go32_remove_aligned_watchpoint (addr, addr, len, rw);
-
-  SHOW_DR (remove_watch, len);
-  return ret;
-}
-
-static int
-go32_remove_aligned_watchpoint (CORE_ADDR waddr, CORE_ADDR addr,
-                               int len, int rw)
-{
-  int i;
-  int read_write_bits, len_bits;
-
-  /* Values of rw: 0 - write, 1 - read, 2 - access (read and write).
-     However, x86 doesn't support read-only data breakpoints.  */
-  read_write_bits = rw ? DR_RW_READWRITE : DR_RW_WRITE;
-
-  switch (len)
-    {
-      case 4:
-       len_bits = DR_LEN_4;
-       break;
-      case 2:
-       len_bits = DR_LEN_2;
-       break;
-      case 1:
-       len_bits = DR_LEN_1;
-       break;
-      default:
-       /* The debug registers only have 2 bits for the length, so
-          so this value will always fail the loop below.  */
-       len_bits = 0x10;
-    }
-
-  if (len == 2)
-    {
-      if (addr % 2)
-       return go32_handle_nonaligned_watchpoint (wp_remove, waddr, addr,
-                                                 len, rw);
-    }
-  else if (len == 4)
-    {
-      if (addr % 4)
-       return go32_handle_nonaligned_watchpoint (wp_remove, waddr, addr,
-                                                 len, rw);
-    }
-  else if (len != 1)
-    return go32_handle_nonaligned_watchpoint (wp_remove, waddr, addr, len, rw);
-
-  for (i = 0; i <= 3; i++)
-    {
-      if (!IS_REG_FREE (i) && D_REGS[i] == addr
-         && DR_DEF (i) == (len_bits | read_write_bits))
-       {
-         dr_ref_count[i]--;
-         if (dr_ref_count[i] == 0)
-           DISABLE_REG (i);
-       }
-    }
-  RESET_LOCAL_EXACT ();
-  RESET_GLOBAL_EXACT ();
-
-  return 0;
-}
-
-/* Can we use debug registers to watch a region whose address is ADDR
-   and whose length is LEN bytes?  */
-
-int
-go32_region_ok_for_watchpoint (CORE_ADDR addr, int len)
+/* Pass the address ADDR to the inferior in the I'th debug register.
+   Here we just store the address in D_REGS, the watchpoint will be
+   actually set up when go32_wait runs the debuggee.  */
+void
+go32_set_dr (int i, CORE_ADDR addr)
 {
-  /* Compute how many aligned watchpoints we would need to cover this
-     region.  */
-  int nregs = go32_handle_nonaligned_watchpoint (wp_count, addr, addr, len, 0);
-
-  return nregs <= 4 ? 1 : 0;
+  if (i < 0 || i > 3)
+    internal_error (__FILE__, __LINE__, 
+                   "Invalid register %d in go32_set_dr.\n", i);
+  D_REGS[i] = addr;
 }
 
-/* Check if stopped by a data watchpoint.  If so, return the address
-   whose access triggered the watchpoint.  */
-
-CORE_ADDR
-go32_stopped_by_watchpoint (int pid, int data_watchpoint)
+/* Pass the value VAL to the inferior in the DR7 debug control
+   register.  Here we just store the address in D_REGS, the watchpoint
+   will be actually set up when go32_wait runs the debuggee.  */
+void
+go32_set_dr7 (unsigned val)
 {
-  int i, ret = 0;
-  int status;
-
-  status = edi.dr[DR_STATUS];
-  SHOW_DR (stopped_by, 0);
-  for (i = 0; i <= 3; i++)
-    {
-      if (WATCH_HIT (i) && data_watchpoint)
-       {
-         SHOW_DR (WP_HIT, 0);
-         ret = D_REGS[i];
-       }
-    }
-
-  return ret;
+  CONTROL = val;
 }
 
-/* Remove a breakpoint.  */
-
-int
-go32_remove_hw_breakpoint (CORE_ADDR addr, CORE_ADDR shadow)
+/* Get the value of the DR6 debug status register from the inferior.
+   Here we just return the value stored in D_REGS, as we've got it
+   from the last go32_wait call.  */
+unsigned
+go32_get_dr6 (void)
 {
-  int i;
-  for (i = 0; i <= 3; i++)
-    {
-      if (!IS_REG_FREE (i) && D_REGS[i] == addr && DR_DEF (i) == 0)
-       {
-         dr_ref_count[i]--;
-         if (dr_ref_count[i] == 0)
-           DISABLE_REG (i);
-       }
-    }
-  SHOW_DR (remove_hw, 0);
-  return 0;
+  return STATUS;
 }
 
-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 an occupied debug register with the same address and the
-     same RW and LEN definitions.  If we find one, we can use it for
-     this breakpoint as well (and save a register).  */
-  for (i = 0; i < 4; i++)
-    {
-      if (!IS_REG_FREE (i) && D_REGS[i] == addr && DR_DEF (i) == 0)
-       {
-         dr_ref_count[i]++;
-         SHOW_DR (insert_hw, 0);
-         return 0;
-       }
-    }
-
-  /* Look for a free debug register.  */
-  for (i = 0; i <= 3; i++)
-    {
-      if (IS_REG_FREE (i))
-       break;
-    }
-
-  /* No more debug registers?  */
-  if (i < 4)
-    {
-      SET_BREAK (i, addr);
-      LOCAL_ENABLE_REG (i);
-    }
-  SHOW_DR (insert_hw, 0);
-
-  return i < 4 ? 0 : -1;
-}
-
-static int inf_flags_valid = 0;
-static int inf_in_flag;
-static int inf_out_flag;
-
 /* Put the device open on handle FD into either raw or cooked
    mode, return 1 if it was in raw mode, zero otherwise.  */
 
@@ -1313,12 +854,17 @@ init_go32_ops (void)
   go32_ops.to_has_execution = 1;
   go32_ops.to_magic = OPS_MAGIC;
 
-  /* Initialize child's cwd with the current one.  */
-  getcwd (child_cwd, sizeof (child_cwd));
+  /* Initialize child's cwd as empty to be initialized when starting
+     the child.  */
+  *child_cwd = 0;
 
   /* Initialize child's command line storage.  */
   if (redir_debug_init (&child_cmd) == -1)
-    fatal ("Cannot allocate redirection storage: not enough memory.\n");
+    internal_error (__FILE__, __LINE__,
+                   "Cannot allocate redirection storage: not enough memory.\n");
+
+  /* We are always processing GCC-compiled programs.  */
+  processing_gcc_compilation = 2;
 }
 
 void
This page took 0.035818 seconds and 4 git commands to generate.