/* Native debugging support for Intel x86 running DJGPP.
- Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1999, 2000, 2001, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Written by Robert Hoehne.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include <fcntl.h>
#include "gdbcmd.h"
#include "floatformat.h"
#include "buildsym.h"
-#include "i387-nat.h"
+#include "i387-tdep.h"
+#include "i386-tdep.h"
#include "value.h"
#include "regcache.h"
#include "gdb_string.h"
+#include "top.h"
#include <stdio.h> /* might be required for __DJGPP_MINOR__ */
#include <stdlib.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 <sys/farptr.h>
static void
save_npx (void)
{
- asm ("inb $0xa0, %%al
- testb $0x20, %%al
- jz 1f
- xorb %% al, %%al
- outb %% al, $0xf0
- movb $0x20, %%al
- outb %% al, $0xa0
- outb %% al, $0x20
-1:
- fnsave % 0
+ asm ("inb $0xa0, %%al \n\
+ testb $0x20, %%al \n\
+ jz 1f \n\
+ xorb %%al, %%al \n\
+ outb %%al, $0xf0 \n\
+ movb $0x20, %%al \n\
+ outb %%al, $0xa0 \n\
+ outb %%al, $0x20 \n\
+1: \n\
+ fnsave %0 \n\
fwait "
: "=m" (npx)
: /* No input */
/* *INDENT-ON* */
-
-
-
/* ------------------------------------------------------------------------- */
/* Reload the contents of the NPX from the global variable `npx'. */
enum target_signal siggnal);
static ptid_t go32_wait (ptid_t ptid,
struct target_waitstatus *status);
-static void go32_fetch_registers (int regno);
-static void store_register (int regno);
-static void go32_store_registers (int regno);
-static void go32_prepare_to_store (void);
+static void go32_fetch_registers (struct regcache *, int regno);
+static void store_register (const struct regcache *, int regno);
+static void go32_store_registers (struct regcache *, int regno);
+static void go32_prepare_to_store (struct regcache *);
static int go32_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
int write,
struct mem_attrib *attrib,
static void go32_files_info (struct target_ops *target);
static void go32_stop (void);
static void go32_kill_inferior (void);
-static void go32_create_inferior (char *exec_file, char *args, char **env);
+static void go32_create_inferior (char *exec_file, char *args, char **env, int from_tty);
static void go32_mourn_inferior (void);
static int go32_can_run (void);
static void
go32_attach (char *args, int from_tty)
{
- error ("\
+ error (_("\
You cannot attach to a running program on this platform.\n\
-Use the `run' command to run DJGPP programs.");
+Use the `run' command to run DJGPP programs."));
}
static void
}
static void
-fetch_register (int regno)
+fetch_register (struct regcache *regcache, int regno)
{
if (regno < FP0_REGNUM)
- supply_register (regno, (char *) &a_tss + regno_mapping[regno].tss_ofs);
- else if (regno <= LAST_FPU_CTRL_REGNUM)
- i387_supply_register (regno, (char *) &npx);
+ regcache_raw_supply (regcache, regno,
+ (char *) &a_tss + regno_mapping[regno].tss_ofs);
+ else if (i386_fp_regnum_p (regno) || i386_fpc_regnum_p (regno))
+ i387_supply_fsave (regcache, regno, &npx);
else
internal_error (__FILE__, __LINE__,
- "Invalid register no. %d in fetch_register.", regno);
+ _("Invalid register no. %d in fetch_register."), regno);
}
static void
-go32_fetch_registers (int regno)
+go32_fetch_registers (struct regcache *regcache, int regno)
{
if (regno >= 0)
- fetch_register (regno);
+ fetch_register (regcache, regno);
else
{
for (regno = 0; regno < FP0_REGNUM; regno++)
- fetch_register (regno);
- i387_supply_fsave ((char *) &npx);
+ fetch_register (regcache, regno);
+ i387_supply_fsave (regcache, -1, &npx);
}
}
static void
-store_register (int regno)
+store_register (const struct regcache *regcache, int regno)
{
- void *rp;
- void *v = (void *) register_buffer (regno);
-
if (regno < FP0_REGNUM)
- memcpy ((char *) &a_tss + regno_mapping[regno].tss_ofs,
- v, regno_mapping[regno].size);
- else if (regno <= LAST_FPU_CTRL_REGNUM)
- i387_fill_fsave ((char *)&npx, regno);
+ regcache_raw_collect (regcache, regno,
+ (char *) &a_tss + regno_mapping[regno].tss_ofs);
+ else if (i386_fp_regnum_p (regno) || i386_fpc_regnum_p (regno))
+ i387_collect_fsave (regcache, regno, &npx);
else
internal_error (__FILE__, __LINE__,
- "Invalid register no. %d in store_register.", regno);
+ _("Invalid register no. %d in store_register."), regno);
}
static void
-go32_store_registers (int regno)
+go32_store_registers (struct regcache *regcache, int regno)
{
unsigned r;
if (regno >= 0)
- store_register (regno);
+ store_register (regcache, regno);
else
{
for (r = 0; r < FP0_REGNUM; r++)
- store_register (r);
- i387_fill_fsave ((char *) &npx, -1);
+ store_register (regcache, r);
+ i387_collect_fsave (regcache, -1, &npx);
}
}
static void
-go32_prepare_to_store (void)
+go32_prepare_to_store (struct regcache *regcache)
{
}
}
static void
-go32_create_inferior (char *exec_file, char *args, char **env)
+go32_create_inferior (char *exec_file, char *args, char **env, int from_tty)
{
extern char **environ;
jmp_buf start_state;
/* Init command line storage. */
if (redir_debug_init (&child_cmd) == -1)
internal_error (__FILE__, __LINE__,
- "Cannot allocate redirection storage: not enough memory.\n");
+ _("Cannot allocate redirection storage: not enough memory.\n"));
/* Parse the command line and create redirections. */
if (strpbrk (args, "<>"))
if (redir_cmdline_parse (args, &child_cmd) == 0)
args = child_cmd.command;
else
- error ("Syntax error in command line.");
+ error (_("Syntax error in command line."));
}
else
child_cmd.command = xstrdup (args);
/* v2loadimage passes command lines via DOS memory, so it cannot
possibly handle commands longer than 1MB. */
if (cmdlen > 1024*1024)
- error ("Command line too long.");
+ error (_("Command line too long."));
cmdline = xmalloc (cmdlen + 4);
strcpy (cmdline + 1, args);
exit (1);
}
environ = env_save;
- free (cmdline);
+ xfree (cmdline);
edi_init (start_state);
#if __DJGPP_MINOR__ < 3
push_target (&go32_ops);
clear_proceed_status ();
insert_breakpoints ();
- proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
prog_has_started = 1;
}
{
if (i < 0 || i > 3)
internal_error (__FILE__, __LINE__,
- "Invalid register %d in go32_set_dr.\n", i);
+ _("Invalid register %d in go32_set_dr.\n"), i);
D_REGS[i] = addr;
}
if (redir_to_child (&child_cmd) == -1)
{
redir_to_debugger (&child_cmd);
- error ("Cannot redirect standard handles for program: %s.",
- strerror (errno));
+ error (_("Cannot redirect standard handles for program: %s."),
+ safe_strerror (errno));
}
/* set the console device of the inferior to whatever mode
(raw or cooked) we found it last time */
if (redir_to_debugger (&child_cmd) == -1)
{
redir_to_child (&child_cmd);
- error ("Cannot redirect standard handles for debugger: %s.",
- strerror (errno));
+ error (_("Cannot redirect standard handles for debugger: %s."),
+ safe_strerror (errno));
}
}
}
go32_ops.to_fetch_registers = go32_fetch_registers;
go32_ops.to_store_registers = go32_store_registers;
go32_ops.to_prepare_to_store = go32_prepare_to_store;
- go32_ops.to_xfer_memory = go32_xfer_memory;
+ go32_ops.deprecated_xfer_memory = go32_xfer_memory;
go32_ops.to_files_info = go32_files_info;
go32_ops.to_insert_breakpoint = memory_insert_breakpoint;
go32_ops.to_remove_breakpoint = memory_remove_breakpoint;
/* Initialize child's command line storage. */
if (redir_debug_init (&child_cmd) == -1)
internal_error (__FILE__, __LINE__,
- "Cannot allocate redirection storage: not enough memory.\n");
+ _("Cannot allocate redirection storage: not enough memory.\n"));
/* We are always processing GCC-compiled programs. */
processing_gcc_compilation = 2;
+
+ /* Override the default name of the GDB init file. */
+ strcpy (gdbinit, "gdb.ini");
}
unsigned short windows_major, windows_minor;
if (__dpmi_set_segment_base_address (sel, addr) != -1
&& __dpmi_set_descriptor_access_rights (sel, access_rights) != -1
- && __dpmi_set_segment_limit (sel, segment_limit) != -1)
+ && __dpmi_set_segment_limit (sel, segment_limit) != -1
+ /* W2K silently fails to set the segment limit, leaving
+ it at zero; this test avoids the resulting crash. */
+ && __dpmi_get_segment_limit (sel) >= segment_limit)
movedata (sel, 0, _my_ds (), (unsigned)dest, len);
else
retval = 0;
if (ldt_entry < 0
|| (ldt_entry & 4) == 0
|| (ldt_entry & 3) != (cpl & 3))
- error ("Invalid LDT entry 0x%03x.", ldt_entry);
+ error (_("Invalid LDT entry 0x%03lx."), (unsigned long)ldt_entry);
}
}
if (ldt_entry >= 0)
{
if (ldt_entry > limit)
- error ("Invalid LDT entry %#x: outside valid limits [0..%#x]",
- ldt_entry, limit);
+ error (_("Invalid LDT entry %#lx: outside valid limits [0..%#x]"),
+ (unsigned long)ldt_entry, limit);
display_descriptor (ldt_descr.stype, base, ldt_entry / 8, 1);
}
{
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);
+ error (_("Invalid GDT entry 0x%03lx: not an integral multiple of 8."),
+ (unsigned long)gdt_entry);
}
}
if (gdt_entry >= 0)
{
if (gdt_entry > gdtr.limit)
- error ("Invalid GDT entry %#x: outside valid limits [0..%#x]",
- gdt_entry, gdtr.limit);
+ error (_("Invalid GDT entry %#lx: outside valid limits [0..%#x]"),
+ (unsigned long)gdt_entry, gdtr.limit);
display_descriptor (0, gdtr.base, gdt_entry / 8, 1);
}
{
idt_entry = parse_and_eval_long (arg);
if (idt_entry < 0)
- error ("Invalid (negative) IDT entry %d.", idt_entry);
+ error (_("Invalid (negative) IDT entry %ld."), idt_entry);
}
}
if (idt_entry >= 0)
{
if (idt_entry > idtr.limit)
- error ("Invalid IDT entry %#x: outside valid limits [0..%#x]",
- idt_entry, idtr.limit);
+ error (_("Invalid IDT entry %#lx: outside valid limits [0..%#x]"),
+ (unsigned long)idt_entry, idtr.limit);
display_descriptor (1, idtr.base, idt_entry, 1);
}
cr3 = _farnspeekl (taskbase + 0x1c) & ~0xfff;
if (cr3 > 0xfffff)
{
+#if 0 /* not fullly supported yet */
/* The Page Directory is in UMBs. In that case, CWSDPMI puts
the first Page Table right below the Page Directory. Thus,
the first Page Table's entry for its own address and the Page
break;
}
}
+#endif
if (cr3 > 0xfffff)
cr3 = 0;
{
pde_idx = parse_and_eval_long (arg);
if (pde_idx < 0 || pde_idx >= 1024)
- error ("Entry %ld is outside valid limits [0..1023].", pde_idx);
+ error (_("Entry %ld is outside valid limits [0..1023]."), pde_idx);
}
}
static void
go32_pte (char *arg, int from_tty)
{
- long pde_idx = -1, i;
+ long pde_idx = -1L, i;
if (arg && *arg)
{
{
pde_idx = parse_and_eval_long (arg);
if (pde_idx < 0 || pde_idx >= 1024)
- error ("Entry %d is outside valid limits [0..1023].", pde_idx);
+ error (_("Entry %ld is outside valid limits [0..1023]."), pde_idx);
}
}
addr = parse_and_eval_address (arg);
}
if (!addr)
- error_no_arg ("linear address");
+ error_no_arg (_("linear address"));
pdbr = get_cr3 ();
if (!pdbr)
init_go32_ops ();
add_target (&go32_ops);
- add_prefix_cmd ("dos", class_info, go32_info_dos_command,
- "Print information specific to DJGPP (a.k.a. MS-DOS) debugging.",
+ add_prefix_cmd ("dos", class_info, go32_info_dos_command, _("\
+Print information specific to DJGPP (aka MS-DOS) debugging."),
&info_dos_cmdlist, "info dos ", 0, &infolist);
- add_cmd ("sysinfo", class_info, go32_sysinfo,
- "Display information about the target system, including CPU, OS, DPMI, etc.",
+ add_cmd ("sysinfo", class_info, go32_sysinfo, _("\
+Display information about the target system, including CPU, OS, DPMI, etc."),
&info_dos_cmdlist);
- add_cmd ("ldt", class_info, go32_sldt,
- "Display entries in the LDT (Local Descriptor Table).\n"
- "Entry number (an expression) as an argument means display only that entry.",
+ add_cmd ("ldt", class_info, go32_sldt, _("\
+Display entries in the LDT (Local Descriptor Table).\n\
+Entry number (an expression) as an argument means display only that entry."),
&info_dos_cmdlist);
- add_cmd ("gdt", class_info, go32_sgdt,
- "Display entries in the GDT (Global Descriptor Table).\n"
- "Entry number (an expression) as an argument means display only that entry.",
+ add_cmd ("gdt", class_info, go32_sgdt, _("\
+Display entries in the GDT (Global Descriptor Table).\n\
+Entry number (an expression) as an argument means display only that entry."),
&info_dos_cmdlist);
- add_cmd ("idt", class_info, go32_sidt,
- "Display entries in the IDT (Interrupt Descriptor Table).\n"
- "Entry number (an expression) as an argument means display only that entry.",
+ add_cmd ("idt", class_info, go32_sidt, _("\
+Display entries in the IDT (Interrupt Descriptor Table).\n\
+Entry number (an expression) as an argument means display only that entry."),
&info_dos_cmdlist);
- add_cmd ("pde", class_info, go32_pde,
- "Display entries in the Page Directory.\n"
- "Entry number (an expression) as an argument means display only that entry.",
+ add_cmd ("pde", class_info, go32_pde, _("\
+Display entries in the Page Directory.\n\
+Entry number (an expression) as an argument means display only that entry."),
&info_dos_cmdlist);
- add_cmd ("pte", class_info, go32_pte,
- "Display entries in Page Tables.\n"
- "Entry number (an expression) as an argument means display only entries\n"
- "from the Page Table pointed to by the specified Page Directory entry.",
+ add_cmd ("pte", class_info, go32_pte, _("\
+Display entries in Page Tables.\n\
+Entry number (an expression) as an argument means display only entries\n\
+from the Page Table pointed to by the specified Page Directory entry."),
&info_dos_cmdlist);
- add_cmd ("address-pte", class_info, go32_pte_for_address,
- "Display a Page Table entry for a linear address.\n"
- "The address argument must be a linear address, after adding to\n"
- "it the base address of the appropriate segment.\n"
- "The base address of variables and functions in the debuggee's data\n"
- "or code segment is stored in the variable __djgpp_base_address,\n"
- "so use `__djgpp_base_address + (char *)&var' as the argument.\n"
- "For other segments, look up their base address in the output of\n"
- "the `info dos ldt' command.",
+ add_cmd ("address-pte", class_info, go32_pte_for_address, _("\
+Display a Page Table entry for a linear address.\n\
+The address argument must be a linear address, after adding to\n\
+it the base address of the appropriate segment.\n\
+The base address of variables and functions in the debuggee's data\n\
+or code segment is stored in the variable __djgpp_base_address,\n\
+so use `__djgpp_base_address + (char *)&var' as the argument.\n\
+For other segments, look up their base address in the output of\n\
+the `info dos ldt' command."),
&info_dos_cmdlist);
}