OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [go32-nat.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* Native debugging support for Intel x86 running DJGPP.
2
   Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
3
   Written by Robert Hoehne.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 2 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 59 Temple Place - Suite 330,
20
   Boston, MA 02111-1307, USA.  */
21
 
22
#include <fcntl.h>
23
 
24
#include "defs.h"
25
#include "inferior.h"
26
#include "gdb_wait.h"
27
#include "gdbcore.h"
28
#include "command.h"
29
#include "gdbcmd.h"
30
#include "floatformat.h"
31
#include "buildsym.h"
32
#include "i387-tdep.h"
33
#include "i386-tdep.h"
34
#include "value.h"
35
#include "regcache.h"
36
#include "gdb_string.h"
37
 
38
#include <stdio.h>              /* might be required for __DJGPP_MINOR__ */
39
#include <stdlib.h>
40
#include <ctype.h>
41
#include <errno.h>
42
#include <unistd.h>
43
#include <sys/utsname.h>
44
#include <io.h>
45
#include <dos.h>
46
#include <dpmi.h>
47
#include <go32.h>
48
#include <sys/farptr.h>
49
#include <debug/v2load.h>
50
#include <debug/dbgcom.h>
51
#if __DJGPP_MINOR__ > 2
52
#include <debug/redir.h>
53
#endif
54
 
55
#if __DJGPP_MINOR__ < 3
56
/* This code will be provided from DJGPP 2.03 on. Until then I code it
57
   here */
58
typedef struct
59
  {
60
    unsigned short sig0;
61
    unsigned short sig1;
62
    unsigned short sig2;
63
    unsigned short sig3;
64
    unsigned short exponent:15;
65
    unsigned short sign:1;
66
  }
67
NPXREG;
68
 
69
typedef struct
70
  {
71
    unsigned int control;
72
    unsigned int status;
73
    unsigned int tag;
74
    unsigned int eip;
75
    unsigned int cs;
76
    unsigned int dataptr;
77
    unsigned int datasel;
78
    NPXREG reg[8];
79
  }
80
NPX;
81
 
82
static NPX npx;
83
 
84
static void save_npx (void);    /* Save the FPU of the debugged program */
85
static void load_npx (void);    /* Restore the FPU of the debugged program */
86
 
87
/* ------------------------------------------------------------------------- */
88
/* Store the contents of the NPX in the global variable `npx'.  */
89
/* *INDENT-OFF* */
90
 
91
static void
92
save_npx (void)
93
{
94
  asm ("inb    $0xa0, %%al  \n\
95
       testb $0x20, %%al    \n\
96
       jz 1f                \n\
97
       xorb %%al, %%al      \n\
98
       outb %%al, $0xf0     \n\
99
       movb $0x20, %%al     \n\
100
       outb %%al, $0xa0     \n\
101
       outb %%al, $0x20     \n\
102
1:                          \n\
103
       fnsave %0            \n\
104
       fwait "
105
:     "=m" (npx)
106
:                               /* No input */
107
:     "%eax");
108
}
109
 
110
/* *INDENT-ON* */
111
 
112
 
113
/* ------------------------------------------------------------------------- */
114
/* Reload the contents of the NPX from the global variable `npx'.  */
115
 
116
static void
117
load_npx (void)
118
{
119
  asm ("frstor %0":"=m" (npx));
120
}
121
/* ------------------------------------------------------------------------- */
122
/* Stubs for the missing redirection functions.  */
123
typedef struct {
124
  char *command;
125
  int redirected;
126
} cmdline_t;
127
 
128
void
129
redir_cmdline_delete (cmdline_t *ptr)
130
{
131
  ptr->redirected = 0;
132
}
133
 
134
int
135
redir_cmdline_parse (const char *args, cmdline_t *ptr)
136
{
137
  return -1;
138
}
139
 
140
int
141
redir_to_child (cmdline_t *ptr)
142
{
143
  return 1;
144
}
145
 
146
int
147
redir_to_debugger (cmdline_t *ptr)
148
{
149
  return 1;
150
}
151
 
152
int
153
redir_debug_init (cmdline_t *ptr)
154
{
155
  return 0;
156
}
157
#endif /* __DJGPP_MINOR < 3 */
158
 
159
typedef enum { wp_insert, wp_remove, wp_count } wp_op;
160
 
161
/* This holds the current reference counts for each debug register.  */
162
static int dr_ref_count[4];
163
 
164
#define SOME_PID 42
165
 
166
static int prog_has_started = 0;
167
static void go32_open (char *name, int from_tty);
168
static void go32_close (int quitting);
169
static void go32_attach (char *args, int from_tty);
170
static void go32_detach (char *args, int from_tty);
171
static void go32_resume (ptid_t ptid, int step,
172
                         enum target_signal siggnal);
173
static ptid_t go32_wait (ptid_t ptid,
174
                               struct target_waitstatus *status);
175
static void go32_fetch_registers (int regno);
176
static void store_register (int regno);
177
static void go32_store_registers (int regno);
178
static void go32_prepare_to_store (void);
179
static int go32_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
180
                             int write,
181
                             struct mem_attrib *attrib,
182
                             struct target_ops *target);
183
static void go32_files_info (struct target_ops *target);
184
static void go32_stop (void);
185
static void go32_kill_inferior (void);
186
static void go32_create_inferior (char *exec_file, char *args, char **env);
187
static void go32_mourn_inferior (void);
188
static int go32_can_run (void);
189
 
190
static struct target_ops go32_ops;
191
static void go32_terminal_init (void);
192
static void go32_terminal_inferior (void);
193
static void go32_terminal_ours (void);
194
 
195
#define r_ofs(x) (offsetof(TSS,x))
196
 
197
static struct
198
{
199
  size_t tss_ofs;
200
  size_t size;
201
}
202
regno_mapping[] =
203
{
204
  {r_ofs (tss_eax), 4}, /* normal registers, from a_tss */
205
  {r_ofs (tss_ecx), 4},
206
  {r_ofs (tss_edx), 4},
207
  {r_ofs (tss_ebx), 4},
208
  {r_ofs (tss_esp), 4},
209
  {r_ofs (tss_ebp), 4},
210
  {r_ofs (tss_esi), 4},
211
  {r_ofs (tss_edi), 4},
212
  {r_ofs (tss_eip), 4},
213
  {r_ofs (tss_eflags), 4},
214
  {r_ofs (tss_cs), 2},
215
  {r_ofs (tss_ss), 2},
216
  {r_ofs (tss_ds), 2},
217
  {r_ofs (tss_es), 2},
218
  {r_ofs (tss_fs), 2},
219
  {r_ofs (tss_gs), 2},
220
  {0, 10},               /* 8 FP registers, from npx.reg[] */
221
  {1, 10},
222
  {2, 10},
223
  {3, 10},
224
  {4, 10},
225
  {5, 10},
226
  {6, 10},
227
  {7, 10},
228
        /* The order of the next 7 registers must be consistent
229
           with their numbering in config/i386/tm-i386.h, which see.  */
230
  {0, 2},                /* control word, from npx */
231
  {4, 2},               /* status word, from npx */
232
  {8, 2},               /* tag word, from npx */
233
  {16, 2},              /* last FP exception CS from npx */
234
  {12, 4},              /* last FP exception EIP from npx */
235
  {24, 2},              /* last FP exception operand selector from npx */
236
  {20, 4},              /* last FP exception operand offset from npx */
237
  {18, 2}               /* last FP opcode from npx */
238
};
239
 
240
static struct
241
  {
242
    int go32_sig;
243
    enum target_signal gdb_sig;
244
  }
245
sig_map[] =
246
{
247
  {0, TARGET_SIGNAL_FPE},
248
  {1, TARGET_SIGNAL_TRAP},
249
  /* Exception 2 is triggered by the NMI.  DJGPP handles it as SIGILL,
250
     but I think SIGBUS is better, since the NMI is usually activated
251
     as a result of a memory parity check failure.  */
252
  {2, TARGET_SIGNAL_BUS},
253
  {3, TARGET_SIGNAL_TRAP},
254
  {4, TARGET_SIGNAL_FPE},
255
  {5, TARGET_SIGNAL_SEGV},
256
  {6, TARGET_SIGNAL_ILL},
257
  {7, TARGET_SIGNAL_EMT},       /* no-coprocessor exception */
258
  {8, TARGET_SIGNAL_SEGV},
259
  {9, TARGET_SIGNAL_SEGV},
260
  {10, TARGET_SIGNAL_BUS},
261
  {11, TARGET_SIGNAL_SEGV},
262
  {12, TARGET_SIGNAL_SEGV},
263
  {13, TARGET_SIGNAL_SEGV},
264
  {14, TARGET_SIGNAL_SEGV},
265
  {16, TARGET_SIGNAL_FPE},
266
  {17, TARGET_SIGNAL_BUS},
267
  {31, TARGET_SIGNAL_ILL},
268
  {0x1b, TARGET_SIGNAL_INT},
269
  {0x75, TARGET_SIGNAL_FPE},
270
  {0x78, TARGET_SIGNAL_ALRM},
271
  {0x79, TARGET_SIGNAL_INT},
272
  {0x7a, TARGET_SIGNAL_QUIT},
273
  {-1, TARGET_SIGNAL_LAST}
274
};
275
 
276
static struct {
277
  enum target_signal gdb_sig;
278
  int djgpp_excepno;
279
} excepn_map[] = {
280
  {TARGET_SIGNAL_0, -1},
281
  {TARGET_SIGNAL_ILL, 6},       /* Invalid Opcode */
282
  {TARGET_SIGNAL_EMT, 7},       /* triggers SIGNOFP */
283
  {TARGET_SIGNAL_SEGV, 13},     /* GPF */
284
  {TARGET_SIGNAL_BUS, 17},      /* Alignment Check */
285
  /* The rest are fake exceptions, see dpmiexcp.c in djlsr*.zip for
286
     details.  */
287
  {TARGET_SIGNAL_TERM, 0x1b},   /* triggers Ctrl-Break type of SIGINT */
288
  {TARGET_SIGNAL_FPE, 0x75},
289
  {TARGET_SIGNAL_INT, 0x79},
290
  {TARGET_SIGNAL_QUIT, 0x7a},
291
  {TARGET_SIGNAL_ALRM, 0x78},   /* triggers SIGTIMR */
292
  {TARGET_SIGNAL_PROF, 0x78},
293
  {TARGET_SIGNAL_LAST, -1}
294
};
295
 
296
static void
297
go32_open (char *name, int from_tty)
298
{
299
  printf_unfiltered ("Done.  Use the \"run\" command to run the program.\n");
300
}
301
 
302
static void
303
go32_close (int quitting)
304
{
305
}
306
 
307
static void
308
go32_attach (char *args, int from_tty)
309
{
310
  error ("\
311
You cannot attach to a running program on this platform.\n\
312
Use the `run' command to run DJGPP programs.");
313
}
314
 
315
static void
316
go32_detach (char *args, int from_tty)
317
{
318
}
319
 
320
static int resume_is_step;
321
static int resume_signal = -1;
322
 
323
static void
324
go32_resume (ptid_t ptid, int step, enum target_signal siggnal)
325
{
326
  int i;
327
 
328
  resume_is_step = step;
329
 
330
  if (siggnal != TARGET_SIGNAL_0 && siggnal != TARGET_SIGNAL_TRAP)
331
  {
332
    for (i = 0, resume_signal = -1;
333
         excepn_map[i].gdb_sig != TARGET_SIGNAL_LAST; i++)
334
      if (excepn_map[i].gdb_sig == siggnal)
335
      {
336
        resume_signal = excepn_map[i].djgpp_excepno;
337
        break;
338
      }
339
    if (resume_signal == -1)
340
      printf_unfiltered ("Cannot deliver signal %s on this platform.\n",
341
                         target_signal_to_name (siggnal));
342
  }
343
}
344
 
345
static char child_cwd[FILENAME_MAX];
346
 
347
static ptid_t
348
go32_wait (ptid_t ptid, struct target_waitstatus *status)
349
{
350
  int i;
351
  unsigned char saved_opcode;
352
  unsigned long INT3_addr = 0;
353
  int stepping_over_INT = 0;
354
 
355
  a_tss.tss_eflags &= 0xfeff;   /* reset the single-step flag (TF) */
356
  if (resume_is_step)
357
    {
358
      /* If the next instruction is INT xx or INTO, we need to handle
359
         them specially.  Intel manuals say that these instructions
360
         reset the single-step flag (a.k.a. TF).  However, it seems
361
         that, at least in the DPMI environment, and at least when
362
         stepping over the DPMI interrupt 31h, the problem is having
363
         TF set at all when INT 31h is executed: the debuggee either
364
         crashes (and takes the system with it) or is killed by a
365
         SIGTRAP.
366
 
367
         So we need to emulate single-step mode: we put an INT3 opcode
368
         right after the INT xx instruction, let the debuggee run
369
         until it hits INT3 and stops, then restore the original
370
         instruction which we overwrote with the INT3 opcode, and back
371
         up the debuggee's EIP to that instruction.  */
372
      read_child (a_tss.tss_eip, &saved_opcode, 1);
373
      if (saved_opcode == 0xCD || saved_opcode == 0xCE)
374
        {
375
          unsigned char INT3_opcode = 0xCC;
376
 
377
          INT3_addr
378
            = saved_opcode == 0xCD ? a_tss.tss_eip + 2 : a_tss.tss_eip + 1;
379
          stepping_over_INT = 1;
380
          read_child (INT3_addr, &saved_opcode, 1);
381
          write_child (INT3_addr, &INT3_opcode, 1);
382
        }
383
      else
384
        a_tss.tss_eflags |= 0x0100; /* normal instruction: set TF */
385
    }
386
 
387
  /* The special value FFFFh in tss_trap indicates to run_child that
388
     tss_irqn holds a signal to be delivered to the debuggee.  */
389
  if (resume_signal <= -1)
390
    {
391
      a_tss.tss_trap = 0;
392
      a_tss.tss_irqn = 0xff;
393
    }
394
  else
395
    {
396
      a_tss.tss_trap = 0xffff;  /* run_child looks for this */
397
      a_tss.tss_irqn = resume_signal;
398
    }
399
 
400
  /* The child might change working directory behind our back.  The
401
     GDB users won't like the side effects of that when they work with
402
     relative file names, and GDB might be confused by its current
403
     directory not being in sync with the truth.  So we always make a
404
     point of changing back to where GDB thinks is its cwd, when we
405
     return control to the debugger, but restore child's cwd before we
406
     run it.  */
407
  /* Initialize child_cwd, before the first call to run_child and not
408
     in the initialization, so the child get also the changed directory
409
     set with the gdb-command "cd ..." */
410
  if (!*child_cwd)
411
    /* Initialize child's cwd with the current one.  */
412
    getcwd (child_cwd, sizeof (child_cwd));
413
 
414
  chdir (child_cwd);
415
 
416
#if __DJGPP_MINOR__ < 3
417
  load_npx ();
418
#endif
419
  run_child ();
420
#if __DJGPP_MINOR__ < 3
421
  save_npx ();
422
#endif
423
 
424
  /* Did we step over an INT xx instruction?  */
425
  if (stepping_over_INT && a_tss.tss_eip == INT3_addr + 1)
426
    {
427
      /* Restore the original opcode.  */
428
      a_tss.tss_eip--;  /* EIP points *after* the INT3 instruction */
429
      write_child (a_tss.tss_eip, &saved_opcode, 1);
430
      /* Simulate a TRAP exception.  */
431
      a_tss.tss_irqn = 1;
432
      a_tss.tss_eflags |= 0x0100;
433
    }
434
 
435
  getcwd (child_cwd, sizeof (child_cwd)); /* in case it has changed */
436
  chdir (current_directory);
437
 
438
  if (a_tss.tss_irqn == 0x21)
439
    {
440
      status->kind = TARGET_WAITKIND_EXITED;
441
      status->value.integer = a_tss.tss_eax & 0xff;
442
    }
443
  else
444
    {
445
      status->value.sig = TARGET_SIGNAL_UNKNOWN;
446
      status->kind = TARGET_WAITKIND_STOPPED;
447
      for (i = 0; sig_map[i].go32_sig != -1; i++)
448
        {
449
          if (a_tss.tss_irqn == sig_map[i].go32_sig)
450
            {
451
#if __DJGPP_MINOR__ < 3
452
              if ((status->value.sig = sig_map[i].gdb_sig) !=
453
                  TARGET_SIGNAL_TRAP)
454
                status->kind = TARGET_WAITKIND_SIGNALLED;
455
#else
456
              status->value.sig = sig_map[i].gdb_sig;
457
#endif
458
              break;
459
            }
460
        }
461
    }
462
  return pid_to_ptid (SOME_PID);
463
}
464
 
465
static void
466
fetch_register (int regno)
467
{
468
  if (regno < FP0_REGNUM)
469
    supply_register (regno, (char *) &a_tss + regno_mapping[regno].tss_ofs);
470
  else if (FP_REGNUM_P (regno) || FPC_REGNUM_P (regno))
471
    i387_supply_register (regno, (char *) &npx);
472
  else
473
    internal_error (__FILE__, __LINE__,
474
                    "Invalid register no. %d in fetch_register.", regno);
475
}
476
 
477
static void
478
go32_fetch_registers (int regno)
479
{
480
  if (regno >= 0)
481
    fetch_register (regno);
482
  else
483
    {
484
      for (regno = 0; regno < FP0_REGNUM; regno++)
485
        fetch_register (regno);
486
      i387_supply_fsave ((char *) &npx);
487
    }
488
}
489
 
490
static void
491
store_register (int regno)
492
{
493
  if (regno < FP0_REGNUM)
494
    regcache_collect (regno, (char *) &a_tss + regno_mapping[regno].tss_ofs);
495
  else if (FP_REGNUM_P (regno) || FPC_REGNUM_P (regno))
496
    i387_fill_fsave ((char *) &npx, regno);
497
  else
498
    internal_error (__FILE__, __LINE__,
499
                    "Invalid register no. %d in store_register.", regno);
500
}
501
 
502
static void
503
go32_store_registers (int regno)
504
{
505
  unsigned r;
506
 
507
  if (regno >= 0)
508
    store_register (regno);
509
  else
510
    {
511
      for (r = 0; r < FP0_REGNUM; r++)
512
        store_register (r);
513
      i387_fill_fsave ((char *) &npx, -1);
514
    }
515
}
516
 
517
static void
518
go32_prepare_to_store (void)
519
{
520
}
521
 
522
static int
523
go32_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
524
                  struct mem_attrib *attrib, struct target_ops *target)
525
{
526
  if (write)
527
    {
528
      if (write_child (memaddr, myaddr, len))
529
        {
530
          return 0;
531
        }
532
      else
533
        {
534
          return len;
535
        }
536
    }
537
  else
538
    {
539
      if (read_child (memaddr, myaddr, len))
540
        {
541
          return 0;
542
        }
543
      else
544
        {
545
          return len;
546
        }
547
    }
548
}
549
 
550
static cmdline_t child_cmd;     /* parsed child's command line kept here */
551
 
552
static void
553
go32_files_info (struct target_ops *target)
554
{
555
  printf_unfiltered ("You are running a DJGPP V2 program.\n");
556
}
557
 
558
static void
559
go32_stop (void)
560
{
561
  normal_stop ();
562
  cleanup_client ();
563
  inferior_ptid = null_ptid;
564
  prog_has_started = 0;
565
}
566
 
567
static void
568
go32_kill_inferior (void)
569
{
570
  redir_cmdline_delete (&child_cmd);
571
  resume_signal = -1;
572
  resume_is_step = 0;
573
  unpush_target (&go32_ops);
574
}
575
 
576
static void
577
go32_create_inferior (char *exec_file, char *args, char **env)
578
{
579
  extern char **environ;
580
  jmp_buf start_state;
581
  char *cmdline;
582
  char **env_save = environ;
583
  size_t cmdlen;
584
 
585
  /* If no exec file handed to us, get it from the exec-file command -- with
586
     a good, common error message if none is specified.  */
587
  if (exec_file == 0)
588
    exec_file = get_exec_file (1);
589
 
590
  if (prog_has_started)
591
    {
592
      go32_stop ();
593
      go32_kill_inferior ();
594
    }
595
  resume_signal = -1;
596
  resume_is_step = 0;
597
 
598
  /* Initialize child's cwd as empty to be initialized when starting
599
     the child.  */
600
  *child_cwd = 0;
601
 
602
  /* Init command line storage.  */
603
  if (redir_debug_init (&child_cmd) == -1)
604
    internal_error (__FILE__, __LINE__,
605
                    "Cannot allocate redirection storage: not enough memory.\n");
606
 
607
  /* Parse the command line and create redirections.  */
608
  if (strpbrk (args, "<>"))
609
    {
610
      if (redir_cmdline_parse (args, &child_cmd) == 0)
611
        args = child_cmd.command;
612
      else
613
        error ("Syntax error in command line.");
614
    }
615
  else
616
    child_cmd.command = xstrdup (args);
617
 
618
  cmdlen = strlen (args);
619
  /* v2loadimage passes command lines via DOS memory, so it cannot
620
     possibly handle commands longer than 1MB.  */
621
  if (cmdlen > 1024*1024)
622
    error ("Command line too long.");
623
 
624
  cmdline = xmalloc (cmdlen + 4);
625
  strcpy (cmdline + 1, args);
626
  /* If the command-line length fits into DOS 126-char limits, use the
627
     DOS command tail format; otherwise, tell v2loadimage to pass it
628
     through a buffer in conventional memory.  */
629
  if (cmdlen < 127)
630
    {
631
      cmdline[0] = strlen (args);
632
      cmdline[cmdlen + 1] = 13;
633
    }
634
  else
635
    cmdline[0] = 0xff;   /* signal v2loadimage it's a long command */
636
 
637
  environ = env;
638
 
639
  if (v2loadimage (exec_file, cmdline, start_state))
640
    {
641
      environ = env_save;
642
      printf_unfiltered ("Load failed for image %s\n", exec_file);
643
      exit (1);
644
    }
645
  environ = env_save;
646
  xfree (cmdline);
647
 
648
  edi_init (start_state);
649
#if __DJGPP_MINOR__ < 3
650
  save_npx ();
651
#endif
652
 
653
  inferior_ptid = pid_to_ptid (SOME_PID);
654
  push_target (&go32_ops);
655
  clear_proceed_status ();
656
  insert_breakpoints ();
657
  proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
658
  prog_has_started = 1;
659
}
660
 
661
static void
662
go32_mourn_inferior (void)
663
{
664
  /* We need to make sure all the breakpoint enable bits in the DR7
665
     register are reset when the inferior exits.  Otherwise, if they
666
     rerun the inferior, the uncleared bits may cause random SIGTRAPs,
667
     failure to set more watchpoints, and other calamities.  It would
668
     be nice if GDB itself would take care to remove all breakpoints
669
     at all times, but it doesn't, probably under an assumption that
670
     the OS cleans up when the debuggee exits.  */
671
  i386_cleanup_dregs ();
672
  go32_kill_inferior ();
673
  generic_mourn_inferior ();
674
}
675
 
676
static int
677
go32_can_run (void)
678
{
679
  return 1;
680
}
681
 
682
/* Hardware watchpoint support.  */
683
 
684
#define D_REGS edi.dr
685
#define CONTROL D_REGS[7]
686
#define STATUS D_REGS[6]
687
 
688
/* Pass the address ADDR to the inferior in the I'th debug register.
689
   Here we just store the address in D_REGS, the watchpoint will be
690
   actually set up when go32_wait runs the debuggee.  */
691
void
692
go32_set_dr (int i, CORE_ADDR addr)
693
{
694
  if (i < 0 || i > 3)
695
    internal_error (__FILE__, __LINE__,
696
                    "Invalid register %d in go32_set_dr.\n", i);
697
  D_REGS[i] = addr;
698
}
699
 
700
/* Pass the value VAL to the inferior in the DR7 debug control
701
   register.  Here we just store the address in D_REGS, the watchpoint
702
   will be actually set up when go32_wait runs the debuggee.  */
703
void
704
go32_set_dr7 (unsigned val)
705
{
706
  CONTROL = val;
707
}
708
 
709
/* Get the value of the DR6 debug status register from the inferior.
710
   Here we just return the value stored in D_REGS, as we've got it
711
   from the last go32_wait call.  */
712
unsigned
713
go32_get_dr6 (void)
714
{
715
  return STATUS;
716
}
717
 
718
/* Put the device open on handle FD into either raw or cooked
719
   mode, return 1 if it was in raw mode, zero otherwise.  */
720
 
721
static int
722
device_mode (int fd, int raw_p)
723
{
724
  int oldmode, newmode;
725
  __dpmi_regs regs;
726
 
727
  regs.x.ax = 0x4400;
728
  regs.x.bx = fd;
729
  __dpmi_int (0x21, &regs);
730
  if (regs.x.flags & 1)
731
    return -1;
732
  newmode = oldmode = regs.x.dx;
733
 
734
  if (raw_p)
735
    newmode |= 0x20;
736
  else
737
    newmode &= ~0x20;
738
 
739
  if (oldmode & 0x80)   /* Only for character dev */
740
  {
741
    regs.x.ax = 0x4401;
742
    regs.x.bx = fd;
743
    regs.x.dx = newmode & 0xff;   /* Force upper byte zero, else it fails */
744
    __dpmi_int (0x21, &regs);
745
    if (regs.x.flags & 1)
746
      return -1;
747
  }
748
  return (oldmode & 0x20) == 0x20;
749
}
750
 
751
 
752
static int inf_mode_valid = 0;
753
static int inf_terminal_mode;
754
 
755
/* This semaphore is needed because, amazingly enough, GDB calls
756
   target.to_terminal_ours more than once after the inferior stops.
757
   But we need the information from the first call only, since the
758
   second call will always see GDB's own cooked terminal.  */
759
static int terminal_is_ours = 1;
760
 
761
static void
762
go32_terminal_init (void)
763
{
764
  inf_mode_valid = 0;    /* reinitialize, in case they are restarting child */
765
  terminal_is_ours = 1;
766
}
767
 
768
static void
769
go32_terminal_info (char *args, int from_tty)
770
{
771
  printf_unfiltered ("Inferior's terminal is in %s mode.\n",
772
                     !inf_mode_valid
773
                     ? "default" : inf_terminal_mode ? "raw" : "cooked");
774
 
775
#if __DJGPP_MINOR__ > 2
776
  if (child_cmd.redirection)
777
  {
778
    int i;
779
 
780
    for (i = 0; i < DBG_HANDLES; i++)
781
    {
782
      if (child_cmd.redirection[i]->file_name)
783
        printf_unfiltered ("\tFile handle %d is redirected to `%s'.\n",
784
                           i, child_cmd.redirection[i]->file_name);
785
      else if (_get_dev_info (child_cmd.redirection[i]->inf_handle) == -1)
786
        printf_unfiltered
787
          ("\tFile handle %d appears to be closed by inferior.\n", i);
788
      /* Mask off the raw/cooked bit when comparing device info words.  */
789
      else if ((_get_dev_info (child_cmd.redirection[i]->inf_handle) & 0xdf)
790
               != (_get_dev_info (i) & 0xdf))
791
        printf_unfiltered
792
          ("\tFile handle %d appears to be redirected by inferior.\n", i);
793
    }
794
  }
795
#endif
796
}
797
 
798
static void
799
go32_terminal_inferior (void)
800
{
801
  /* Redirect standard handles as child wants them.  */
802
  errno = 0;
803
  if (redir_to_child (&child_cmd) == -1)
804
  {
805
    redir_to_debugger (&child_cmd);
806
    error ("Cannot redirect standard handles for program: %s.",
807
           safe_strerror (errno));
808
  }
809
  /* set the console device of the inferior to whatever mode
810
     (raw or cooked) we found it last time */
811
  if (terminal_is_ours)
812
  {
813
    if (inf_mode_valid)
814
      device_mode (0, inf_terminal_mode);
815
    terminal_is_ours = 0;
816
  }
817
}
818
 
819
static void
820
go32_terminal_ours (void)
821
{
822
  /* Switch to cooked mode on the gdb terminal and save the inferior
823
     terminal mode to be restored when it is resumed */
824
  if (!terminal_is_ours)
825
  {
826
    inf_terminal_mode = device_mode (0, 0);
827
    if (inf_terminal_mode != -1)
828
      inf_mode_valid = 1;
829
    else
830
      /* If device_mode returned -1, we don't know what happens with
831
         handle 0 anymore, so make the info invalid.  */
832
      inf_mode_valid = 0;
833
    terminal_is_ours = 1;
834
 
835
    /* Restore debugger's standard handles.  */
836
    errno = 0;
837
    if (redir_to_debugger (&child_cmd) == -1)
838
    {
839
      redir_to_child (&child_cmd);
840
      error ("Cannot redirect standard handles for debugger: %s.",
841
             safe_strerror (errno));
842
    }
843
  }
844
}
845
 
846
static void
847
init_go32_ops (void)
848
{
849
  go32_ops.to_shortname = "djgpp";
850
  go32_ops.to_longname = "djgpp target process";
851
  go32_ops.to_doc =
852
    "Program loaded by djgpp, when gdb is used as an external debugger";
853
  go32_ops.to_open = go32_open;
854
  go32_ops.to_close = go32_close;
855
  go32_ops.to_attach = go32_attach;
856
  go32_ops.to_detach = go32_detach;
857
  go32_ops.to_resume = go32_resume;
858
  go32_ops.to_wait = go32_wait;
859
  go32_ops.to_fetch_registers = go32_fetch_registers;
860
  go32_ops.to_store_registers = go32_store_registers;
861
  go32_ops.to_prepare_to_store = go32_prepare_to_store;
862
  go32_ops.to_xfer_memory = go32_xfer_memory;
863
  go32_ops.to_files_info = go32_files_info;
864
  go32_ops.to_insert_breakpoint = memory_insert_breakpoint;
865
  go32_ops.to_remove_breakpoint = memory_remove_breakpoint;
866
  go32_ops.to_terminal_init = go32_terminal_init;
867
  go32_ops.to_terminal_inferior = go32_terminal_inferior;
868
  go32_ops.to_terminal_ours_for_output = go32_terminal_ours;
869
  go32_ops.to_terminal_ours = go32_terminal_ours;
870
  go32_ops.to_terminal_info = go32_terminal_info;
871
  go32_ops.to_kill = go32_kill_inferior;
872
  go32_ops.to_create_inferior = go32_create_inferior;
873
  go32_ops.to_mourn_inferior = go32_mourn_inferior;
874
  go32_ops.to_can_run = go32_can_run;
875
  go32_ops.to_stop = go32_stop;
876
  go32_ops.to_stratum = process_stratum;
877
  go32_ops.to_has_all_memory = 1;
878
  go32_ops.to_has_memory = 1;
879
  go32_ops.to_has_stack = 1;
880
  go32_ops.to_has_registers = 1;
881
  go32_ops.to_has_execution = 1;
882
  go32_ops.to_magic = OPS_MAGIC;
883
 
884
  /* Initialize child's cwd as empty to be initialized when starting
885
     the child.  */
886
  *child_cwd = 0;
887
 
888
  /* Initialize child's command line storage.  */
889
  if (redir_debug_init (&child_cmd) == -1)
890
    internal_error (__FILE__, __LINE__,
891
                    "Cannot allocate redirection storage: not enough memory.\n");
892
 
893
  /* We are always processing GCC-compiled programs.  */
894
  processing_gcc_compilation = 2;
895
}
896
 
897
unsigned short windows_major, windows_minor;
898
 
899
/* Compute the version Windows reports via Int 2Fh/AX=1600h.  */
900
static void
901
go32_get_windows_version(void)
902
{
903
  __dpmi_regs r;
904
 
905
  r.x.ax = 0x1600;
906
  __dpmi_int(0x2f, &r);
907
  if (r.h.al > 2 && r.h.al != 0x80 && r.h.al != 0xff
908
      && (r.h.al > 3 || r.h.ah > 0))
909
    {
910
      windows_major = r.h.al;
911
      windows_minor = r.h.ah;
912
    }
913
  else
914
    windows_major = 0xff;       /* meaning no Windows */
915
}
916
 
917
/* A subroutine of go32_sysinfo to display memory info.  */
918
static void
919
print_mem (unsigned long datum, const char *header, int in_pages_p)
920
{
921
  if (datum != 0xffffffffUL)
922
    {
923
      if (in_pages_p)
924
        datum <<= 12;
925
      puts_filtered (header);
926
      if (datum > 1024)
927
        {
928
          printf_filtered ("%lu KB", datum >> 10);
929
          if (datum > 1024 * 1024)
930
            printf_filtered (" (%lu MB)", datum >> 20);
931
        }
932
      else
933
        printf_filtered ("%lu Bytes", datum);
934
      puts_filtered ("\n");
935
    }
936
}
937
 
938
/* Display assorted information about the underlying OS.  */
939
static void
940
go32_sysinfo (char *arg, int from_tty)
941
{
942
  struct utsname u;
943
  char cpuid_vendor[13];
944
  unsigned cpuid_max = 0, cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
945
  unsigned true_dos_version = _get_dos_version (1);
946
  unsigned advertized_dos_version = ((unsigned int)_osmajor << 8) | _osminor;
947
  int dpmi_flags;
948
  char dpmi_vendor_info[129];
949
  int dpmi_vendor_available =
950
    __dpmi_get_capabilities (&dpmi_flags, dpmi_vendor_info);
951
  __dpmi_version_ret dpmi_version_data;
952
  long eflags;
953
  __dpmi_free_mem_info mem_info;
954
  __dpmi_regs regs;
955
 
956
  cpuid_vendor[0] = '\0';
957
  if (uname (&u))
958
    strcpy (u.machine, "Unknown x86");
959
  else if (u.machine[0] == 'i' && u.machine[1] > 4)
960
    {
961
      /* CPUID with EAX = 0 returns the Vendor ID.  */
962
      __asm__ __volatile__ ("xorl   %%ebx, %%ebx;"
963
                            "xorl   %%ecx, %%ecx;"
964
                            "xorl   %%edx, %%edx;"
965
                            "movl   $0,    %%eax;"
966
                            "cpuid;"
967
                            "movl   %%ebx,  %0;"
968
                            "movl   %%edx,  %1;"
969
                            "movl   %%ecx,  %2;"
970
                            "movl   %%eax,  %3;"
971
                            : "=m" (cpuid_vendor[0]),
972
                              "=m" (cpuid_vendor[4]),
973
                              "=m" (cpuid_vendor[8]),
974
                              "=m" (cpuid_max)
975
                            :
976
                            : "%eax", "%ebx", "%ecx", "%edx");
977
      cpuid_vendor[12] = '\0';
978
    }
979
 
980
  printf_filtered ("CPU Type.......................%s", u.machine);
981
  if (cpuid_vendor[0])
982
    printf_filtered (" (%s)", cpuid_vendor);
983
  puts_filtered ("\n");
984
 
985
  /* CPUID with EAX = 1 returns processor signature and features.  */
986
  if (cpuid_max >= 1)
987
    {
988
      static char *brand_name[] = {
989
        "",
990
        " Celeron",
991
        " III",
992
        " III Xeon",
993
        "", "", "", "",
994
        " 4"
995
      };
996
      char cpu_string[80];
997
      char cpu_brand[20];
998
      unsigned brand_idx;
999
      int intel_p = strcmp (cpuid_vendor, "GenuineIntel") == 0;
1000
      int amd_p = strcmp (cpuid_vendor, "AuthenticAMD") == 0;
1001
      unsigned cpu_family, cpu_model;
1002
 
1003
      __asm__ __volatile__ ("movl   $1, %%eax;"
1004
                            "cpuid;"
1005
                            : "=a" (cpuid_eax),
1006
                              "=b" (cpuid_ebx),
1007
                              "=d" (cpuid_edx)
1008
                            :
1009
                            : "%ecx");
1010
      brand_idx = cpuid_ebx & 0xff;
1011
      cpu_family = (cpuid_eax >> 8) & 0xf;
1012
      cpu_model  = (cpuid_eax >> 4) & 0xf;
1013
      cpu_brand[0] = '\0';
1014
      if (intel_p)
1015
        {
1016
          if (brand_idx > 0
1017
              && brand_idx < sizeof(brand_name)/sizeof(brand_name[0])
1018
              && *brand_name[brand_idx])
1019
            strcpy (cpu_brand, brand_name[brand_idx]);
1020
          else if (cpu_family == 5)
1021
            {
1022
              if (((cpuid_eax >> 12) & 3) == 0 && cpu_model == 4)
1023
                strcpy (cpu_brand, " MMX");
1024
              else if (cpu_model > 1 && ((cpuid_eax >> 12) & 3) == 1)
1025
                strcpy (cpu_brand, " OverDrive");
1026
              else if (cpu_model > 1 && ((cpuid_eax >> 12) & 3) == 2)
1027
                strcpy (cpu_brand, " Dual");
1028
            }
1029
          else if (cpu_family == 6 && cpu_model < 8)
1030
            {
1031
              switch (cpu_model)
1032
                {
1033
                  case 1:
1034
                    strcpy (cpu_brand, " Pro");
1035
                    break;
1036
                  case 3:
1037
                    strcpy (cpu_brand, " II");
1038
                    break;
1039
                  case 5:
1040
                    strcpy (cpu_brand, " II Xeon");
1041
                    break;
1042
                  case 6:
1043
                    strcpy (cpu_brand, " Celeron");
1044
                    break;
1045
                  case 7:
1046
                    strcpy (cpu_brand, " III");
1047
                    break;
1048
                }
1049
            }
1050
        }
1051
      else if (amd_p)
1052
        {
1053
          switch (cpu_family)
1054
            {
1055
              case 4:
1056
                strcpy (cpu_brand, "486/5x86");
1057
                break;
1058
              case 5:
1059
                switch (cpu_model)
1060
                  {
1061
                    case 0:
1062
                    case 1:
1063
                    case 2:
1064
                    case 3:
1065
                      strcpy (cpu_brand, "-K5");
1066
                      break;
1067
                    case 6:
1068
                    case 7:
1069
                      strcpy (cpu_brand, "-K6");
1070
                      break;
1071
                    case 8:
1072
                      strcpy (cpu_brand, "-K6-2");
1073
                      break;
1074
                    case 9:
1075
                      strcpy (cpu_brand, "-K6-III");
1076
                      break;
1077
                  }
1078
                break;
1079
              case 6:
1080
                switch (cpu_model)
1081
                  {
1082
                    case 1:
1083
                    case 2:
1084
                    case 4:
1085
                      strcpy (cpu_brand, " Athlon");
1086
                      break;
1087
                    case 3:
1088
                      strcpy (cpu_brand, " Duron");
1089
                      break;
1090
                  }
1091
                break;
1092
            }
1093
        }
1094
      sprintf (cpu_string, "%s%s Model %d Stepping %d",
1095
               intel_p ? "Pentium" : (amd_p ? "AMD" : "ix86"),
1096
               cpu_brand, cpu_model, cpuid_eax & 0xf);
1097
      printfi_filtered (31, "%s\n", cpu_string);
1098
      if (((cpuid_edx & (6 | (0x0d << 23))) != 0)
1099
          || ((cpuid_edx & 1) == 0)
1100
          || (amd_p && (cpuid_edx & (3 << 30)) != 0))
1101
        {
1102
          puts_filtered ("CPU Features...................");
1103
          /* We only list features which might be useful in the DPMI
1104
             environment.  */
1105
          if ((cpuid_edx & 1) == 0)
1106
            puts_filtered ("No FPU "); /* it's unusual to not have an FPU */
1107
          if ((cpuid_edx & (1 << 1)) != 0)
1108
            puts_filtered ("VME ");
1109
          if ((cpuid_edx & (1 << 2)) != 0)
1110
            puts_filtered ("DE ");
1111
          if ((cpuid_edx & (1 << 4)) != 0)
1112
            puts_filtered ("TSC ");
1113
          if ((cpuid_edx & (1 << 23)) != 0)
1114
            puts_filtered ("MMX ");
1115
          if ((cpuid_edx & (1 << 25)) != 0)
1116
            puts_filtered ("SSE ");
1117
          if ((cpuid_edx & (1 << 26)) != 0)
1118
            puts_filtered ("SSE2 ");
1119
          if (amd_p)
1120
            {
1121
              if ((cpuid_edx & (1 << 31)) != 0)
1122
                puts_filtered ("3DNow! ");
1123
              if ((cpuid_edx & (1 << 30)) != 0)
1124
                puts_filtered ("3DNow!Ext");
1125
            }
1126
          puts_filtered ("\n");
1127
        }
1128
    }
1129
  puts_filtered ("\n");
1130
  printf_filtered ("DOS Version....................%s %s.%s",
1131
                   _os_flavor, u.release, u.version);
1132
  if (true_dos_version != advertized_dos_version)
1133
    printf_filtered (" (disguised as v%d.%d)", _osmajor, _osminor);
1134
  puts_filtered ("\n");
1135
  if (!windows_major)
1136
    go32_get_windows_version ();
1137
  if (windows_major != 0xff)
1138
    {
1139
      const char *windows_flavor;
1140
 
1141
      printf_filtered ("Windows Version................%d.%02d (Windows ",
1142
                       windows_major, windows_minor);
1143
      switch (windows_major)
1144
        {
1145
          case 3:
1146
            windows_flavor = "3.X";
1147
            break;
1148
          case 4:
1149
            switch (windows_minor)
1150
              {
1151
                case 0:
1152
                  windows_flavor = "95, 95A, or 95B";
1153
                  break;
1154
                case 3:
1155
                  windows_flavor = "95B OSR2.1 or 95C OSR2.5";
1156
                  break;
1157
                case 10:
1158
                  windows_flavor = "98 or 98 SE";
1159
                  break;
1160
                case 90:
1161
                  windows_flavor = "ME";
1162
                  break;
1163
                default:
1164
                  windows_flavor = "9X";
1165
                  break;
1166
              }
1167
            break;
1168
          default:
1169
            windows_flavor = "??";
1170
            break;
1171
        }
1172
      printf_filtered ("%s)\n", windows_flavor);
1173
    }
1174
  else if (true_dos_version == 0x532 && advertized_dos_version == 0x500)
1175
    printf_filtered ("Windows Version................Windows NT or Windows 2000\n");
1176
  puts_filtered ("\n");
1177
  if (dpmi_vendor_available == 0)
1178
    {
1179
      /* The DPMI spec says the vendor string should be ASCIIZ, but
1180
         I don't trust the vendors to follow that...  */
1181
      if (!memchr (&dpmi_vendor_info[2], 0, 126))
1182
        dpmi_vendor_info[128] = '\0';
1183
      printf_filtered ("DPMI Host......................%s v%d.%d (capabilities: %#x)\n",
1184
                       &dpmi_vendor_info[2],
1185
                       (unsigned)dpmi_vendor_info[0],
1186
                       (unsigned)dpmi_vendor_info[1],
1187
                       ((unsigned)dpmi_flags & 0x7f));
1188
    }
1189
  __dpmi_get_version (&dpmi_version_data);
1190
  printf_filtered ("DPMI Version...................%d.%02d\n",
1191
                   dpmi_version_data.major, dpmi_version_data.minor);
1192
  printf_filtered ("DPMI Info......................%s-bit DPMI, with%s Virtual Memory support\n",
1193
                   (dpmi_version_data.flags & 1) ? "32" : "16",
1194
                   (dpmi_version_data.flags & 4) ? "" : "out");
1195
  printfi_filtered (31, "Interrupts reflected to %s mode\n",
1196
                   (dpmi_version_data.flags & 2) ? "V86" : "Real");
1197
  printfi_filtered (31, "Processor type: i%d86\n",
1198
                   dpmi_version_data.cpu);
1199
  printfi_filtered (31, "PIC base interrupt: Master: %#x  Slave: %#x\n",
1200
                   dpmi_version_data.master_pic, dpmi_version_data.slave_pic);
1201
 
1202
  /* a_tss is only initialized when the debuggee is first run.  */
1203
  if (prog_has_started)
1204
    {
1205
      __asm__ __volatile__ ("pushfl ; popl %0" : "=g" (eflags));
1206
      printf_filtered ("Protection.....................Ring %d (in %s), with%s I/O protection\n",
1207
                       a_tss.tss_cs & 3, (a_tss.tss_cs & 4) ? "LDT" : "GDT",
1208
                       (a_tss.tss_cs & 3) > ((eflags >> 12) & 3) ? "" : "out");
1209
    }
1210
  puts_filtered ("\n");
1211
  __dpmi_get_free_memory_information (&mem_info);
1212
  print_mem (mem_info.total_number_of_physical_pages,
1213
             "DPMI Total Physical Memory.....", 1);
1214
  print_mem (mem_info.total_number_of_free_pages,
1215
             "DPMI Free Physical Memory......", 1);
1216
  print_mem (mem_info.size_of_paging_file_partition_in_pages,
1217
             "DPMI Swap Space................", 1);
1218
  print_mem (mem_info.linear_address_space_size_in_pages,
1219
             "DPMI Total Linear Address Size.", 1);
1220
  print_mem (mem_info.free_linear_address_space_in_pages,
1221
             "DPMI Free Linear Address Size..", 1);
1222
  print_mem (mem_info.largest_available_free_block_in_bytes,
1223
             "DPMI Largest Free Memory Block.", 0);
1224
 
1225
  regs.h.ah = 0x48;
1226
  regs.x.bx = 0xffff;
1227
  __dpmi_int (0x21, &regs);
1228
  print_mem (regs.x.bx << 4, "Free DOS Memory................", 0);
1229
  regs.x.ax = 0x5800;
1230
  __dpmi_int (0x21, &regs);
1231
  if ((regs.x.flags & 1) == 0)
1232
    {
1233
      static const char *dos_hilo[] = {
1234
        "Low", "", "", "", "High", "", "", "", "High, then Low"
1235
      };
1236
      static const char *dos_fit[] = {
1237
        "First", "Best", "Last"
1238
      };
1239
      int hilo_idx = (regs.x.ax >> 4) & 0x0f;
1240
      int fit_idx  = regs.x.ax & 0x0f;
1241
 
1242
      if (hilo_idx > 8)
1243
        hilo_idx = 0;
1244
      if (fit_idx > 2)
1245
        fit_idx = 0;
1246
      printf_filtered ("DOS Memory Allocation..........%s memory, %s fit\n",
1247
                       dos_hilo[hilo_idx], dos_fit[fit_idx]);
1248
      regs.x.ax = 0x5802;
1249
      __dpmi_int (0x21, &regs);
1250
      if ((regs.x.flags & 1) != 0)
1251
        regs.h.al = 0;
1252
      printfi_filtered (31, "UMBs %sin DOS memory chain\n",
1253
                        regs.h.al == 0 ? "not " : "");
1254
    }
1255
}
1256
 
1257
struct seg_descr {
1258
  unsigned short limit0          __attribute__((packed));
1259
  unsigned short base0           __attribute__((packed));
1260
  unsigned char  base1           __attribute__((packed));
1261
  unsigned       stype:5         __attribute__((packed));
1262
  unsigned       dpl:2           __attribute__((packed));
1263
  unsigned       present:1       __attribute__((packed));
1264
  unsigned       limit1:4        __attribute__((packed));
1265
  unsigned       available:1     __attribute__((packed));
1266
  unsigned       dummy:1         __attribute__((packed));
1267
  unsigned       bit32:1         __attribute__((packed));
1268
  unsigned       page_granular:1 __attribute__((packed));
1269
  unsigned char  base2           __attribute__((packed));
1270
};
1271
 
1272
struct gate_descr {
1273
  unsigned short offset0         __attribute__((packed));
1274
  unsigned short selector        __attribute__((packed));
1275
  unsigned       param_count:5   __attribute__((packed));
1276
  unsigned       dummy:3         __attribute__((packed));
1277
  unsigned       stype:5         __attribute__((packed));
1278
  unsigned       dpl:2           __attribute__((packed));
1279
  unsigned       present:1       __attribute__((packed));
1280
  unsigned short offset1         __attribute__((packed));
1281
};
1282
 
1283
/* Read LEN bytes starting at logical address ADDR, and put the result
1284
   into DEST.  Return 1 if success, zero if not.  */
1285
static int
1286
read_memory_region (unsigned long addr, void *dest, size_t len)
1287
{
1288
  unsigned long dos_ds_limit = __dpmi_get_segment_limit (_dos_ds);
1289
  int retval = 1;
1290
 
1291
  /* For the low memory, we can simply use _dos_ds.  */
1292
  if (addr <= dos_ds_limit - len)
1293
    dosmemget (addr, len, dest);
1294
  else
1295
    {
1296
      /* For memory above 1MB we need to set up a special segment to
1297
         be able to access that memory.  */
1298
      int sel = __dpmi_allocate_ldt_descriptors (1);
1299
 
1300
      if (sel <= 0)
1301
        retval = 0;
1302
      else
1303
        {
1304
          int access_rights = __dpmi_get_descriptor_access_rights (sel);
1305
          size_t segment_limit = len - 1;
1306
 
1307
          /* Make sure the crucial bits in the descriptor access
1308
             rights are set correctly.  Some DPMI providers might barf
1309
             if we set the segment limit to something that is not an
1310
             integral multiple of 4KB pages if the granularity bit is
1311
             not set to byte-granular, even though the DPMI spec says
1312
             it's the host's responsibility to set that bit correctly.  */
1313
          if (len > 1024 * 1024)
1314
            {
1315
              access_rights |= 0x8000;
1316
              /* Page-granular segments should have the low 12 bits of
1317
                 the limit set.  */
1318
              segment_limit |= 0xfff;
1319
            }
1320
          else
1321
            access_rights &= ~0x8000;
1322
 
1323
          if (__dpmi_set_segment_base_address (sel, addr) != -1
1324
              && __dpmi_set_descriptor_access_rights (sel, access_rights) != -1
1325
              && __dpmi_set_segment_limit (sel, segment_limit) != -1
1326
              /* W2K silently fails to set the segment limit, leaving
1327
                 it at zero; this test avoids the resulting crash.  */
1328
              && __dpmi_get_segment_limit (sel) >= segment_limit)
1329
            movedata (sel, 0, _my_ds (), (unsigned)dest, len);
1330
          else
1331
            retval = 0;
1332
 
1333
          __dpmi_free_ldt_descriptor (sel);
1334
        }
1335
    }
1336
  return retval;
1337
}
1338
 
1339
/* Get a segment descriptor stored at index IDX in the descriptor
1340
   table whose base address is TABLE_BASE.  Return the descriptor
1341
   type, or -1 if failure.  */
1342
static int
1343
get_descriptor (unsigned long table_base, int idx, void *descr)
1344
{
1345
  unsigned long addr = table_base + idx * 8; /* 8 bytes per entry */
1346
 
1347
  if (read_memory_region (addr, descr, 8))
1348
    return (int)((struct seg_descr *)descr)->stype;
1349
  return -1;
1350
}
1351
 
1352
struct dtr_reg {
1353
  unsigned short limit __attribute__((packed));
1354
  unsigned long  base  __attribute__((packed));
1355
};
1356
 
1357
/* Display a segment descriptor stored at index IDX in a descriptor
1358
   table whose type is TYPE and whose base address is BASE_ADDR.  If
1359
   FORCE is non-zero, display even invalid descriptors.  */
1360
static void
1361
display_descriptor (unsigned type, unsigned long base_addr, int idx, int force)
1362
{
1363
  struct seg_descr descr;
1364
  struct gate_descr gate;
1365
 
1366
  /* Get the descriptor from the table.  */
1367
  if (idx == 0 && type == 0)
1368
    puts_filtered ("0x000: null descriptor\n");
1369
  else if (get_descriptor (base_addr, idx, &descr) != -1)
1370
    {
1371
      /* For each type of descriptor table, this has a bit set if the
1372
         corresponding type of selectors is valid in that table.  */
1373
      static unsigned allowed_descriptors[] = {
1374
          0xffffdafeL,   /* GDT */
1375
          0x0000c0e0L,   /* IDT */
1376
          0xffffdafaL    /* LDT */
1377
      };
1378
 
1379
      /* If the program hasn't started yet, assume the debuggee will
1380
         have the same CPL as the debugger.  */
1381
      int cpl = prog_has_started ? (a_tss.tss_cs & 3) : _my_cs () & 3;
1382
      unsigned long limit = (descr.limit1 << 16) | descr.limit0;
1383
 
1384
      if (descr.present
1385
          && (allowed_descriptors[type] & (1 << descr.stype)) != 0)
1386
        {
1387
          printf_filtered ("0x%03x: ",
1388
                           type == 1
1389
                           ? idx : (idx * 8) | (type ? (cpl | 4) : 0));
1390
          if (descr.page_granular)
1391
            limit = (limit << 12) | 0xfff; /* big segment: low 12 bit set */
1392
          if (descr.stype == 1 || descr.stype == 2 || descr.stype == 3
1393
              || descr.stype == 9 || descr.stype == 11
1394
              || (descr.stype >= 16 && descr.stype < 32))
1395
            printf_filtered ("base=0x%02x%02x%04x limit=0x%08lx",
1396
                             descr.base2, descr.base1, descr.base0, limit);
1397
 
1398
          switch (descr.stype)
1399
            {
1400
              case 1:
1401
              case 3:
1402
                printf_filtered (" 16-bit TSS  (task %sactive)",
1403
                                 descr.stype == 3 ? "" : "in");
1404
                break;
1405
              case 2:
1406
                puts_filtered (" LDT");
1407
                break;
1408
              case 4:
1409
                memcpy (&gate, &descr, sizeof gate);
1410
                printf_filtered ("selector=0x%04x  offs=0x%04x%04x",
1411
                                 gate.selector, gate.offset1, gate.offset0);
1412
                printf_filtered (" 16-bit Call Gate (params=%d)",
1413
                                 gate.param_count);
1414
                break;
1415
              case 5:
1416
                printf_filtered ("TSS selector=0x%04x", descr.base0);
1417
                printfi_filtered (16, "Task Gate");
1418
                break;
1419
              case 6:
1420
              case 7:
1421
                memcpy (&gate, &descr, sizeof gate);
1422
                printf_filtered ("selector=0x%04x  offs=0x%04x%04x",
1423
                                 gate.selector, gate.offset1, gate.offset0);
1424
                printf_filtered (" 16-bit %s Gate",
1425
                                 descr.stype == 6 ? "Interrupt" : "Trap");
1426
                break;
1427
              case 9:
1428
              case 11:
1429
                printf_filtered (" 32-bit TSS (task %sactive)",
1430
                                 descr.stype == 3 ? "" : "in");
1431
                break;
1432
              case 12:
1433
                memcpy (&gate, &descr, sizeof gate);
1434
                printf_filtered ("selector=0x%04x  offs=0x%04x%04x",
1435
                                 gate.selector, gate.offset1, gate.offset0);
1436
                printf_filtered (" 32-bit Call Gate (params=%d)",
1437
                                 gate.param_count);
1438
                break;
1439
              case 14:
1440
              case 15:
1441
                memcpy (&gate, &descr, sizeof gate);
1442
                printf_filtered ("selector=0x%04x  offs=0x%04x%04x",
1443
                                 gate.selector, gate.offset1, gate.offset0);
1444
                printf_filtered (" 32-bit %s Gate",
1445
                                 descr.stype == 14 ? "Interrupt" : "Trap");
1446
                break;
1447
              case 16:          /* data segments */
1448
              case 17:
1449
              case 18:
1450
              case 19:
1451
              case 20:
1452
              case 21:
1453
              case 22:
1454
              case 23:
1455
                printf_filtered (" %s-bit Data (%s Exp-%s%s)",
1456
                                 descr.bit32 ? "32" : "16",
1457
                                 descr.stype & 2 ? "Read/Write," : "Read-Only, ",
1458
                                 descr.stype & 4 ? "down" : "up",
1459
                                 descr.stype & 1 ? "" : ", N.Acc");
1460
                break;
1461
              case 24:          /* code segments */
1462
              case 25:
1463
              case 26:
1464
              case 27:
1465
              case 28:
1466
              case 29:
1467
              case 30:
1468
              case 31:
1469
                printf_filtered (" %s-bit Code (%s,  %sConf%s)",
1470
                                 descr.bit32 ? "32" : "16",
1471
                                 descr.stype & 2 ? "Exec/Read" : "Exec-Only",
1472
                                 descr.stype & 4 ? "" : "N.",
1473
                                 descr.stype & 1 ? "" : ", N.Acc");
1474
                break;
1475
              default:
1476
                printf_filtered ("Unknown type 0x%02x", descr.stype);
1477
                break;
1478
            }
1479
          puts_filtered ("\n");
1480
        }
1481
      else if (force)
1482
        {
1483
          printf_filtered ("0x%03x: ",
1484
                           type == 1
1485
                           ? idx : (idx * 8) | (type ? (cpl | 4) : 0));
1486
          if (!descr.present)
1487
            puts_filtered ("Segment not present\n");
1488
          else
1489
            printf_filtered ("Segment type 0x%02x is invalid in this table\n",
1490
                             descr.stype);
1491
        }
1492
    }
1493
  else if (force)
1494
    printf_filtered ("0x%03x: Cannot read this descriptor\n", idx);
1495
}
1496
 
1497
static void
1498
go32_sldt (char *arg, int from_tty)
1499
{
1500
  struct dtr_reg gdtr;
1501
  unsigned short ldtr = 0;
1502
  int ldt_idx;
1503
  struct seg_descr ldt_descr;
1504
  long ldt_entry = -1L;
1505
  int cpl = (prog_has_started ? a_tss.tss_cs : _my_cs ()) & 3;
1506
 
1507
  if (arg && *arg)
1508
    {
1509
      while (*arg && isspace(*arg))
1510
        arg++;
1511
 
1512
      if (*arg)
1513
        {
1514
          ldt_entry = parse_and_eval_long (arg);
1515
          if (ldt_entry < 0
1516
              || (ldt_entry & 4) == 0
1517
              || (ldt_entry & 3) != (cpl & 3))
1518
            error ("Invalid LDT entry 0x%03x.", ldt_entry);
1519
        }
1520
    }
1521
 
1522
  __asm__ __volatile__ ("sgdt   %0" : "=m" (gdtr) : /* no inputs */ );
1523
  __asm__ __volatile__ ("sldt   %0" : "=m" (ldtr) : /* no inputs */ );
1524
  ldt_idx = ldtr / 8;
1525
  if (ldt_idx == 0)
1526
    puts_filtered ("There is no LDT.\n");
1527
  /* LDT's entry in the GDT must have the type LDT, which is 2.  */
1528
  else if (get_descriptor (gdtr.base, ldt_idx, &ldt_descr) != 2)
1529
    printf_filtered ("LDT is present (at %#x), but unreadable by GDB.\n",
1530
                     ldt_descr.base0
1531
                     | (ldt_descr.base1 << 16)
1532
                     | (ldt_descr.base2 << 24));
1533
  else
1534
    {
1535
      unsigned base =
1536
        ldt_descr.base0
1537
        | (ldt_descr.base1 << 16)
1538
        | (ldt_descr.base2 << 24);
1539
      unsigned limit = ldt_descr.limit0 | (ldt_descr.limit1 << 16);
1540
      int max_entry;
1541
 
1542
      if (ldt_descr.page_granular)
1543
        /* Page-granular segments must have the low 12 bits of their
1544
           limit set.  */
1545
        limit = (limit << 12) | 0xfff;
1546
      /* LDT cannot have more than 8K 8-byte entries, i.e. more than
1547
         64KB.  */
1548
      if (limit > 0xffff)
1549
        limit = 0xffff;
1550
 
1551
      max_entry = (limit + 1) / 8;
1552
 
1553
      if (ldt_entry >= 0)
1554
        {
1555
          if (ldt_entry > limit)
1556
            error ("Invalid LDT entry %#x: outside valid limits [0..%#x]",
1557
                   ldt_entry, limit);
1558
 
1559
          display_descriptor (ldt_descr.stype, base, ldt_entry / 8, 1);
1560
        }
1561
      else
1562
        {
1563
          int i;
1564
 
1565
          for (i = 0; i < max_entry; i++)
1566
            display_descriptor (ldt_descr.stype, base, i, 0);
1567
        }
1568
    }
1569
}
1570
 
1571
static void
1572
go32_sgdt (char *arg, int from_tty)
1573
{
1574
  struct dtr_reg gdtr;
1575
  long gdt_entry = -1L;
1576
  int max_entry;
1577
 
1578
  if (arg && *arg)
1579
    {
1580
      while (*arg && isspace(*arg))
1581
        arg++;
1582
 
1583
      if (*arg)
1584
        {
1585
          gdt_entry = parse_and_eval_long (arg);
1586
          if (gdt_entry < 0 || (gdt_entry & 7) != 0)
1587
            error ("Invalid GDT entry 0x%03x: not an integral multiple of 8.",
1588
                   gdt_entry);
1589
        }
1590
    }
1591
 
1592
  __asm__ __volatile__ ("sgdt   %0" : "=m" (gdtr) : /* no inputs */ );
1593
  max_entry = (gdtr.limit + 1) / 8;
1594
 
1595
  if (gdt_entry >= 0)
1596
    {
1597
      if (gdt_entry > gdtr.limit)
1598
        error ("Invalid GDT entry %#x: outside valid limits [0..%#x]",
1599
               gdt_entry, gdtr.limit);
1600
 
1601
      display_descriptor (0, gdtr.base, gdt_entry / 8, 1);
1602
    }
1603
  else
1604
    {
1605
      int i;
1606
 
1607
      for (i = 0; i < max_entry; i++)
1608
        display_descriptor (0, gdtr.base, i, 0);
1609
    }
1610
}
1611
 
1612
static void
1613
go32_sidt (char *arg, int from_tty)
1614
{
1615
  struct dtr_reg idtr;
1616
  long idt_entry = -1L;
1617
  int max_entry;
1618
 
1619
  if (arg && *arg)
1620
    {
1621
      while (*arg && isspace(*arg))
1622
        arg++;
1623
 
1624
      if (*arg)
1625
        {
1626
          idt_entry = parse_and_eval_long (arg);
1627
          if (idt_entry < 0)
1628
            error ("Invalid (negative) IDT entry %d.", idt_entry);
1629
        }
1630
    }
1631
 
1632
  __asm__ __volatile__ ("sidt   %0" : "=m" (idtr) : /* no inputs */ );
1633
  max_entry = (idtr.limit + 1) / 8;
1634
  if (max_entry > 0x100)        /* no more than 256 entries */
1635
    max_entry = 0x100;
1636
 
1637
  if (idt_entry >= 0)
1638
    {
1639
      if (idt_entry > idtr.limit)
1640
        error ("Invalid IDT entry %#x: outside valid limits [0..%#x]",
1641
               idt_entry, idtr.limit);
1642
 
1643
      display_descriptor (1, idtr.base, idt_entry, 1);
1644
    }
1645
  else
1646
    {
1647
      int i;
1648
 
1649
      for (i = 0; i < max_entry; i++)
1650
        display_descriptor (1, idtr.base, i, 0);
1651
    }
1652
}
1653
 
1654
/* Cached linear address of the base of the page directory.  For
1655
   now, available only under CWSDPMI.  Code based on ideas and
1656
   suggestions from Charles Sandmann <sandmann@clio.rice.edu>.  */
1657
static unsigned long pdbr;
1658
 
1659
static unsigned long
1660
get_cr3 (void)
1661
{
1662
  unsigned offset;
1663
  unsigned taskreg;
1664
  unsigned long taskbase, cr3;
1665
  struct dtr_reg gdtr;
1666
 
1667
  if (pdbr > 0 && pdbr <= 0xfffff)
1668
    return pdbr;
1669
 
1670
  /* Get the linear address of GDT and the Task Register.  */
1671
  __asm__ __volatile__ ("sgdt   %0" : "=m" (gdtr) : /* no inputs */ );
1672
  __asm__ __volatile__ ("str    %0" : "=m" (taskreg) : /* no inputs */ );
1673
 
1674
  /* Task Register is a segment selector for the TSS of the current
1675
     task.  Therefore, it can be used as an index into the GDT to get
1676
     at the segment descriptor for the TSS.  To get the index, reset
1677
     the low 3 bits of the selector (which give the CPL).  Add 2 to the
1678
     offset to point to the 3 low bytes of the base address.  */
1679
  offset = gdtr.base + (taskreg & 0xfff8) + 2;
1680
 
1681
 
1682
  /* CWSDPMI's task base is always under the 1MB mark.  */
1683
  if (offset > 0xfffff)
1684
    return 0;
1685
 
1686
  _farsetsel (_dos_ds);
1687
  taskbase  = _farnspeekl (offset) & 0xffffffU;
1688
  taskbase += _farnspeekl (offset + 2) & 0xff000000U;
1689
  if (taskbase > 0xfffff)
1690
    return 0;
1691
 
1692
  /* CR3 (a.k.a. PDBR, the Page Directory Base Register) is stored at
1693
     offset 1Ch in the TSS.  */
1694
  cr3 = _farnspeekl (taskbase + 0x1c) & ~0xfff;
1695
  if (cr3 > 0xfffff)
1696
    {
1697
#if 0  /* not fullly supported yet */
1698
      /* The Page Directory is in UMBs.  In that case, CWSDPMI puts
1699
         the first Page Table right below the Page Directory.  Thus,
1700
         the first Page Table's entry for its own address and the Page
1701
         Directory entry for that Page Table will hold the same
1702
         physical address.  The loop below searches the entire UMB
1703
         range of addresses for such an occurence.  */
1704
      unsigned long addr, pte_idx;
1705
 
1706
      for (addr = 0xb0000, pte_idx = 0xb0;
1707
           pte_idx < 0xff;
1708
           addr += 0x1000, pte_idx++)
1709
        {
1710
          if (((_farnspeekl (addr + 4 * pte_idx) & 0xfffff027) ==
1711
               (_farnspeekl (addr + 0x1000) & 0xfffff027))
1712
              && ((_farnspeekl (addr + 4 * pte_idx + 4) & 0xfffff000) == cr3))
1713
            {
1714
              cr3 = addr + 0x1000;
1715
              break;
1716
            }
1717
        }
1718
#endif
1719
 
1720
      if (cr3 > 0xfffff)
1721
        cr3 = 0;
1722
    }
1723
 
1724
  return cr3;
1725
}
1726
 
1727
/* Return the N'th Page Directory entry.  */
1728
static unsigned long
1729
get_pde (int n)
1730
{
1731
  unsigned long pde = 0;
1732
 
1733
  if (pdbr && n >= 0 && n < 1024)
1734
    {
1735
      pde = _farpeekl (_dos_ds, pdbr + 4*n);
1736
    }
1737
  return pde;
1738
}
1739
 
1740
/* Return the N'th entry of the Page Table whose Page Directory entry
1741
   is PDE.  */
1742
static unsigned long
1743
get_pte (unsigned long pde, int n)
1744
{
1745
  unsigned long pte = 0;
1746
 
1747
  /* pde & 0x80 tests the 4MB page bit.  We don't support 4MB
1748
     page tables, for now.  */
1749
  if ((pde & 1) && !(pde & 0x80) && n >= 0 && n < 1024)
1750
    {
1751
      pde &= ~0xfff;    /* clear non-address bits */
1752
      pte = _farpeekl (_dos_ds, pde + 4*n);
1753
    }
1754
  return pte;
1755
}
1756
 
1757
/* Display a Page Directory or Page Table entry.  IS_DIR, if non-zero,
1758
   says this is a Page Directory entry.  If FORCE is non-zero, display
1759
   the entry even if its Present flag is off.  OFF is the offset of the
1760
   address from the page's base address.  */
1761
static void
1762
display_ptable_entry (unsigned long entry, int is_dir, int force, unsigned off)
1763
{
1764
  if ((entry & 1) != 0)
1765
    {
1766
      printf_filtered ("Base=0x%05lx000", entry >> 12);
1767
      if ((entry & 0x100) && !is_dir)
1768
        puts_filtered (" Global");
1769
      if ((entry & 0x40) && !is_dir)
1770
        puts_filtered (" Dirty");
1771
      printf_filtered (" %sAcc.", (entry & 0x20) ? "" : "Not-");
1772
      printf_filtered (" %sCached", (entry & 0x10) ? "" : "Not-");
1773
      printf_filtered (" Write-%s", (entry & 8) ? "Thru" : "Back");
1774
      printf_filtered (" %s", (entry & 4) ? "Usr" : "Sup");
1775
      printf_filtered (" Read-%s", (entry & 2) ? "Write" : "Only");
1776
      if (off)
1777
        printf_filtered (" +0x%x", off);
1778
      puts_filtered ("\n");
1779
    }
1780
  else if (force)
1781
    printf_filtered ("Page%s not present or not supported; value=0x%lx.\n",
1782
                     is_dir ? " Table" : "", entry >> 1);
1783
}
1784
 
1785
static void
1786
go32_pde (char *arg, int from_tty)
1787
{
1788
  long pde_idx = -1, i;
1789
 
1790
  if (arg && *arg)
1791
    {
1792
      while (*arg && isspace(*arg))
1793
        arg++;
1794
 
1795
      if (*arg)
1796
        {
1797
          pde_idx = parse_and_eval_long (arg);
1798
          if (pde_idx < 0 || pde_idx >= 1024)
1799
            error ("Entry %ld is outside valid limits [0..1023].", pde_idx);
1800
        }
1801
    }
1802
 
1803
  pdbr = get_cr3 ();
1804
  if (!pdbr)
1805
    puts_filtered ("Access to Page Directories is not supported on this system.\n");
1806
  else if (pde_idx >= 0)
1807
    display_ptable_entry (get_pde (pde_idx), 1, 1, 0);
1808
  else
1809
    for (i = 0; i < 1024; i++)
1810
      display_ptable_entry (get_pde (i), 1, 0, 0);
1811
}
1812
 
1813
/* A helper function to display entries in a Page Table pointed to by
1814
   the N'th entry in the Page Directory.  If FORCE is non-zero, say
1815
   something even if the Page Table is not accessible.  */
1816
static void
1817
display_page_table (long n, int force)
1818
{
1819
  unsigned long pde = get_pde (n);
1820
 
1821
  if ((pde & 1) != 0)
1822
    {
1823
      int i;
1824
 
1825
      printf_filtered ("Page Table pointed to by Page Directory entry 0x%lx:\n", n);
1826
      for (i = 0; i < 1024; i++)
1827
        display_ptable_entry (get_pte (pde, i), 0, 0, 0);
1828
      puts_filtered ("\n");
1829
    }
1830
  else if (force)
1831
    printf_filtered ("Page Table not present; value=0x%lx.\n", pde >> 1);
1832
}
1833
 
1834
static void
1835
go32_pte (char *arg, int from_tty)
1836
{
1837
  long pde_idx = -1, i;
1838
 
1839
  if (arg && *arg)
1840
    {
1841
      while (*arg && isspace(*arg))
1842
        arg++;
1843
 
1844
      if (*arg)
1845
        {
1846
          pde_idx = parse_and_eval_long (arg);
1847
          if (pde_idx < 0 || pde_idx >= 1024)
1848
            error ("Entry %d is outside valid limits [0..1023].", pde_idx);
1849
        }
1850
    }
1851
 
1852
  pdbr = get_cr3 ();
1853
  if (!pdbr)
1854
    puts_filtered ("Access to Page Tables is not supported on this system.\n");
1855
  else if (pde_idx >= 0)
1856
    display_page_table (pde_idx, 1);
1857
  else
1858
    for (i = 0; i < 1024; i++)
1859
      display_page_table (i, 0);
1860
}
1861
 
1862
static void
1863
go32_pte_for_address (char *arg, int from_tty)
1864
{
1865
  CORE_ADDR addr = 0, i;
1866
 
1867
  if (arg && *arg)
1868
    {
1869
      while (*arg && isspace(*arg))
1870
        arg++;
1871
 
1872
      if (*arg)
1873
        addr = parse_and_eval_address (arg);
1874
    }
1875
  if (!addr)
1876
    error_no_arg ("linear address");
1877
 
1878
  pdbr = get_cr3 ();
1879
  if (!pdbr)
1880
    puts_filtered ("Access to Page Tables is not supported on this system.\n");
1881
  else
1882
    {
1883
      int pde_idx = (addr >> 22) & 0x3ff;
1884
      int pte_idx = (addr >> 12) & 0x3ff;
1885
      unsigned offs = addr & 0xfff;
1886
 
1887
      printf_filtered ("Page Table entry for address 0x%llx:\n",
1888
                       (unsigned long long)addr);
1889
      display_ptable_entry (get_pte (get_pde (pde_idx), pte_idx), 0, 1, offs);
1890
    }
1891
}
1892
 
1893
static struct cmd_list_element *info_dos_cmdlist = NULL;
1894
 
1895
static void
1896
go32_info_dos_command (char *args, int from_tty)
1897
{
1898
  help_list (info_dos_cmdlist, "info dos ", class_info, gdb_stdout);
1899
}
1900
 
1901
void
1902
_initialize_go32_nat (void)
1903
{
1904
  init_go32_ops ();
1905
  add_target (&go32_ops);
1906
 
1907
  add_prefix_cmd ("dos", class_info, go32_info_dos_command,
1908
                  "Print information specific to DJGPP (aka MS-DOS) debugging.",
1909
                  &info_dos_cmdlist, "info dos ", 0, &infolist);
1910
 
1911
  add_cmd ("sysinfo", class_info, go32_sysinfo,
1912
            "Display information about the target system, including CPU, OS, DPMI, etc.",
1913
           &info_dos_cmdlist);
1914
  add_cmd ("ldt", class_info, go32_sldt,
1915
           "Display entries in the LDT (Local Descriptor Table).\n"
1916
           "Entry number (an expression) as an argument means display only that entry.",
1917
           &info_dos_cmdlist);
1918
  add_cmd ("gdt", class_info, go32_sgdt,
1919
           "Display entries in the GDT (Global Descriptor Table).\n"
1920
           "Entry number (an expression) as an argument means display only that entry.",
1921
           &info_dos_cmdlist);
1922
  add_cmd ("idt", class_info, go32_sidt,
1923
           "Display entries in the IDT (Interrupt Descriptor Table).\n"
1924
           "Entry number (an expression) as an argument means display only that entry.",
1925
           &info_dos_cmdlist);
1926
  add_cmd ("pde", class_info, go32_pde,
1927
           "Display entries in the Page Directory.\n"
1928
           "Entry number (an expression) as an argument means display only that entry.",
1929
           &info_dos_cmdlist);
1930
  add_cmd ("pte", class_info, go32_pte,
1931
           "Display entries in Page Tables.\n"
1932
           "Entry number (an expression) as an argument means display only entries\n"
1933
           "from the Page Table pointed to by the specified Page Directory entry.",
1934
           &info_dos_cmdlist);
1935
  add_cmd ("address-pte", class_info, go32_pte_for_address,
1936
           "Display a Page Table entry for a linear address.\n"
1937
           "The address argument must be a linear address, after adding to\n"
1938
           "it the base address of the appropriate segment.\n"
1939
           "The base address of variables and functions in the debuggee's data\n"
1940
           "or code segment is stored in the variable __djgpp_base_address,\n"
1941
           "so use `__djgpp_base_address + (char *)&var' as the argument.\n"
1942
           "For other segments, look up their base address in the output of\n"
1943
           "the `info dos ldt' command.",
1944
           &info_dos_cmdlist);
1945
}
1946
 
1947
pid_t
1948
tcgetpgrp (int fd)
1949
{
1950
  if (isatty (fd))
1951
    return SOME_PID;
1952
  errno = ENOTTY;
1953
  return -1;
1954
}
1955
 
1956
int
1957
tcsetpgrp (int fd, pid_t pgid)
1958
{
1959
  if (isatty (fd) && pgid == SOME_PID)
1960
    return 0;
1961
  errno = pgid == SOME_PID ? ENOTTY : ENOSYS;
1962
  return -1;
1963
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.