xref: /freebsd-12.1/contrib/gdb/gdb/go32-nat.c (revision f759f848)
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
save_npx(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
load_npx(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
redir_cmdline_delete(cmdline_t * ptr)129 redir_cmdline_delete (cmdline_t *ptr)
130 {
131   ptr->redirected = 0;
132 }
133 
134 int
redir_cmdline_parse(const char * args,cmdline_t * ptr)135 redir_cmdline_parse (const char *args, cmdline_t *ptr)
136 {
137   return -1;
138 }
139 
140 int
redir_to_child(cmdline_t * ptr)141 redir_to_child (cmdline_t *ptr)
142 {
143   return 1;
144 }
145 
146 int
redir_to_debugger(cmdline_t * ptr)147 redir_to_debugger (cmdline_t *ptr)
148 {
149   return 1;
150 }
151 
152 int
redir_debug_init(cmdline_t * ptr)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
go32_open(char * name,int from_tty)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
go32_close(int quitting)303 go32_close (int quitting)
304 {
305 }
306 
307 static void
go32_attach(char * args,int from_tty)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
go32_detach(char * args,int from_tty)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
go32_resume(ptid_t ptid,int step,enum target_signal siggnal)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
go32_wait(ptid_t ptid,struct target_waitstatus * status)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
fetch_register(int regno)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 (i386_fp_regnum_p (regno) || i386_fpc_regnum_p (regno))
471     i387_supply_fsave (current_regcache, regno, &npx);
472   else
473     internal_error (__FILE__, __LINE__,
474 		    "Invalid register no. %d in fetch_register.", regno);
475 }
476 
477 static void
go32_fetch_registers(int regno)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 (current_regcache, -1, &npx);
487     }
488 }
489 
490 static void
store_register(int regno)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 (i386_fp_regnum_p (regno) || i386_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
go32_store_registers(int regno)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
go32_prepare_to_store(void)518 go32_prepare_to_store (void)
519 {
520 }
521 
522 static int
go32_xfer_memory(CORE_ADDR memaddr,char * myaddr,int len,int write,struct mem_attrib * attrib,struct target_ops * target)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
go32_files_info(struct target_ops * target)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
go32_stop(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
go32_kill_inferior(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
go32_create_inferior(char * exec_file,char * args,char ** env)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
go32_mourn_inferior(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
go32_can_run(void)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
go32_set_dr(int i,CORE_ADDR addr)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
go32_set_dr7(unsigned val)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
go32_get_dr6(void)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
device_mode(int fd,int raw_p)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
go32_terminal_init(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
go32_terminal_info(char * args,int from_tty)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
go32_terminal_inferior(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
go32_terminal_ours(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
init_go32_ops(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
go32_get_windows_version(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
print_mem(unsigned long datum,const char * header,int in_pages_p)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
go32_sysinfo(char * arg,int from_tty)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
read_memory_region(unsigned long addr,void * dest,size_t len)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
get_descriptor(unsigned long table_base,int idx,void * descr)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
display_descriptor(unsigned type,unsigned long base_addr,int idx,int force)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
go32_sldt(char * arg,int from_tty)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%03lx.", (unsigned long)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 %#lx: outside valid limits [0..%#x]",
1557 		   (unsigned long)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
go32_sgdt(char * arg,int from_tty)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%03lx: not an integral multiple of 8.",
1588 		   (unsigned long)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 %#lx: outside valid limits [0..%#x]",
1599 	       (unsigned long)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
go32_sidt(char * arg,int from_tty)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 %ld.", 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 %#lx: outside valid limits [0..%#x]",
1641 	       (unsigned long)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 <[email protected]>.  */
1657 static unsigned long pdbr;
1658 
1659 static unsigned long
get_cr3(void)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
get_pde(int n)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
get_pte(unsigned long pde,int n)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
display_ptable_entry(unsigned long entry,int is_dir,int force,unsigned off)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
go32_pde(char * arg,int from_tty)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
display_page_table(long n,int force)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
go32_pte(char * arg,int from_tty)1835 go32_pte (char *arg, int from_tty)
1836 {
1837   long pde_idx = -1L, 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 %ld 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
go32_pte_for_address(char * arg,int from_tty)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
go32_info_dos_command(char * args,int from_tty)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
_initialize_go32_nat(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
tcgetpgrp(int fd)1948 tcgetpgrp (int fd)
1949 {
1950   if (isatty (fd))
1951     return SOME_PID;
1952   errno = ENOTTY;
1953   return -1;
1954 }
1955 
1956 int
tcsetpgrp(int fd,pid_t pgid)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 }
1964