xref: /openbsd/gnu/usr.bin/binutils/gdb/go32-nat.c (revision 898184e3)
1 /* 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, int from_tty);
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     regcache_raw_supply (current_regcache, regno,
470 			 (char *) &a_tss + regno_mapping[regno].tss_ofs);
471   else if (i386_fp_regnum_p (regno) || i386_fpc_regnum_p (regno))
472     i387_supply_fsave (current_regcache, regno, &npx);
473   else
474     internal_error (__FILE__, __LINE__,
475 		    "Invalid register no. %d in fetch_register.", regno);
476 }
477 
478 static void
479 go32_fetch_registers (int regno)
480 {
481   if (regno >= 0)
482     fetch_register (regno);
483   else
484     {
485       for (regno = 0; regno < FP0_REGNUM; regno++)
486 	fetch_register (regno);
487       i387_supply_fsave (current_regcache, -1, &npx);
488     }
489 }
490 
491 static void
492 store_register (int regno)
493 {
494   if (regno < FP0_REGNUM)
495     regcache_raw_collect (current_regcache, regno,
496 			  (char *) &a_tss + regno_mapping[regno].tss_ofs);
497   else if (i386_fp_regnum_p (regno) || i386_fpc_regnum_p (regno))
498     i387_fill_fsave ((char *) &npx, regno);
499   else
500     internal_error (__FILE__, __LINE__,
501 		    "Invalid register no. %d in store_register.", regno);
502 }
503 
504 static void
505 go32_store_registers (int regno)
506 {
507   unsigned r;
508 
509   if (regno >= 0)
510     store_register (regno);
511   else
512     {
513       for (r = 0; r < FP0_REGNUM; r++)
514 	store_register (r);
515       i387_fill_fsave ((char *) &npx, -1);
516     }
517 }
518 
519 static void
520 go32_prepare_to_store (void)
521 {
522 }
523 
524 static int
525 go32_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
526 		  struct mem_attrib *attrib, struct target_ops *target)
527 {
528   if (write)
529     {
530       if (write_child (memaddr, myaddr, len))
531 	{
532 	  return 0;
533 	}
534       else
535 	{
536 	  return len;
537 	}
538     }
539   else
540     {
541       if (read_child (memaddr, myaddr, len))
542 	{
543 	  return 0;
544 	}
545       else
546 	{
547 	  return len;
548 	}
549     }
550 }
551 
552 static cmdline_t child_cmd;	/* parsed child's command line kept here */
553 
554 static void
555 go32_files_info (struct target_ops *target)
556 {
557   printf_unfiltered ("You are running a DJGPP V2 program.\n");
558 }
559 
560 static void
561 go32_stop (void)
562 {
563   normal_stop ();
564   cleanup_client ();
565   inferior_ptid = null_ptid;
566   prog_has_started = 0;
567 }
568 
569 static void
570 go32_kill_inferior (void)
571 {
572   redir_cmdline_delete (&child_cmd);
573   resume_signal = -1;
574   resume_is_step = 0;
575   unpush_target (&go32_ops);
576 }
577 
578 static void
579 go32_create_inferior (char *exec_file, char *args, char **env, int from_tty)
580 {
581   extern char **environ;
582   jmp_buf start_state;
583   char *cmdline;
584   char **env_save = environ;
585   size_t cmdlen;
586 
587   /* If no exec file handed to us, get it from the exec-file command -- with
588      a good, common error message if none is specified.  */
589   if (exec_file == 0)
590     exec_file = get_exec_file (1);
591 
592   if (prog_has_started)
593     {
594       go32_stop ();
595       go32_kill_inferior ();
596     }
597   resume_signal = -1;
598   resume_is_step = 0;
599 
600   /* Initialize child's cwd as empty to be initialized when starting
601      the child.  */
602   *child_cwd = 0;
603 
604   /* Init command line storage.  */
605   if (redir_debug_init (&child_cmd) == -1)
606     internal_error (__FILE__, __LINE__,
607 		    "Cannot allocate redirection storage: not enough memory.\n");
608 
609   /* Parse the command line and create redirections.  */
610   if (strpbrk (args, "<>"))
611     {
612       if (redir_cmdline_parse (args, &child_cmd) == 0)
613 	args = child_cmd.command;
614       else
615 	error ("Syntax error in command line.");
616     }
617   else
618     child_cmd.command = xstrdup (args);
619 
620   cmdlen = strlen (args);
621   /* v2loadimage passes command lines via DOS memory, so it cannot
622      possibly handle commands longer than 1MB.  */
623   if (cmdlen > 1024*1024)
624     error ("Command line too long.");
625 
626   cmdline = xmalloc (cmdlen + 4);
627   strcpy (cmdline + 1, args);
628   /* If the command-line length fits into DOS 126-char limits, use the
629      DOS command tail format; otherwise, tell v2loadimage to pass it
630      through a buffer in conventional memory.  */
631   if (cmdlen < 127)
632     {
633       cmdline[0] = strlen (args);
634       cmdline[cmdlen + 1] = 13;
635     }
636   else
637     cmdline[0] = 0xff;	/* signal v2loadimage it's a long command */
638 
639   environ = env;
640 
641   if (v2loadimage (exec_file, cmdline, start_state))
642     {
643       environ = env_save;
644       printf_unfiltered ("Load failed for image %s\n", exec_file);
645       exit (1);
646     }
647   environ = env_save;
648   xfree (cmdline);
649 
650   edi_init (start_state);
651 #if __DJGPP_MINOR__ < 3
652   save_npx ();
653 #endif
654 
655   inferior_ptid = pid_to_ptid (SOME_PID);
656   push_target (&go32_ops);
657   clear_proceed_status ();
658   insert_breakpoints ();
659   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
660   prog_has_started = 1;
661 }
662 
663 static void
664 go32_mourn_inferior (void)
665 {
666   /* We need to make sure all the breakpoint enable bits in the DR7
667      register are reset when the inferior exits.  Otherwise, if they
668      rerun the inferior, the uncleared bits may cause random SIGTRAPs,
669      failure to set more watchpoints, and other calamities.  It would
670      be nice if GDB itself would take care to remove all breakpoints
671      at all times, but it doesn't, probably under an assumption that
672      the OS cleans up when the debuggee exits.  */
673   i386_cleanup_dregs ();
674   go32_kill_inferior ();
675   generic_mourn_inferior ();
676 }
677 
678 static int
679 go32_can_run (void)
680 {
681   return 1;
682 }
683 
684 /* Hardware watchpoint support.  */
685 
686 #define D_REGS edi.dr
687 #define CONTROL D_REGS[7]
688 #define STATUS D_REGS[6]
689 
690 /* Pass the address ADDR to the inferior in the I'th debug register.
691    Here we just store the address in D_REGS, the watchpoint will be
692    actually set up when go32_wait runs the debuggee.  */
693 void
694 go32_set_dr (int i, CORE_ADDR addr)
695 {
696   if (i < 0 || i > 3)
697     internal_error (__FILE__, __LINE__,
698 		    "Invalid register %d in go32_set_dr.\n", i);
699   D_REGS[i] = addr;
700 }
701 
702 /* Pass the value VAL to the inferior in the DR7 debug control
703    register.  Here we just store the address in D_REGS, the watchpoint
704    will be actually set up when go32_wait runs the debuggee.  */
705 void
706 go32_set_dr7 (unsigned val)
707 {
708   CONTROL = val;
709 }
710 
711 /* Get the value of the DR6 debug status register from the inferior.
712    Here we just return the value stored in D_REGS, as we've got it
713    from the last go32_wait call.  */
714 unsigned
715 go32_get_dr6 (void)
716 {
717   return STATUS;
718 }
719 
720 /* Put the device open on handle FD into either raw or cooked
721    mode, return 1 if it was in raw mode, zero otherwise.  */
722 
723 static int
724 device_mode (int fd, int raw_p)
725 {
726   int oldmode, newmode;
727   __dpmi_regs regs;
728 
729   regs.x.ax = 0x4400;
730   regs.x.bx = fd;
731   __dpmi_int (0x21, &regs);
732   if (regs.x.flags & 1)
733     return -1;
734   newmode = oldmode = regs.x.dx;
735 
736   if (raw_p)
737     newmode |= 0x20;
738   else
739     newmode &= ~0x20;
740 
741   if (oldmode & 0x80)	/* Only for character dev */
742   {
743     regs.x.ax = 0x4401;
744     regs.x.bx = fd;
745     regs.x.dx = newmode & 0xff;   /* Force upper byte zero, else it fails */
746     __dpmi_int (0x21, &regs);
747     if (regs.x.flags & 1)
748       return -1;
749   }
750   return (oldmode & 0x20) == 0x20;
751 }
752 
753 
754 static int inf_mode_valid = 0;
755 static int inf_terminal_mode;
756 
757 /* This semaphore is needed because, amazingly enough, GDB calls
758    target.to_terminal_ours more than once after the inferior stops.
759    But we need the information from the first call only, since the
760    second call will always see GDB's own cooked terminal.  */
761 static int terminal_is_ours = 1;
762 
763 static void
764 go32_terminal_init (void)
765 {
766   inf_mode_valid = 0;	/* reinitialize, in case they are restarting child */
767   terminal_is_ours = 1;
768 }
769 
770 static void
771 go32_terminal_info (char *args, int from_tty)
772 {
773   printf_unfiltered ("Inferior's terminal is in %s mode.\n",
774 		     !inf_mode_valid
775 		     ? "default" : inf_terminal_mode ? "raw" : "cooked");
776 
777 #if __DJGPP_MINOR__ > 2
778   if (child_cmd.redirection)
779   {
780     int i;
781 
782     for (i = 0; i < DBG_HANDLES; i++)
783     {
784       if (child_cmd.redirection[i]->file_name)
785 	printf_unfiltered ("\tFile handle %d is redirected to `%s'.\n",
786 			   i, child_cmd.redirection[i]->file_name);
787       else if (_get_dev_info (child_cmd.redirection[i]->inf_handle) == -1)
788 	printf_unfiltered
789 	  ("\tFile handle %d appears to be closed by inferior.\n", i);
790       /* Mask off the raw/cooked bit when comparing device info words.  */
791       else if ((_get_dev_info (child_cmd.redirection[i]->inf_handle) & 0xdf)
792 	       != (_get_dev_info (i) & 0xdf))
793 	printf_unfiltered
794 	  ("\tFile handle %d appears to be redirected by inferior.\n", i);
795     }
796   }
797 #endif
798 }
799 
800 static void
801 go32_terminal_inferior (void)
802 {
803   /* Redirect standard handles as child wants them.  */
804   errno = 0;
805   if (redir_to_child (&child_cmd) == -1)
806   {
807     redir_to_debugger (&child_cmd);
808     error ("Cannot redirect standard handles for program: %s.",
809 	   safe_strerror (errno));
810   }
811   /* set the console device of the inferior to whatever mode
812      (raw or cooked) we found it last time */
813   if (terminal_is_ours)
814   {
815     if (inf_mode_valid)
816       device_mode (0, inf_terminal_mode);
817     terminal_is_ours = 0;
818   }
819 }
820 
821 static void
822 go32_terminal_ours (void)
823 {
824   /* Switch to cooked mode on the gdb terminal and save the inferior
825      terminal mode to be restored when it is resumed */
826   if (!terminal_is_ours)
827   {
828     inf_terminal_mode = device_mode (0, 0);
829     if (inf_terminal_mode != -1)
830       inf_mode_valid = 1;
831     else
832       /* If device_mode returned -1, we don't know what happens with
833 	 handle 0 anymore, so make the info invalid.  */
834       inf_mode_valid = 0;
835     terminal_is_ours = 1;
836 
837     /* Restore debugger's standard handles.  */
838     errno = 0;
839     if (redir_to_debugger (&child_cmd) == -1)
840     {
841       redir_to_child (&child_cmd);
842       error ("Cannot redirect standard handles for debugger: %s.",
843 	     safe_strerror (errno));
844     }
845   }
846 }
847 
848 static void
849 init_go32_ops (void)
850 {
851   go32_ops.to_shortname = "djgpp";
852   go32_ops.to_longname = "djgpp target process";
853   go32_ops.to_doc =
854     "Program loaded by djgpp, when gdb is used as an external debugger";
855   go32_ops.to_open = go32_open;
856   go32_ops.to_close = go32_close;
857   go32_ops.to_attach = go32_attach;
858   go32_ops.to_detach = go32_detach;
859   go32_ops.to_resume = go32_resume;
860   go32_ops.to_wait = go32_wait;
861   go32_ops.to_fetch_registers = go32_fetch_registers;
862   go32_ops.to_store_registers = go32_store_registers;
863   go32_ops.to_prepare_to_store = go32_prepare_to_store;
864   go32_ops.deprecated_xfer_memory = go32_xfer_memory;
865   go32_ops.to_files_info = go32_files_info;
866   go32_ops.to_insert_breakpoint = memory_insert_breakpoint;
867   go32_ops.to_remove_breakpoint = memory_remove_breakpoint;
868   go32_ops.to_terminal_init = go32_terminal_init;
869   go32_ops.to_terminal_inferior = go32_terminal_inferior;
870   go32_ops.to_terminal_ours_for_output = go32_terminal_ours;
871   go32_ops.to_terminal_ours = go32_terminal_ours;
872   go32_ops.to_terminal_info = go32_terminal_info;
873   go32_ops.to_kill = go32_kill_inferior;
874   go32_ops.to_create_inferior = go32_create_inferior;
875   go32_ops.to_mourn_inferior = go32_mourn_inferior;
876   go32_ops.to_can_run = go32_can_run;
877   go32_ops.to_stop = go32_stop;
878   go32_ops.to_stratum = process_stratum;
879   go32_ops.to_has_all_memory = 1;
880   go32_ops.to_has_memory = 1;
881   go32_ops.to_has_stack = 1;
882   go32_ops.to_has_registers = 1;
883   go32_ops.to_has_execution = 1;
884   go32_ops.to_magic = OPS_MAGIC;
885 
886   /* Initialize child's cwd as empty to be initialized when starting
887      the child.  */
888   *child_cwd = 0;
889 
890   /* Initialize child's command line storage.  */
891   if (redir_debug_init (&child_cmd) == -1)
892     internal_error (__FILE__, __LINE__,
893 		    "Cannot allocate redirection storage: not enough memory.\n");
894 
895   /* We are always processing GCC-compiled programs.  */
896   processing_gcc_compilation = 2;
897 }
898 
899 unsigned short windows_major, windows_minor;
900 
901 /* Compute the version Windows reports via Int 2Fh/AX=1600h.  */
902 static void
903 go32_get_windows_version(void)
904 {
905   __dpmi_regs r;
906 
907   r.x.ax = 0x1600;
908   __dpmi_int(0x2f, &r);
909   if (r.h.al > 2 && r.h.al != 0x80 && r.h.al != 0xff
910       && (r.h.al > 3 || r.h.ah > 0))
911     {
912       windows_major = r.h.al;
913       windows_minor = r.h.ah;
914     }
915   else
916     windows_major = 0xff;	/* meaning no Windows */
917 }
918 
919 /* A subroutine of go32_sysinfo to display memory info.  */
920 static void
921 print_mem (unsigned long datum, const char *header, int in_pages_p)
922 {
923   if (datum != 0xffffffffUL)
924     {
925       if (in_pages_p)
926 	datum <<= 12;
927       puts_filtered (header);
928       if (datum > 1024)
929 	{
930 	  printf_filtered ("%lu KB", datum >> 10);
931 	  if (datum > 1024 * 1024)
932 	    printf_filtered (" (%lu MB)", datum >> 20);
933 	}
934       else
935 	printf_filtered ("%lu Bytes", datum);
936       puts_filtered ("\n");
937     }
938 }
939 
940 /* Display assorted information about the underlying OS.  */
941 static void
942 go32_sysinfo (char *arg, int from_tty)
943 {
944   struct utsname u;
945   char cpuid_vendor[13];
946   unsigned cpuid_max = 0, cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
947   unsigned true_dos_version = _get_dos_version (1);
948   unsigned advertized_dos_version = ((unsigned int)_osmajor << 8) | _osminor;
949   int dpmi_flags;
950   char dpmi_vendor_info[129];
951   int dpmi_vendor_available =
952     __dpmi_get_capabilities (&dpmi_flags, dpmi_vendor_info);
953   __dpmi_version_ret dpmi_version_data;
954   long eflags;
955   __dpmi_free_mem_info mem_info;
956   __dpmi_regs regs;
957 
958   cpuid_vendor[0] = '\0';
959   if (uname (&u))
960     strcpy (u.machine, "Unknown x86");
961   else if (u.machine[0] == 'i' && u.machine[1] > 4)
962     {
963       /* CPUID with EAX = 0 returns the Vendor ID.  */
964       __asm__ __volatile__ ("xorl   %%ebx, %%ebx;"
965 			    "xorl   %%ecx, %%ecx;"
966 			    "xorl   %%edx, %%edx;"
967 			    "movl   $0,    %%eax;"
968 			    "cpuid;"
969 			    "movl   %%ebx,  %0;"
970 			    "movl   %%edx,  %1;"
971 			    "movl   %%ecx,  %2;"
972 			    "movl   %%eax,  %3;"
973 			    : "=m" (cpuid_vendor[0]),
974 			      "=m" (cpuid_vendor[4]),
975 			      "=m" (cpuid_vendor[8]),
976 			      "=m" (cpuid_max)
977 			    :
978 			    : "%eax", "%ebx", "%ecx", "%edx");
979       cpuid_vendor[12] = '\0';
980     }
981 
982   printf_filtered ("CPU Type.......................%s", u.machine);
983   if (cpuid_vendor[0])
984     printf_filtered (" (%s)", cpuid_vendor);
985   puts_filtered ("\n");
986 
987   /* CPUID with EAX = 1 returns processor signature and features.  */
988   if (cpuid_max >= 1)
989     {
990       static char *brand_name[] = {
991 	"",
992 	" Celeron",
993 	" III",
994 	" III Xeon",
995 	"", "", "", "",
996 	" 4"
997       };
998       char cpu_string[80];
999       char cpu_brand[20];
1000       unsigned brand_idx;
1001       int intel_p = strcmp (cpuid_vendor, "GenuineIntel") == 0;
1002       int amd_p = strcmp (cpuid_vendor, "AuthenticAMD") == 0;
1003       unsigned cpu_family, cpu_model;
1004 
1005       __asm__ __volatile__ ("movl   $1, %%eax;"
1006 			    "cpuid;"
1007 			    : "=a" (cpuid_eax),
1008 			      "=b" (cpuid_ebx),
1009 			      "=d" (cpuid_edx)
1010 			    :
1011 			    : "%ecx");
1012       brand_idx = cpuid_ebx & 0xff;
1013       cpu_family = (cpuid_eax >> 8) & 0xf;
1014       cpu_model  = (cpuid_eax >> 4) & 0xf;
1015       cpu_brand[0] = '\0';
1016       if (intel_p)
1017 	{
1018 	  if (brand_idx > 0
1019 	      && brand_idx < sizeof(brand_name)/sizeof(brand_name[0])
1020 	      && *brand_name[brand_idx])
1021 	    strcpy (cpu_brand, brand_name[brand_idx]);
1022 	  else if (cpu_family == 5)
1023 	    {
1024 	      if (((cpuid_eax >> 12) & 3) == 0 && cpu_model == 4)
1025 		strcpy (cpu_brand, " MMX");
1026 	      else if (cpu_model > 1 && ((cpuid_eax >> 12) & 3) == 1)
1027 		strcpy (cpu_brand, " OverDrive");
1028 	      else if (cpu_model > 1 && ((cpuid_eax >> 12) & 3) == 2)
1029 		strcpy (cpu_brand, " Dual");
1030 	    }
1031 	  else if (cpu_family == 6 && cpu_model < 8)
1032 	    {
1033 	      switch (cpu_model)
1034 		{
1035 		  case 1:
1036 		    strcpy (cpu_brand, " Pro");
1037 		    break;
1038 		  case 3:
1039 		    strcpy (cpu_brand, " II");
1040 		    break;
1041 		  case 5:
1042 		    strcpy (cpu_brand, " II Xeon");
1043 		    break;
1044 		  case 6:
1045 		    strcpy (cpu_brand, " Celeron");
1046 		    break;
1047 		  case 7:
1048 		    strcpy (cpu_brand, " III");
1049 		    break;
1050 		}
1051 	    }
1052 	}
1053       else if (amd_p)
1054 	{
1055 	  switch (cpu_family)
1056 	    {
1057 	      case 4:
1058 		strcpy (cpu_brand, "486/5x86");
1059 		break;
1060 	      case 5:
1061 		switch (cpu_model)
1062 		  {
1063 		    case 0:
1064 		    case 1:
1065 		    case 2:
1066 		    case 3:
1067 		      strcpy (cpu_brand, "-K5");
1068 		      break;
1069 		    case 6:
1070 		    case 7:
1071 		      strcpy (cpu_brand, "-K6");
1072 		      break;
1073 		    case 8:
1074 		      strcpy (cpu_brand, "-K6-2");
1075 		      break;
1076 		    case 9:
1077 		      strcpy (cpu_brand, "-K6-III");
1078 		      break;
1079 		  }
1080 		break;
1081 	      case 6:
1082 		switch (cpu_model)
1083 		  {
1084 		    case 1:
1085 		    case 2:
1086 		    case 4:
1087 		      strcpy (cpu_brand, " Athlon");
1088 		      break;
1089 		    case 3:
1090 		      strcpy (cpu_brand, " Duron");
1091 		      break;
1092 		  }
1093 		break;
1094 	    }
1095 	}
1096       sprintf (cpu_string, "%s%s Model %d Stepping %d",
1097 	       intel_p ? "Pentium" : (amd_p ? "AMD" : "ix86"),
1098 	       cpu_brand, cpu_model, cpuid_eax & 0xf);
1099       printfi_filtered (31, "%s\n", cpu_string);
1100       if (((cpuid_edx & (6 | (0x0d << 23))) != 0)
1101 	  || ((cpuid_edx & 1) == 0)
1102 	  || (amd_p && (cpuid_edx & (3 << 30)) != 0))
1103 	{
1104 	  puts_filtered ("CPU Features...................");
1105 	  /* We only list features which might be useful in the DPMI
1106 	     environment.  */
1107 	  if ((cpuid_edx & 1) == 0)
1108 	    puts_filtered ("No FPU "); /* it's unusual to not have an FPU */
1109 	  if ((cpuid_edx & (1 << 1)) != 0)
1110 	    puts_filtered ("VME ");
1111 	  if ((cpuid_edx & (1 << 2)) != 0)
1112 	    puts_filtered ("DE ");
1113 	  if ((cpuid_edx & (1 << 4)) != 0)
1114 	    puts_filtered ("TSC ");
1115 	  if ((cpuid_edx & (1 << 23)) != 0)
1116 	    puts_filtered ("MMX ");
1117 	  if ((cpuid_edx & (1 << 25)) != 0)
1118 	    puts_filtered ("SSE ");
1119 	  if ((cpuid_edx & (1 << 26)) != 0)
1120 	    puts_filtered ("SSE2 ");
1121 	  if (amd_p)
1122 	    {
1123 	      if ((cpuid_edx & (1 << 31)) != 0)
1124 		puts_filtered ("3DNow! ");
1125 	      if ((cpuid_edx & (1 << 30)) != 0)
1126 		puts_filtered ("3DNow!Ext");
1127 	    }
1128 	  puts_filtered ("\n");
1129 	}
1130     }
1131   puts_filtered ("\n");
1132   printf_filtered ("DOS Version....................%s %s.%s",
1133 		   _os_flavor, u.release, u.version);
1134   if (true_dos_version != advertized_dos_version)
1135     printf_filtered (" (disguised as v%d.%d)", _osmajor, _osminor);
1136   puts_filtered ("\n");
1137   if (!windows_major)
1138     go32_get_windows_version ();
1139   if (windows_major != 0xff)
1140     {
1141       const char *windows_flavor;
1142 
1143       printf_filtered ("Windows Version................%d.%02d (Windows ",
1144 		       windows_major, windows_minor);
1145       switch (windows_major)
1146 	{
1147 	  case 3:
1148 	    windows_flavor = "3.X";
1149 	    break;
1150 	  case 4:
1151 	    switch (windows_minor)
1152 	      {
1153 		case 0:
1154 		  windows_flavor = "95, 95A, or 95B";
1155 		  break;
1156 		case 3:
1157 		  windows_flavor = "95B OSR2.1 or 95C OSR2.5";
1158 		  break;
1159 		case 10:
1160 		  windows_flavor = "98 or 98 SE";
1161 		  break;
1162 		case 90:
1163 		  windows_flavor = "ME";
1164 		  break;
1165 		default:
1166 		  windows_flavor = "9X";
1167 		  break;
1168 	      }
1169 	    break;
1170 	  default:
1171 	    windows_flavor = "??";
1172 	    break;
1173 	}
1174       printf_filtered ("%s)\n", windows_flavor);
1175     }
1176   else if (true_dos_version == 0x532 && advertized_dos_version == 0x500)
1177     printf_filtered ("Windows Version................Windows NT or Windows 2000\n");
1178   puts_filtered ("\n");
1179   if (dpmi_vendor_available == 0)
1180     {
1181       /* The DPMI spec says the vendor string should be ASCIIZ, but
1182 	 I don't trust the vendors to follow that...  */
1183       if (!memchr (&dpmi_vendor_info[2], 0, 126))
1184 	dpmi_vendor_info[128] = '\0';
1185       printf_filtered ("DPMI Host......................%s v%d.%d (capabilities: %#x)\n",
1186 		       &dpmi_vendor_info[2],
1187 		       (unsigned)dpmi_vendor_info[0],
1188 		       (unsigned)dpmi_vendor_info[1],
1189 		       ((unsigned)dpmi_flags & 0x7f));
1190     }
1191   __dpmi_get_version (&dpmi_version_data);
1192   printf_filtered ("DPMI Version...................%d.%02d\n",
1193 		   dpmi_version_data.major, dpmi_version_data.minor);
1194   printf_filtered ("DPMI Info......................%s-bit DPMI, with%s Virtual Memory support\n",
1195 		   (dpmi_version_data.flags & 1) ? "32" : "16",
1196 		   (dpmi_version_data.flags & 4) ? "" : "out");
1197   printfi_filtered (31, "Interrupts reflected to %s mode\n",
1198 		   (dpmi_version_data.flags & 2) ? "V86" : "Real");
1199   printfi_filtered (31, "Processor type: i%d86\n",
1200 		   dpmi_version_data.cpu);
1201   printfi_filtered (31, "PIC base interrupt: Master: %#x  Slave: %#x\n",
1202 		   dpmi_version_data.master_pic, dpmi_version_data.slave_pic);
1203 
1204   /* a_tss is only initialized when the debuggee is first run.  */
1205   if (prog_has_started)
1206     {
1207       __asm__ __volatile__ ("pushfl ; popl %0" : "=g" (eflags));
1208       printf_filtered ("Protection.....................Ring %d (in %s), with%s I/O protection\n",
1209 		       a_tss.tss_cs & 3, (a_tss.tss_cs & 4) ? "LDT" : "GDT",
1210 		       (a_tss.tss_cs & 3) > ((eflags >> 12) & 3) ? "" : "out");
1211     }
1212   puts_filtered ("\n");
1213   __dpmi_get_free_memory_information (&mem_info);
1214   print_mem (mem_info.total_number_of_physical_pages,
1215 	     "DPMI Total Physical Memory.....", 1);
1216   print_mem (mem_info.total_number_of_free_pages,
1217 	     "DPMI Free Physical Memory......", 1);
1218   print_mem (mem_info.size_of_paging_file_partition_in_pages,
1219 	     "DPMI Swap Space................", 1);
1220   print_mem (mem_info.linear_address_space_size_in_pages,
1221 	     "DPMI Total Linear Address Size.", 1);
1222   print_mem (mem_info.free_linear_address_space_in_pages,
1223 	     "DPMI Free Linear Address Size..", 1);
1224   print_mem (mem_info.largest_available_free_block_in_bytes,
1225 	     "DPMI Largest Free Memory Block.", 0);
1226 
1227   regs.h.ah = 0x48;
1228   regs.x.bx = 0xffff;
1229   __dpmi_int (0x21, &regs);
1230   print_mem (regs.x.bx << 4, "Free DOS Memory................", 0);
1231   regs.x.ax = 0x5800;
1232   __dpmi_int (0x21, &regs);
1233   if ((regs.x.flags & 1) == 0)
1234     {
1235       static const char *dos_hilo[] = {
1236 	"Low", "", "", "", "High", "", "", "", "High, then Low"
1237       };
1238       static const char *dos_fit[] = {
1239 	"First", "Best", "Last"
1240       };
1241       int hilo_idx = (regs.x.ax >> 4) & 0x0f;
1242       int fit_idx  = regs.x.ax & 0x0f;
1243 
1244       if (hilo_idx > 8)
1245 	hilo_idx = 0;
1246       if (fit_idx > 2)
1247 	fit_idx = 0;
1248       printf_filtered ("DOS Memory Allocation..........%s memory, %s fit\n",
1249 		       dos_hilo[hilo_idx], dos_fit[fit_idx]);
1250       regs.x.ax = 0x5802;
1251       __dpmi_int (0x21, &regs);
1252       if ((regs.x.flags & 1) != 0)
1253 	regs.h.al = 0;
1254       printfi_filtered (31, "UMBs %sin DOS memory chain\n",
1255 			regs.h.al == 0 ? "not " : "");
1256     }
1257 }
1258 
1259 struct seg_descr {
1260   unsigned short limit0          __attribute__((packed));
1261   unsigned short base0           __attribute__((packed));
1262   unsigned char  base1           __attribute__((packed));
1263   unsigned       stype:5         __attribute__((packed));
1264   unsigned       dpl:2           __attribute__((packed));
1265   unsigned       present:1       __attribute__((packed));
1266   unsigned       limit1:4        __attribute__((packed));
1267   unsigned       available:1     __attribute__((packed));
1268   unsigned       dummy:1         __attribute__((packed));
1269   unsigned       bit32:1         __attribute__((packed));
1270   unsigned       page_granular:1 __attribute__((packed));
1271   unsigned char  base2           __attribute__((packed));
1272 };
1273 
1274 struct gate_descr {
1275   unsigned short offset0         __attribute__((packed));
1276   unsigned short selector        __attribute__((packed));
1277   unsigned       param_count:5   __attribute__((packed));
1278   unsigned       dummy:3         __attribute__((packed));
1279   unsigned       stype:5         __attribute__((packed));
1280   unsigned       dpl:2           __attribute__((packed));
1281   unsigned       present:1       __attribute__((packed));
1282   unsigned short offset1         __attribute__((packed));
1283 };
1284 
1285 /* Read LEN bytes starting at logical address ADDR, and put the result
1286    into DEST.  Return 1 if success, zero if not.  */
1287 static int
1288 read_memory_region (unsigned long addr, void *dest, size_t len)
1289 {
1290   unsigned long dos_ds_limit = __dpmi_get_segment_limit (_dos_ds);
1291   int retval = 1;
1292 
1293   /* For the low memory, we can simply use _dos_ds.  */
1294   if (addr <= dos_ds_limit - len)
1295     dosmemget (addr, len, dest);
1296   else
1297     {
1298       /* For memory above 1MB we need to set up a special segment to
1299 	 be able to access that memory.  */
1300       int sel = __dpmi_allocate_ldt_descriptors (1);
1301 
1302       if (sel <= 0)
1303 	retval = 0;
1304       else
1305 	{
1306 	  int access_rights = __dpmi_get_descriptor_access_rights (sel);
1307 	  size_t segment_limit = len - 1;
1308 
1309 	  /* Make sure the crucial bits in the descriptor access
1310 	     rights are set correctly.  Some DPMI providers might barf
1311 	     if we set the segment limit to something that is not an
1312 	     integral multiple of 4KB pages if the granularity bit is
1313 	     not set to byte-granular, even though the DPMI spec says
1314 	     it's the host's responsibility to set that bit correctly.  */
1315 	  if (len > 1024 * 1024)
1316 	    {
1317 	      access_rights |= 0x8000;
1318 	      /* Page-granular segments should have the low 12 bits of
1319 		 the limit set.  */
1320 	      segment_limit |= 0xfff;
1321 	    }
1322 	  else
1323 	    access_rights &= ~0x8000;
1324 
1325 	  if (__dpmi_set_segment_base_address (sel, addr) != -1
1326 	      && __dpmi_set_descriptor_access_rights (sel, access_rights) != -1
1327 	      && __dpmi_set_segment_limit (sel, segment_limit) != -1
1328 	      /* W2K silently fails to set the segment limit, leaving
1329 		 it at zero; this test avoids the resulting crash.  */
1330 	      && __dpmi_get_segment_limit (sel) >= segment_limit)
1331 	    movedata (sel, 0, _my_ds (), (unsigned)dest, len);
1332 	  else
1333 	    retval = 0;
1334 
1335 	  __dpmi_free_ldt_descriptor (sel);
1336 	}
1337     }
1338   return retval;
1339 }
1340 
1341 /* Get a segment descriptor stored at index IDX in the descriptor
1342    table whose base address is TABLE_BASE.  Return the descriptor
1343    type, or -1 if failure.  */
1344 static int
1345 get_descriptor (unsigned long table_base, int idx, void *descr)
1346 {
1347   unsigned long addr = table_base + idx * 8; /* 8 bytes per entry */
1348 
1349   if (read_memory_region (addr, descr, 8))
1350     return (int)((struct seg_descr *)descr)->stype;
1351   return -1;
1352 }
1353 
1354 struct dtr_reg {
1355   unsigned short limit __attribute__((packed));
1356   unsigned long  base  __attribute__((packed));
1357 };
1358 
1359 /* Display a segment descriptor stored at index IDX in a descriptor
1360    table whose type is TYPE and whose base address is BASE_ADDR.  If
1361    FORCE is non-zero, display even invalid descriptors.  */
1362 static void
1363 display_descriptor (unsigned type, unsigned long base_addr, int idx, int force)
1364 {
1365   struct seg_descr descr;
1366   struct gate_descr gate;
1367 
1368   /* Get the descriptor from the table.  */
1369   if (idx == 0 && type == 0)
1370     puts_filtered ("0x000: null descriptor\n");
1371   else if (get_descriptor (base_addr, idx, &descr) != -1)
1372     {
1373       /* For each type of descriptor table, this has a bit set if the
1374 	 corresponding type of selectors is valid in that table.  */
1375       static unsigned allowed_descriptors[] = {
1376 	  0xffffdafeL,   /* GDT */
1377 	  0x0000c0e0L,   /* IDT */
1378 	  0xffffdafaL    /* LDT */
1379       };
1380 
1381       /* If the program hasn't started yet, assume the debuggee will
1382 	 have the same CPL as the debugger.  */
1383       int cpl = prog_has_started ? (a_tss.tss_cs & 3) : _my_cs () & 3;
1384       unsigned long limit = (descr.limit1 << 16) | descr.limit0;
1385 
1386       if (descr.present
1387 	  && (allowed_descriptors[type] & (1 << descr.stype)) != 0)
1388 	{
1389 	  printf_filtered ("0x%03x: ",
1390 			   type == 1
1391 			   ? idx : (idx * 8) | (type ? (cpl | 4) : 0));
1392 	  if (descr.page_granular)
1393 	    limit = (limit << 12) | 0xfff; /* big segment: low 12 bit set */
1394 	  if (descr.stype == 1 || descr.stype == 2 || descr.stype == 3
1395 	      || descr.stype == 9 || descr.stype == 11
1396 	      || (descr.stype >= 16 && descr.stype < 32))
1397 	    printf_filtered ("base=0x%02x%02x%04x limit=0x%08lx",
1398 			     descr.base2, descr.base1, descr.base0, limit);
1399 
1400 	  switch (descr.stype)
1401 	    {
1402 	      case 1:
1403 	      case 3:
1404 		printf_filtered (" 16-bit TSS  (task %sactive)",
1405 				 descr.stype == 3 ? "" : "in");
1406 		break;
1407 	      case 2:
1408 		puts_filtered (" LDT");
1409 		break;
1410 	      case 4:
1411 		memcpy (&gate, &descr, sizeof gate);
1412 		printf_filtered ("selector=0x%04x  offs=0x%04x%04x",
1413 				 gate.selector, gate.offset1, gate.offset0);
1414 		printf_filtered (" 16-bit Call Gate (params=%d)",
1415 				 gate.param_count);
1416 		break;
1417 	      case 5:
1418 		printf_filtered ("TSS selector=0x%04x", descr.base0);
1419 		printfi_filtered (16, "Task Gate");
1420 		break;
1421 	      case 6:
1422 	      case 7:
1423 		memcpy (&gate, &descr, sizeof gate);
1424 		printf_filtered ("selector=0x%04x  offs=0x%04x%04x",
1425 				 gate.selector, gate.offset1, gate.offset0);
1426 		printf_filtered (" 16-bit %s Gate",
1427 				 descr.stype == 6 ? "Interrupt" : "Trap");
1428 		break;
1429 	      case 9:
1430 	      case 11:
1431 		printf_filtered (" 32-bit TSS (task %sactive)",
1432 				 descr.stype == 3 ? "" : "in");
1433 		break;
1434 	      case 12:
1435 		memcpy (&gate, &descr, sizeof gate);
1436 		printf_filtered ("selector=0x%04x  offs=0x%04x%04x",
1437 				 gate.selector, gate.offset1, gate.offset0);
1438 		printf_filtered (" 32-bit Call Gate (params=%d)",
1439 				 gate.param_count);
1440 		break;
1441 	      case 14:
1442 	      case 15:
1443 		memcpy (&gate, &descr, sizeof gate);
1444 		printf_filtered ("selector=0x%04x  offs=0x%04x%04x",
1445 				 gate.selector, gate.offset1, gate.offset0);
1446 		printf_filtered (" 32-bit %s Gate",
1447 				 descr.stype == 14 ? "Interrupt" : "Trap");
1448 		break;
1449 	      case 16:		/* data segments */
1450 	      case 17:
1451 	      case 18:
1452 	      case 19:
1453 	      case 20:
1454 	      case 21:
1455 	      case 22:
1456 	      case 23:
1457 		printf_filtered (" %s-bit Data (%s Exp-%s%s)",
1458 				 descr.bit32 ? "32" : "16",
1459 				 descr.stype & 2 ? "Read/Write," : "Read-Only, ",
1460 				 descr.stype & 4 ? "down" : "up",
1461 				 descr.stype & 1 ? "" : ", N.Acc");
1462 		break;
1463 	      case 24:		/* code segments */
1464 	      case 25:
1465 	      case 26:
1466 	      case 27:
1467 	      case 28:
1468 	      case 29:
1469 	      case 30:
1470 	      case 31:
1471 		printf_filtered (" %s-bit Code (%s,  %sConf%s)",
1472 				 descr.bit32 ? "32" : "16",
1473 				 descr.stype & 2 ? "Exec/Read" : "Exec-Only",
1474 				 descr.stype & 4 ? "" : "N.",
1475 				 descr.stype & 1 ? "" : ", N.Acc");
1476 		break;
1477 	      default:
1478 		printf_filtered ("Unknown type 0x%02x", descr.stype);
1479 		break;
1480 	    }
1481 	  puts_filtered ("\n");
1482 	}
1483       else if (force)
1484 	{
1485 	  printf_filtered ("0x%03x: ",
1486 			   type == 1
1487 			   ? idx : (idx * 8) | (type ? (cpl | 4) : 0));
1488 	  if (!descr.present)
1489 	    puts_filtered ("Segment not present\n");
1490 	  else
1491 	    printf_filtered ("Segment type 0x%02x is invalid in this table\n",
1492 			     descr.stype);
1493 	}
1494     }
1495   else if (force)
1496     printf_filtered ("0x%03x: Cannot read this descriptor\n", idx);
1497 }
1498 
1499 static void
1500 go32_sldt (char *arg, int from_tty)
1501 {
1502   struct dtr_reg gdtr;
1503   unsigned short ldtr = 0;
1504   int ldt_idx;
1505   struct seg_descr ldt_descr;
1506   long ldt_entry = -1L;
1507   int cpl = (prog_has_started ? a_tss.tss_cs : _my_cs ()) & 3;
1508 
1509   if (arg && *arg)
1510     {
1511       while (*arg && isspace(*arg))
1512 	arg++;
1513 
1514       if (*arg)
1515 	{
1516 	  ldt_entry = parse_and_eval_long (arg);
1517 	  if (ldt_entry < 0
1518 	      || (ldt_entry & 4) == 0
1519 	      || (ldt_entry & 3) != (cpl & 3))
1520 	    error ("Invalid LDT entry 0x%03lx.", (unsigned long)ldt_entry);
1521 	}
1522     }
1523 
1524   __asm__ __volatile__ ("sgdt   %0" : "=m" (gdtr) : /* no inputs */ );
1525   __asm__ __volatile__ ("sldt   %0" : "=m" (ldtr) : /* no inputs */ );
1526   ldt_idx = ldtr / 8;
1527   if (ldt_idx == 0)
1528     puts_filtered ("There is no LDT.\n");
1529   /* LDT's entry in the GDT must have the type LDT, which is 2.  */
1530   else if (get_descriptor (gdtr.base, ldt_idx, &ldt_descr) != 2)
1531     printf_filtered ("LDT is present (at %#x), but unreadable by GDB.\n",
1532 		     ldt_descr.base0
1533 		     | (ldt_descr.base1 << 16)
1534 		     | (ldt_descr.base2 << 24));
1535   else
1536     {
1537       unsigned base =
1538 	ldt_descr.base0
1539 	| (ldt_descr.base1 << 16)
1540 	| (ldt_descr.base2 << 24);
1541       unsigned limit = ldt_descr.limit0 | (ldt_descr.limit1 << 16);
1542       int max_entry;
1543 
1544       if (ldt_descr.page_granular)
1545 	/* Page-granular segments must have the low 12 bits of their
1546 	   limit set.  */
1547 	limit = (limit << 12) | 0xfff;
1548       /* LDT cannot have more than 8K 8-byte entries, i.e. more than
1549 	 64KB.  */
1550       if (limit > 0xffff)
1551 	limit = 0xffff;
1552 
1553       max_entry = (limit + 1) / 8;
1554 
1555       if (ldt_entry >= 0)
1556 	{
1557 	  if (ldt_entry > limit)
1558 	    error ("Invalid LDT entry %#lx: outside valid limits [0..%#x]",
1559 		   (unsigned long)ldt_entry, limit);
1560 
1561 	  display_descriptor (ldt_descr.stype, base, ldt_entry / 8, 1);
1562 	}
1563       else
1564 	{
1565 	  int i;
1566 
1567 	  for (i = 0; i < max_entry; i++)
1568 	    display_descriptor (ldt_descr.stype, base, i, 0);
1569 	}
1570     }
1571 }
1572 
1573 static void
1574 go32_sgdt (char *arg, int from_tty)
1575 {
1576   struct dtr_reg gdtr;
1577   long gdt_entry = -1L;
1578   int max_entry;
1579 
1580   if (arg && *arg)
1581     {
1582       while (*arg && isspace(*arg))
1583 	arg++;
1584 
1585       if (*arg)
1586 	{
1587 	  gdt_entry = parse_and_eval_long (arg);
1588 	  if (gdt_entry < 0 || (gdt_entry & 7) != 0)
1589 	    error ("Invalid GDT entry 0x%03lx: not an integral multiple of 8.",
1590 		   (unsigned long)gdt_entry);
1591 	}
1592     }
1593 
1594   __asm__ __volatile__ ("sgdt   %0" : "=m" (gdtr) : /* no inputs */ );
1595   max_entry = (gdtr.limit + 1) / 8;
1596 
1597   if (gdt_entry >= 0)
1598     {
1599       if (gdt_entry > gdtr.limit)
1600 	error ("Invalid GDT entry %#lx: outside valid limits [0..%#x]",
1601 	       (unsigned long)gdt_entry, gdtr.limit);
1602 
1603       display_descriptor (0, gdtr.base, gdt_entry / 8, 1);
1604     }
1605   else
1606     {
1607       int i;
1608 
1609       for (i = 0; i < max_entry; i++)
1610 	display_descriptor (0, gdtr.base, i, 0);
1611     }
1612 }
1613 
1614 static void
1615 go32_sidt (char *arg, int from_tty)
1616 {
1617   struct dtr_reg idtr;
1618   long idt_entry = -1L;
1619   int max_entry;
1620 
1621   if (arg && *arg)
1622     {
1623       while (*arg && isspace(*arg))
1624 	arg++;
1625 
1626       if (*arg)
1627 	{
1628 	  idt_entry = parse_and_eval_long (arg);
1629 	  if (idt_entry < 0)
1630 	    error ("Invalid (negative) IDT entry %ld.", idt_entry);
1631 	}
1632     }
1633 
1634   __asm__ __volatile__ ("sidt   %0" : "=m" (idtr) : /* no inputs */ );
1635   max_entry = (idtr.limit + 1) / 8;
1636   if (max_entry > 0x100)	/* no more than 256 entries */
1637     max_entry = 0x100;
1638 
1639   if (idt_entry >= 0)
1640     {
1641       if (idt_entry > idtr.limit)
1642 	error ("Invalid IDT entry %#lx: outside valid limits [0..%#x]",
1643 	       (unsigned long)idt_entry, idtr.limit);
1644 
1645       display_descriptor (1, idtr.base, idt_entry, 1);
1646     }
1647   else
1648     {
1649       int i;
1650 
1651       for (i = 0; i < max_entry; i++)
1652 	display_descriptor (1, idtr.base, i, 0);
1653     }
1654 }
1655 
1656 /* Cached linear address of the base of the page directory.  For
1657    now, available only under CWSDPMI.  Code based on ideas and
1658    suggestions from Charles Sandmann <sandmann@clio.rice.edu>.  */
1659 static unsigned long pdbr;
1660 
1661 static unsigned long
1662 get_cr3 (void)
1663 {
1664   unsigned offset;
1665   unsigned taskreg;
1666   unsigned long taskbase, cr3;
1667   struct dtr_reg gdtr;
1668 
1669   if (pdbr > 0 && pdbr <= 0xfffff)
1670     return pdbr;
1671 
1672   /* Get the linear address of GDT and the Task Register.  */
1673   __asm__ __volatile__ ("sgdt   %0" : "=m" (gdtr) : /* no inputs */ );
1674   __asm__ __volatile__ ("str    %0" : "=m" (taskreg) : /* no inputs */ );
1675 
1676   /* Task Register is a segment selector for the TSS of the current
1677      task.  Therefore, it can be used as an index into the GDT to get
1678      at the segment descriptor for the TSS.  To get the index, reset
1679      the low 3 bits of the selector (which give the CPL).  Add 2 to the
1680      offset to point to the 3 low bytes of the base address.  */
1681   offset = gdtr.base + (taskreg & 0xfff8) + 2;
1682 
1683 
1684   /* CWSDPMI's task base is always under the 1MB mark.  */
1685   if (offset > 0xfffff)
1686     return 0;
1687 
1688   _farsetsel (_dos_ds);
1689   taskbase  = _farnspeekl (offset) & 0xffffffU;
1690   taskbase += _farnspeekl (offset + 2) & 0xff000000U;
1691   if (taskbase > 0xfffff)
1692     return 0;
1693 
1694   /* CR3 (a.k.a. PDBR, the Page Directory Base Register) is stored at
1695      offset 1Ch in the TSS.  */
1696   cr3 = _farnspeekl (taskbase + 0x1c) & ~0xfff;
1697   if (cr3 > 0xfffff)
1698     {
1699 #if 0  /* not fullly supported yet */
1700       /* The Page Directory is in UMBs.  In that case, CWSDPMI puts
1701 	 the first Page Table right below the Page Directory.  Thus,
1702 	 the first Page Table's entry for its own address and the Page
1703 	 Directory entry for that Page Table will hold the same
1704 	 physical address.  The loop below searches the entire UMB
1705 	 range of addresses for such an occurence.  */
1706       unsigned long addr, pte_idx;
1707 
1708       for (addr = 0xb0000, pte_idx = 0xb0;
1709 	   pte_idx < 0xff;
1710 	   addr += 0x1000, pte_idx++)
1711 	{
1712 	  if (((_farnspeekl (addr + 4 * pte_idx) & 0xfffff027) ==
1713 	       (_farnspeekl (addr + 0x1000) & 0xfffff027))
1714 	      && ((_farnspeekl (addr + 4 * pte_idx + 4) & 0xfffff000) == cr3))
1715 	    {
1716 	      cr3 = addr + 0x1000;
1717 	      break;
1718 	    }
1719 	}
1720 #endif
1721 
1722       if (cr3 > 0xfffff)
1723 	cr3 = 0;
1724     }
1725 
1726   return cr3;
1727 }
1728 
1729 /* Return the N'th Page Directory entry.  */
1730 static unsigned long
1731 get_pde (int n)
1732 {
1733   unsigned long pde = 0;
1734 
1735   if (pdbr && n >= 0 && n < 1024)
1736     {
1737       pde = _farpeekl (_dos_ds, pdbr + 4*n);
1738     }
1739   return pde;
1740 }
1741 
1742 /* Return the N'th entry of the Page Table whose Page Directory entry
1743    is PDE.  */
1744 static unsigned long
1745 get_pte (unsigned long pde, int n)
1746 {
1747   unsigned long pte = 0;
1748 
1749   /* pde & 0x80 tests the 4MB page bit.  We don't support 4MB
1750      page tables, for now.  */
1751   if ((pde & 1) && !(pde & 0x80) && n >= 0 && n < 1024)
1752     {
1753       pde &= ~0xfff;	/* clear non-address bits */
1754       pte = _farpeekl (_dos_ds, pde + 4*n);
1755     }
1756   return pte;
1757 }
1758 
1759 /* Display a Page Directory or Page Table entry.  IS_DIR, if non-zero,
1760    says this is a Page Directory entry.  If FORCE is non-zero, display
1761    the entry even if its Present flag is off.  OFF is the offset of the
1762    address from the page's base address.  */
1763 static void
1764 display_ptable_entry (unsigned long entry, int is_dir, int force, unsigned off)
1765 {
1766   if ((entry & 1) != 0)
1767     {
1768       printf_filtered ("Base=0x%05lx000", entry >> 12);
1769       if ((entry & 0x100) && !is_dir)
1770 	puts_filtered (" Global");
1771       if ((entry & 0x40) && !is_dir)
1772 	puts_filtered (" Dirty");
1773       printf_filtered (" %sAcc.", (entry & 0x20) ? "" : "Not-");
1774       printf_filtered (" %sCached", (entry & 0x10) ? "" : "Not-");
1775       printf_filtered (" Write-%s", (entry & 8) ? "Thru" : "Back");
1776       printf_filtered (" %s", (entry & 4) ? "Usr" : "Sup");
1777       printf_filtered (" Read-%s", (entry & 2) ? "Write" : "Only");
1778       if (off)
1779 	printf_filtered (" +0x%x", off);
1780       puts_filtered ("\n");
1781     }
1782   else if (force)
1783     printf_filtered ("Page%s not present or not supported; value=0x%lx.\n",
1784 		     is_dir ? " Table" : "", entry >> 1);
1785 }
1786 
1787 static void
1788 go32_pde (char *arg, int from_tty)
1789 {
1790   long pde_idx = -1, i;
1791 
1792   if (arg && *arg)
1793     {
1794       while (*arg && isspace(*arg))
1795 	arg++;
1796 
1797       if (*arg)
1798 	{
1799 	  pde_idx = parse_and_eval_long (arg);
1800 	  if (pde_idx < 0 || pde_idx >= 1024)
1801 	    error ("Entry %ld is outside valid limits [0..1023].", pde_idx);
1802 	}
1803     }
1804 
1805   pdbr = get_cr3 ();
1806   if (!pdbr)
1807     puts_filtered ("Access to Page Directories is not supported on this system.\n");
1808   else if (pde_idx >= 0)
1809     display_ptable_entry (get_pde (pde_idx), 1, 1, 0);
1810   else
1811     for (i = 0; i < 1024; i++)
1812       display_ptable_entry (get_pde (i), 1, 0, 0);
1813 }
1814 
1815 /* A helper function to display entries in a Page Table pointed to by
1816    the N'th entry in the Page Directory.  If FORCE is non-zero, say
1817    something even if the Page Table is not accessible.  */
1818 static void
1819 display_page_table (long n, int force)
1820 {
1821   unsigned long pde = get_pde (n);
1822 
1823   if ((pde & 1) != 0)
1824     {
1825       int i;
1826 
1827       printf_filtered ("Page Table pointed to by Page Directory entry 0x%lx:\n", n);
1828       for (i = 0; i < 1024; i++)
1829 	display_ptable_entry (get_pte (pde, i), 0, 0, 0);
1830       puts_filtered ("\n");
1831     }
1832   else if (force)
1833     printf_filtered ("Page Table not present; value=0x%lx.\n", pde >> 1);
1834 }
1835 
1836 static void
1837 go32_pte (char *arg, int from_tty)
1838 {
1839   long pde_idx = -1L, i;
1840 
1841   if (arg && *arg)
1842     {
1843       while (*arg && isspace(*arg))
1844 	arg++;
1845 
1846       if (*arg)
1847 	{
1848 	  pde_idx = parse_and_eval_long (arg);
1849 	  if (pde_idx < 0 || pde_idx >= 1024)
1850 	    error ("Entry %ld is outside valid limits [0..1023].", pde_idx);
1851 	}
1852     }
1853 
1854   pdbr = get_cr3 ();
1855   if (!pdbr)
1856     puts_filtered ("Access to Page Tables is not supported on this system.\n");
1857   else if (pde_idx >= 0)
1858     display_page_table (pde_idx, 1);
1859   else
1860     for (i = 0; i < 1024; i++)
1861       display_page_table (i, 0);
1862 }
1863 
1864 static void
1865 go32_pte_for_address (char *arg, int from_tty)
1866 {
1867   CORE_ADDR addr = 0, i;
1868 
1869   if (arg && *arg)
1870     {
1871       while (*arg && isspace(*arg))
1872 	arg++;
1873 
1874       if (*arg)
1875 	addr = parse_and_eval_address (arg);
1876     }
1877   if (!addr)
1878     error_no_arg ("linear address");
1879 
1880   pdbr = get_cr3 ();
1881   if (!pdbr)
1882     puts_filtered ("Access to Page Tables is not supported on this system.\n");
1883   else
1884     {
1885       int pde_idx = (addr >> 22) & 0x3ff;
1886       int pte_idx = (addr >> 12) & 0x3ff;
1887       unsigned offs = addr & 0xfff;
1888 
1889       printf_filtered ("Page Table entry for address 0x%llx:\n",
1890 		       (unsigned long long)addr);
1891       display_ptable_entry (get_pte (get_pde (pde_idx), pte_idx), 0, 1, offs);
1892     }
1893 }
1894 
1895 static struct cmd_list_element *info_dos_cmdlist = NULL;
1896 
1897 static void
1898 go32_info_dos_command (char *args, int from_tty)
1899 {
1900   help_list (info_dos_cmdlist, "info dos ", class_info, gdb_stdout);
1901 }
1902 
1903 void
1904 _initialize_go32_nat (void)
1905 {
1906   init_go32_ops ();
1907   add_target (&go32_ops);
1908 
1909   add_prefix_cmd ("dos", class_info, go32_info_dos_command,
1910 		  "Print information specific to DJGPP (aka MS-DOS) debugging.",
1911 		  &info_dos_cmdlist, "info dos ", 0, &infolist);
1912 
1913   add_cmd ("sysinfo", class_info, go32_sysinfo,
1914 	    "Display information about the target system, including CPU, OS, DPMI, etc.",
1915 	   &info_dos_cmdlist);
1916   add_cmd ("ldt", class_info, go32_sldt,
1917 	   "Display entries in the LDT (Local Descriptor Table).\n"
1918 	   "Entry number (an expression) as an argument means display only that entry.",
1919 	   &info_dos_cmdlist);
1920   add_cmd ("gdt", class_info, go32_sgdt,
1921 	   "Display entries in the GDT (Global Descriptor Table).\n"
1922 	   "Entry number (an expression) as an argument means display only that entry.",
1923 	   &info_dos_cmdlist);
1924   add_cmd ("idt", class_info, go32_sidt,
1925 	   "Display entries in the IDT (Interrupt Descriptor Table).\n"
1926 	   "Entry number (an expression) as an argument means display only that entry.",
1927 	   &info_dos_cmdlist);
1928   add_cmd ("pde", class_info, go32_pde,
1929 	   "Display entries in the Page Directory.\n"
1930 	   "Entry number (an expression) as an argument means display only that entry.",
1931 	   &info_dos_cmdlist);
1932   add_cmd ("pte", class_info, go32_pte,
1933 	   "Display entries in Page Tables.\n"
1934 	   "Entry number (an expression) as an argument means display only entries\n"
1935 	   "from the Page Table pointed to by the specified Page Directory entry.",
1936 	   &info_dos_cmdlist);
1937   add_cmd ("address-pte", class_info, go32_pte_for_address,
1938 	   "Display a Page Table entry for a linear address.\n"
1939 	   "The address argument must be a linear address, after adding to\n"
1940 	   "it the base address of the appropriate segment.\n"
1941 	   "The base address of variables and functions in the debuggee's data\n"
1942 	   "or code segment is stored in the variable __djgpp_base_address,\n"
1943 	   "so use `__djgpp_base_address + (char *)&var' as the argument.\n"
1944 	   "For other segments, look up their base address in the output of\n"
1945 	   "the `info dos ldt' command.",
1946 	   &info_dos_cmdlist);
1947 }
1948 
1949 pid_t
1950 tcgetpgrp (int fd)
1951 {
1952   if (isatty (fd))
1953     return SOME_PID;
1954   errno = ENOTTY;
1955   return -1;
1956 }
1957 
1958 int
1959 tcsetpgrp (int fd, pid_t pgid)
1960 {
1961   if (isatty (fd) && pgid == SOME_PID)
1962     return 0;
1963   errno = pgid == SOME_PID ? ENOTTY : ENOSYS;
1964   return -1;
1965 }
1966