mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-04 08:08:01 +00:00
* 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:
parent
6cc9a2ee51
commit
10ba702db3
@ -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
|
||||
|
748
gdb/go32-nat.c
748
gdb/go32-nat.c
@ -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, ®s);
|
||||
print_mem (regs.x.bx << 4, "Free DOS Memory................", 0);
|
||||
regs.x.ax = 0x5800;
|
||||
__dpmi_int (0x21, ®s);
|
||||
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, ®s);
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user