* go32-nat.c (go32_get_windows_version, print_mem, go32_sysinfo)

(read_memory_region, get_descriptor, display_descriptor)
	(go32_sldt, go32_sgdt, go32_sidt): New functions.
	(top-level): Include ctype.h, utsname.h, dos.h, and go32.h.  Ifdef
	away `disable' from dos.h, since breakpoint.h defines an enum
	member of the same name, and GCC 2.7.2 barfs.
	(_initialize_go32_nat): Provide new commands dos-sysinfo, dos-ldt,
	dos-gdt, and dos-idt, all of them in the "info" class
This commit is contained in:
Eli Zaretskii 2001-07-08 10:28:20 +00:00
parent 6cc9a2ee51
commit 10ba702db3
2 changed files with 758 additions and 1 deletions

View File

@ -1,3 +1,14 @@
2001-07-08 Eli Zaretskii <eliz@is.elta.co.il>
* go32-nat.c (go32_get_windows_version, print_mem, go32_sysinfo)
(read_memory_region, get_descriptor, display_descriptor)
(go32_sldt, go32_sgdt, go32_sidt): New functions.
(top-level): Include ctype.h, utsname.h, dos.h, and go32.h. Ifdef
away `disable' from dos.h, since breakpoint.h defines an enum
member of the same name, and GCC 2.7.2 barfs.
(_initialize_go32_nat): Provide new commands dos-sysinfo, dos-ldt,
dos-gdt, and dos-idt, all of them in the "info" class
2001-07-07 Kevin Buettner <kevinb@redhat.com>
* procfs.c (create_procinfo): Allocate space for saved_entryset

View File

@ -33,12 +33,19 @@
#include "regcache.h"
#include "gdb_string.h"
#include <stdio.h> /* required for __DJGPP_MINOR__ */
#include <stdio.h> /* might be required for __DJGPP_MINOR__ */
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <sys/utsname.h>
#include <io.h>
/* breakpoint.h defines `disable' which is an enum member. */
#define disable interrup_disable
#include <dos.h>
#undef disable
#include <dpmi.h>
#include <go32.h>
#include <debug/v2load.h>
#include <debug/dbgcom.h>
#if __DJGPP_MINOR__ > 2
@ -878,11 +885,750 @@ init_go32_ops (void)
processing_gcc_compilation = 2;
}
unsigned short windows_major, windows_minor;
/* Compute the version Windows reports via Int 2Fh/AX=1600h. */
static void
go32_get_windows_version(void)
{
__dpmi_regs r;
r.x.ax = 0x1600;
__dpmi_int(0x2f, &r);
if (r.h.al > 2 && r.h.al != 0x80 && r.h.al != 0xff
&& (r.h.al > 3 || r.h.ah > 0))
{
windows_major = r.h.al;
windows_minor = r.h.ah;
}
else
windows_major = 0xff; /* meaning no Windows */
}
/* A subroutine of go32_sysinfo to display memory info. */
static void
print_mem (unsigned long datum, const char *header, int in_pages_p)
{
if (datum != 0xffffffffUL)
{
if (in_pages_p)
datum <<= 12;
puts_filtered (header);
if (datum > 1024)
{
printf_filtered ("%lu KB", datum >> 10);
if (datum > 1024 * 1024)
printf_filtered (" (%lu MB)", datum >> 20);
}
else
printf_filtered ("%lu Bytes", datum);
puts_filtered ("\n");
}
}
/* Display assorted information about the underlying OS. */
static void
go32_sysinfo (char *arg, int from_tty)
{
struct utsname u;
char cpuid_vendor[13];
unsigned cpuid_max = 0, cpuid_eax, cpuid_ebx, cpuid_ecx, cpuid_edx;
unsigned true_dos_version = _get_dos_version (1);
unsigned advertized_dos_version = ((unsigned int)_osmajor << 8) | _osminor;
int dpmi_flags;
char dpmi_vendor_info[129];
int dpmi_vendor_available =
__dpmi_get_capabilities (&dpmi_flags, dpmi_vendor_info);
__dpmi_version_ret dpmi_version_data;
long eflags;
__dpmi_free_mem_info mem_info;
__dpmi_regs regs;
cpuid_vendor[0] = '\0';
if (uname (&u))
strcpy (u.machine, "Unknown x86");
else if (u.machine[0] == 'i' && u.machine[1] > 4)
{
/* CPUID with EAX = 0 returns the Vendor ID. */
__asm__ __volatile__ ("xorl %%ebx, %%ebx;"
"xorl %%ecx, %%ecx;"
"xorl %%edx, %%edx;"
"movl $0, %%eax;"
"cpuid;"
"movl %%ebx, %0;"
"movl %%edx, %1;"
"movl %%ecx, %2;"
"movl %%eax, %3;"
: "=m" (cpuid_vendor[0]),
"=m" (cpuid_vendor[4]),
"=m" (cpuid_vendor[8]),
"=m" (cpuid_max)
:
: "%eax", "%ebx", "%ecx", "%edx");
cpuid_vendor[12] = '\0';
}
printf_filtered ("CPU Type.......................%s", u.machine);
if (cpuid_vendor[0])
printf_filtered (" (%s)", cpuid_vendor);
puts_filtered ("\n");
/* CPUID with EAX = 1 returns processor signature and features. */
if (cpuid_max >= 1)
{
static char *brand_name[] = {
"",
" Celeron",
" III",
" III Xeon",
"", "", "", "",
" 4"
};
char cpu_string[80];
char cpu_brand[20];
unsigned brand_idx;
int intel_p = strcmp (cpuid_vendor, "GenuineIntel") == 0;
int amd_p = strcmp (cpuid_vendor, "AuthenticAMD") == 0;
unsigned cpu_family, cpu_model;
__asm__ __volatile__ ("movl $1, %%eax;"
"cpuid;"
: "=a" (cpuid_eax),
"=b" (cpuid_ebx),
"=d" (cpuid_edx)
:
: "%ecx");
brand_idx = cpuid_ebx & 0xff;
cpu_family = (cpuid_eax >> 8) & 0xf;
cpu_model = (cpuid_eax >> 4) & 0xf;
cpu_brand[0] = '\0';
if (intel_p)
{
if (brand_idx > 0
&& brand_idx < sizeof(brand_name)/sizeof(brand_name[0])
&& *brand_name[brand_idx])
strcpy (cpu_brand, brand_name[brand_idx]);
else if (cpu_family == 5)
{
if (((cpuid_eax >> 12) & 3) == 0 && cpu_model == 4)
strcpy (cpu_brand, " MMX");
else if (cpu_model > 1 && ((cpuid_eax >> 12) & 3) == 1)
strcpy (cpu_brand, " OverDrive");
else if (cpu_model > 1 && ((cpuid_eax >> 12) & 3) == 2)
strcpy (cpu_brand, " Dual");
}
else if (cpu_family == 6 && cpu_model < 8)
{
switch (cpu_model)
{
case 1:
strcpy (cpu_brand, " Pro");
break;
case 3:
strcpy (cpu_brand, " II");
break;
case 5:
strcpy (cpu_brand, " II Xeon");
break;
case 6:
strcpy (cpu_brand, " Celeron");
break;
case 7:
strcpy (cpu_brand, " III");
break;
}
}
}
else if (amd_p)
{
switch (cpu_family)
{
case 4:
strcpy (cpu_brand, "486/5x86");
break;
case 5:
switch (cpu_model)
{
case 0:
case 1:
case 2:
case 3:
strcpy (cpu_brand, "-K5");
break;
case 6:
case 7:
strcpy (cpu_brand, "-K6");
break;
case 8:
strcpy (cpu_brand, "-K6-2");
break;
case 9:
strcpy (cpu_brand, "-K6-III");
break;
}
break;
case 6:
switch (cpu_model)
{
case 1:
case 2:
case 4:
strcpy (cpu_brand, " Athlon");
break;
case 3:
strcpy (cpu_brand, " Duron");
break;
}
break;
}
}
sprintf (cpu_string, "%s%s Model %d Stepping %d",
intel_p ? "Pentium" : (amd_p ? "AMD" : "ix86"),
cpu_brand, cpu_model, cpuid_eax & 0xf);
printfi_filtered (31, "%s\n", cpu_string);
if (((cpuid_edx & (6 | (0x0d << 23))) != 0)
|| ((cpuid_edx & 1) == 0)
|| (amd_p && (cpuid_edx & (3 << 30)) != 0))
{
puts_filtered ("CPU Features...................");
/* We only list features which might be useful in the DPMI
environment. */
if ((cpuid_edx & 1) == 0)
puts_filtered ("No FPU "); /* it's unusual to not have an FPU */
if ((cpuid_edx & (1 << 1)) != 0)
puts_filtered ("VME ");
if ((cpuid_edx & (1 << 2)) != 0)
puts_filtered ("DE ");
if ((cpuid_edx & (1 << 4)) != 0)
puts_filtered ("TSC ");
if ((cpuid_edx & (1 << 23)) != 0)
puts_filtered ("MMX ");
if ((cpuid_edx & (1 << 25)) != 0)
puts_filtered ("SSE ");
if ((cpuid_edx & (1 << 26)) != 0)
puts_filtered ("SSE2 ");
if (amd_p)
{
if ((cpuid_edx & (1 << 31)) != 0)
puts_filtered ("3DNow! ");
if ((cpuid_edx & (1 << 30)) != 0)
puts_filtered ("3DNow!Ext");
}
puts_filtered ("\n");
}
}
puts_filtered ("\n");
printf_filtered ("DOS Version....................%s %s.%s",
_os_flavor, u.release, u.version);
if (true_dos_version != advertized_dos_version)
printf_filtered (" (disguised as v%d.%d)", _osmajor, _osminor);
puts_filtered ("\n");
if (!windows_major)
go32_get_windows_version ();
if (windows_major != 0xff)
{
const char *windows_flavor;
printf_filtered ("Windows Version................%d.%02d (Windows ",
windows_major, windows_minor);
switch (windows_major)
{
case 3:
windows_flavor = "3.X";
break;
case 4:
switch (windows_minor)
{
case 0:
windows_flavor = "95, 95A, or 95B";
break;
case 3:
windows_flavor = "95B OSR2.1 or 95C OSR2.5";
break;
case 10:
windows_flavor = "98 or 98 SE";
break;
case 90:
windows_flavor = "ME";
break;
default:
windows_flavor = "9X";
break;
}
break;
default:
windows_flavor = "??";
break;
}
printf_filtered ("%s)\n", windows_flavor);
}
else if (true_dos_version == 0x532 && advertized_dos_version == 0x500)
printf_filtered ("Windows Version................Windows NT or Windows 2000\n");
puts_filtered ("\n");
if (dpmi_vendor_available == 0)
{
/* The DPMI spec says the vendor string should be ASCIIZ, but
I don't trust the vendors to follow that... */
if (!memchr (&dpmi_vendor_info[2], 0, 126))
dpmi_vendor_info[128] = '\0';
printf_filtered ("DPMI Host......................%s v%d.%d (capabilities: %#x)\n",
&dpmi_vendor_info[2],
(unsigned)dpmi_vendor_info[0],
(unsigned)dpmi_vendor_info[1],
((unsigned)dpmi_flags & 0x7f));
}
__dpmi_get_version (&dpmi_version_data);
printf_filtered ("DPMI Version...................%d.%02d\n",
dpmi_version_data.major, dpmi_version_data.minor);
printf_filtered ("DPMI Info......................%s-bit DPMI, with%s Virtual Memory support\n",
(dpmi_version_data.flags & 1) ? "32" : "16",
(dpmi_version_data.flags & 4) ? "" : "out");
printfi_filtered (31, "Interrupts reflected to %s mode\n",
(dpmi_version_data.flags & 2) ? "V86" : "Real");
printfi_filtered (31, "Processor type: i%d86\n",
dpmi_version_data.cpu);
printfi_filtered (31, "PIC base interrupt: Master: %#x Slave: %#x\n",
dpmi_version_data.master_pic, dpmi_version_data.slave_pic);
/* a_tss is only initialized when the debuggee is first run. */
if (prog_has_started)
{
__asm__ __volatile__ ("pushfl ; popl %0" : "=g" (eflags));
printf_filtered ("Protection.....................Ring %d (in %s), with%s I/O protection\n",
a_tss.tss_cs & 3, (a_tss.tss_cs & 4) ? "LDT" : "GDT",
(a_tss.tss_cs & 3) > ((eflags >> 12) & 3) ? "" : "out");
}
puts_filtered ("\n");
__dpmi_get_free_memory_information (&mem_info);
print_mem (mem_info.total_number_of_physical_pages,
"DPMI Total Physical Memory.....", 1);
print_mem (mem_info.total_number_of_free_pages,
"DPMI Free Physical Memory......", 1);
print_mem (mem_info.size_of_paging_file_partition_in_pages,
"DPMI Swap Space................", 1);
print_mem (mem_info.linear_address_space_size_in_pages,
"DPMI Total Linear Address Size.", 1);
print_mem (mem_info.free_linear_address_space_in_pages,
"DPMI Free Linear Address Size..", 1);
print_mem (mem_info.largest_available_free_block_in_bytes,
"DPMI Largest Free Memory Block.", 0);
regs.h.ah = 0x48;
regs.x.bx = 0xffff;
__dpmi_int (0x21, &regs);
print_mem (regs.x.bx << 4, "Free DOS Memory................", 0);
regs.x.ax = 0x5800;
__dpmi_int (0x21, &regs);
if ((regs.x.flags & 1) == 0)
{
static const char *dos_hilo[] = {
"Low", "", "", "", "High", "", "", "", "High, then Low"
};
static const char *dos_fit[] = {
"First", "Best", "Last"
};
int hilo_idx = (regs.x.ax >> 4) & 0x0f;
int fit_idx = regs.x.ax & 0x0f;
if (hilo_idx > 8)
hilo_idx = 0;
if (fit_idx > 2)
fit_idx = 0;
printf_filtered ("DOS Memory Allocation..........%s memory, %s fit\n",
dos_hilo[hilo_idx], dos_fit[fit_idx]);
regs.x.ax = 0x5802;
__dpmi_int (0x21, &regs);
if ((regs.x.flags & 1) != 0)
regs.h.al = 0;
printfi_filtered (31, "UMBs %sin DOS memory chain\n",
regs.h.al == 0 ? "not " : "");
}
}
struct seg_descr {
unsigned short limit0 __attribute__((packed));
unsigned short base0 __attribute__((packed));
unsigned char base1 __attribute__((packed));
unsigned stype:5 __attribute__((packed));
unsigned dpl:2 __attribute__((packed));
unsigned present:1 __attribute__((packed));
unsigned limit1:4 __attribute__((packed));
unsigned available:1 __attribute__((packed));
unsigned dummy:1 __attribute__((packed));
unsigned bit32:1 __attribute__((packed));
unsigned page_granular:1 __attribute__((packed));
unsigned char base2 __attribute__((packed));
};
struct gate_descr {
unsigned short offset0 __attribute__((packed));
unsigned short selector __attribute__((packed));
unsigned param_count:5 __attribute__((packed));
unsigned dummy:3 __attribute__((packed));
unsigned stype:5 __attribute__((packed));
unsigned dpl:2 __attribute__((packed));
unsigned present:1 __attribute__((packed));
unsigned short offset1 __attribute__((packed));
};
/* Read LEN bytes starting at logical address ADDR, and put the result
into DEST. Return 1 if success, zero if not. */
static int
read_memory_region (unsigned long addr, void *dest, size_t len)
{
unsigned long dos_ds_limit = __dpmi_get_segment_limit (_dos_ds);
/* For the low memory, we can simply use _dos_ds. */
if (addr <= dos_ds_limit - len)
dosmemget (addr, len, dest);
else
{
/* For memory above 1MB we need to set up a special segment to
be able to access that memory. */
int sel = __dpmi_allocate_ldt_descriptors (1);
if (sel <= 0
|| __dpmi_set_segment_base_address (sel, addr) == -1
|| __dpmi_set_segment_limit (sel, len - 1) == -1)
return 0;
movedata (sel, 0, _my_ds (), (unsigned)dest, len);
__dpmi_free_ldt_descriptor (sel);
}
return 1;
}
/* Get a segment descriptor stored at index IDX in the descriptor
table whose base address is TABLE_BASE. Return the descriptor
type, or -1 if failure. */
static int
get_descriptor (unsigned long table_base, int idx, void *descr)
{
unsigned long addr = table_base + idx * 8; /* 8 bytes per entry */
if (read_memory_region (addr, descr, 8))
return (int)((struct seg_descr *)descr)->stype;
return -1;
}
struct dtr_reg {
unsigned short limit __attribute__((packed));
unsigned long base __attribute__((packed));
};
/* Display a segment descriptor stored at index IDX in a descriptor
table whose type is TYPE and whose base address is BASE_ADDR. If
FORCE is non-zero, display even invalid descriptors. */
static void
display_descriptor (unsigned type, unsigned long base_addr, int idx, int force)
{
struct seg_descr descr;
struct gate_descr gate;
/* Get the descriptor from the table. */
if (idx == 0 && type == 0)
puts_filtered ("0x000: null descriptor\n");
else if (get_descriptor (base_addr, idx, &descr) != -1)
{
/* For each type of descriptor table, this has a bit set if the
corresponding type of selectors is valid in that table. */
static unsigned allowed_descriptors[] = {
0xffffdafeL, /* GDT */
0x0000c0e0L, /* IDT */
0xffffdafaL /* LDT */
};
/* If the program hasn't started yet, assume the debuggee will
have the same CPL as the debugger. */
int cpl = prog_has_started ? (a_tss.tss_cs & 3) : _my_cs () & 3;
unsigned long limit = (descr.limit1 << 16) | descr.limit0;
if (descr.present
&& (allowed_descriptors[type] & (1 << descr.stype)) != 0)
{
printf_filtered ("0x%03x: ",
type == 1
? idx : (idx * 8) | (type ? (cpl | 4) : 0));
if (descr.page_granular)
limit = (limit << 12) | 0xfff; /* big segment: low 12 bit set */
if (descr.stype == 1 || descr.stype == 2 || descr.stype == 3
|| descr.stype == 9 || descr.stype == 11
|| (descr.stype >= 16 && descr.stype < 32))
printf_filtered ("base=0x%02x%02x%04x limit=0x%08lx",
descr.base2, descr.base1, descr.base0, limit);
switch (descr.stype)
{
case 1:
case 3:
printf_filtered (" 16-bit TSS (task %sactive)",
descr.stype == 3 ? "" : "in");
break;
case 2:
puts_filtered (" LDT");
break;
case 4:
memcpy (&gate, &descr, sizeof gate);
printf_filtered ("selector=0x%04x offs=0x%04x%04x",
gate.selector, gate.offset1, gate.offset0);
printf_filtered (" 16-bit Call Gate (params=%d)",
gate.param_count);
break;
case 5:
printf_filtered ("TSS selector=0x%04x", descr.base0);
printfi_filtered (16, "Task Gate");
break;
case 6:
case 7:
memcpy (&gate, &descr, sizeof gate);
printf_filtered ("selector=0x%04x offs=0x%04x%04x",
gate.selector, gate.offset1, gate.offset0);
printf_filtered (" 16-bit %s Gate",
descr.stype == 6 ? "Interrupt" : "Trap");
break;
case 9:
case 11:
printf_filtered (" 32-bit TSS (task %sactive)",
descr.stype == 3 ? "" : "in");
break;
case 12:
memcpy (&gate, &descr, sizeof gate);
printf_filtered ("selector=0x%04x offs=0x%04x%04x",
gate.selector, gate.offset1, gate.offset0);
printf_filtered (" 32-bit Call Gate (params=%d)",
gate.param_count);
break;
case 14:
case 15:
memcpy (&gate, &descr, sizeof gate);
printf_filtered ("selector=0x%04x offs=0x%04x%04x",
gate.selector, gate.offset1, gate.offset0);
printf_filtered (" 32-bit %s Gate",
descr.stype == 14 ? "Interrupt" : "Trap");
break;
case 16: /* data segments */
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
printf_filtered (" %s-bit Data (%s Exp-%s%s)",
descr.bit32 ? "32" : "16",
descr.stype & 2 ? "Read/Write," : "Read-Only, ",
descr.stype & 4 ? "down" : "up",
descr.stype & 1 ? "" : ", N.Acc");
break;
case 24: /* code segments */
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
printf_filtered (" %s-bit Code (%s, %sConf%s)",
descr.bit32 ? "32" : "16",
descr.stype & 2 ? "Exec/Read" : "Exec-Only",
descr.stype & 4 ? "" : "N.",
descr.stype & 1 ? "" : ", N.Acc");
break;
default:
printf_filtered ("Unknown type 0x%02x", descr.stype);
break;
}
puts_filtered ("\n");
}
else if (force)
{
printf_filtered ("0x%03x: ",
type == 1
? idx : (idx * 8) | (type ? (cpl | 4) : 0));
if (!descr.present)
puts_filtered ("Segment not present\n");
else
printf_filtered ("Segment type 0x%02x is invalid in this table\n",
descr.stype);
}
}
else if (force)
printf_filtered ("0x%03x: Cannot read this descriptor\n", idx);
}
static void
go32_sldt (char *arg, int from_tty)
{
struct dtr_reg gdtr;
unsigned short ldtr = 0;
int ldt_idx;
struct seg_descr ldt_descr;
long ldt_entry = -1L;
int cpl = (prog_has_started ? a_tss.tss_cs : _my_cs ()) & 3;
if (arg && *arg)
{
while (*arg && isspace(*arg))
arg++;
if (*arg)
{
ldt_entry = parse_and_eval_long (arg);
if (ldt_entry < 0
|| (ldt_entry & 4) == 0
|| (ldt_entry & 3) != (cpl & 3))
error ("Invalid LDT entry 0x%03x.", ldt_entry);
}
}
__asm__ __volatile__ ("sgdt %0" : "=m" (gdtr) : /* no inputs */ );
__asm__ __volatile__ ("sldt %0" : "=m" (ldtr) : /* no inputs */ );
ldt_idx = ldtr / 8;
if (ldt_idx == 0)
puts_filtered ("There is no LDT.\n");
/* LDT's entry in the GDT must have the type LDT, which is 2. */
else if (get_descriptor (gdtr.base, ldt_idx, &ldt_descr) != 2)
printf_filtered ("LDT is present (at %#x), but unreadable by GDB.\n",
ldt_descr.base0
| (ldt_descr.base1 << 16)
| (ldt_descr.base2 << 24));
else
{
unsigned base =
ldt_descr.base0
| (ldt_descr.base1 << 16)
| (ldt_descr.base2 << 24);
unsigned limit = ldt_descr.limit0 | (ldt_descr.limit1 << 16);
int max_entry;
if (ldt_descr.page_granular)
/* Page-granular segments must have the low 12 bits of their
limit set. */
limit = (limit << 12) | 0xfff;
/* LDT cannot have more than 8K 8-byte entries, i.e. more than
64KB. */
if (limit > 0xffff)
limit = 0xffff;
max_entry = (limit + 1) / 8;
if (ldt_entry >= 0)
{
if (ldt_entry > limit)
error ("Invalid LDT entry %#x: outside valid limits [0..%#x]",
ldt_entry, limit);
display_descriptor (ldt_descr.stype, base, ldt_entry / 8, 1);
}
else
{
int i;
for (i = 0; i < max_entry; i++)
display_descriptor (ldt_descr.stype, base, i, 0);
}
}
}
static void
go32_sgdt (char *arg, int from_tty)
{
struct dtr_reg gdtr;
long gdt_entry = -1L;
int max_entry;
if (arg && *arg)
{
while (*arg && isspace(*arg))
arg++;
if (*arg)
{
gdt_entry = parse_and_eval_long (arg);
if (gdt_entry < 0 || (gdt_entry & 7) != 0)
error ("Invalid GDT entry 0x%03x: not an integral multiple of 8.",
gdt_entry);
}
}
__asm__ __volatile__ ("sgdt %0" : "=m" (gdtr) : /* no inputs */ );
max_entry = (gdtr.limit + 1) / 8;
if (gdt_entry >= 0)
{
if (gdt_entry > gdtr.limit)
error ("Invalid GDT entry %#x: outside valid limits [0..%#x]",
gdt_entry, gdtr.limit);
display_descriptor (0, gdtr.base, gdt_entry / 8, 1);
}
else
{
int i;
for (i = 0; i < max_entry; i++)
display_descriptor (0, gdtr.base, i, 0);
}
}
static void
go32_sidt (char *arg, int from_tty)
{
struct dtr_reg idtr;
long idt_entry = -1L;
int max_entry;
if (arg && *arg)
{
while (*arg && isspace(*arg))
arg++;
if (*arg)
{
idt_entry = parse_and_eval_long (arg);
if (idt_entry < 0)
error ("Invalid (negative) IDT entry 0x%03x.", idt_entry);
}
}
__asm__ __volatile__ ("sidt %0" : "=m" (idtr) : /* no inputs */ );
max_entry = (idtr.limit + 1) / 8;
if (max_entry > 0x100) /* no more than 256 entries */
max_entry = 0x100;
if (idt_entry >= 0)
{
if (idt_entry > idtr.limit)
error ("Invalid IDT entry %#x: outside valid limits [0..%#x]",
idt_entry, idtr.limit);
display_descriptor (1, idtr.base, idt_entry, 1);
}
else
{
int i;
for (i = 0; i < max_entry; i++)
display_descriptor (1, idtr.base, i, 0);
}
}
void
_initialize_go32_nat (void)
{
init_go32_ops ();
add_target (&go32_ops);
add_info ("dos-sysinfo", go32_sysinfo,
"Display information about the target system, including CPU, OS, DPMI, etc.");
add_info ("dos-ldt", go32_sldt,
"Display entries in the LDT (Local Descriptor Table).\n"
"Entry number (an expression) as an argument means display only that entry.");
add_info ("dos-gdt", go32_sgdt,
"Display entries in the GDT (Global Descriptor Table).\n"
"Entry number (an expression) as an argument means display only that entry.");
add_info ("dos-idt", go32_sidt,
"Display entries in the IDT (Interrupt Descriptor Table).\n"
"Entry number (an expression) as an argument means display only that entry.");
}
pid_t