/* Native debugging support for Intel x86 running DJGPP.
- Copyright (C) 1997-2018 Free Software Foundation, Inc.
+ Copyright (C) 1997-2020 Free Software Foundation, Inc.
Written by Robert Hoehne.
This file is part of GDB.
#include "inferior.h"
#include "infrun.h"
#include "gdbthread.h"
-#include "gdb_wait.h"
+#include "gdbsupport/gdb_wait.h"
#include "gdbcore.h"
#include "command.h"
#include "gdbcmd.h"
#include "floatformat.h"
-#include "buildsym.h"
+#include "buildsym-legacy.h"
#include "i387-tdep.h"
#include "i386-tdep.h"
#include "nat/x86-cpuid.h"
#define SOME_PID 42
static int prog_has_started = 0;
-static void go32_mourn_inferior (struct target_ops *ops);
#define r_ofs(x) (offsetof(TSS,x))
{GDB_SIGNAL_LAST, -1}
};
-static void
-go32_attach (struct target_ops *ops, const char *args, int from_tty)
+/* The go32 target. */
+
+struct go32_nat_target final : public x86_nat_target<inf_child_target>
+{
+ void attach (const char *, int) override;
+
+ void resume (ptid_t, int, enum gdb_signal) override;
+
+ ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+
+ void fetch_registers (struct regcache *, int) override;
+ void store_registers (struct regcache *, int) override;
+
+ enum target_xfer_status xfer_partial (enum target_object object,
+ const char *annex,
+ gdb_byte *readbuf,
+ const gdb_byte *writebuf,
+ ULONGEST offset, ULONGEST len,
+ ULONGEST *xfered_len) override;
+
+ void files_info () override;
+
+ void terminal_init () override;
+
+ void terminal_inferior () override;
+
+ void terminal_ours_for_output () override;
+
+ void terminal_ours () override;
+
+ void terminal_info (const char *, int) override;
+
+ void pass_ctrlc () override;
+
+ void kill () override;
+
+ void create_inferior (const char *, const std::string &,
+ char **, int) override;
+
+ void mourn_inferior () override;
+
+ bool thread_alive (ptid_t ptid) override;
+
+ std::string pid_to_str (ptid_t) override;
+};
+
+static go32_nat_target the_go32_nat_target;
+
+void
+go32_nat_target::attach (const char *args, int from_tty)
{
error (_("\
You cannot attach to a running program on this platform.\n\
static int resume_is_step;
static int resume_signal = -1;
-static void
-go32_resume (struct target_ops *ops,
- ptid_t ptid, int step, enum gdb_signal siggnal)
+void
+go32_nat_target::resume (ptid_t ptid, int step, enum gdb_signal siggnal)
{
int i;
static char child_cwd[FILENAME_MAX];
-static ptid_t
-go32_wait (struct target_ops *ops,
- ptid_t ptid, struct target_waitstatus *status, int options)
+ptid_t
+go32_nat_target::wait (ptid_t ptid, struct target_waitstatus *status,
+ int options)
{
int i;
unsigned char saved_opcode;
}
getcwd (child_cwd, sizeof (child_cwd)); /* in case it has changed */
- chdir (current_directory);
+ if (current_directory != NULL)
+ chdir (current_directory);
if (a_tss.tss_irqn == 0x21)
{
}
}
}
- return pid_to_ptid (SOME_PID);
+ return ptid_t (SOME_PID);
}
static void
{
struct gdbarch *gdbarch = regcache->arch ();
if (regno < gdbarch_fp0_regnum (gdbarch))
- regcache_raw_supply (regcache, regno,
- (char *) &a_tss + regno_mapping[regno].tss_ofs);
+ regcache->raw_supply (regno,
+ (char *) &a_tss + regno_mapping[regno].tss_ofs);
else if (i386_fp_regnum_p (gdbarch, regno) || i386_fpc_regnum_p (gdbarch,
regno))
i387_supply_fsave (regcache, regno, &npx);
_("Invalid register no. %d in fetch_register."), regno);
}
-static void
-go32_fetch_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
+void
+go32_nat_target::fetch_registers (struct regcache *regcache, int regno)
{
if (regno >= 0)
fetch_register (regcache, regno);
{
struct gdbarch *gdbarch = regcache->arch ();
if (regno < gdbarch_fp0_regnum (gdbarch))
- regcache_raw_collect (regcache, regno,
- (char *) &a_tss + regno_mapping[regno].tss_ofs);
+ regcache->raw_collect (regno,
+ (char *) &a_tss + regno_mapping[regno].tss_ofs);
else if (i386_fp_regnum_p (gdbarch, regno) || i386_fpc_regnum_p (gdbarch,
regno))
i387_collect_fsave (regcache, regno, &npx);
_("Invalid register no. %d in store_register."), regno);
}
-static void
-go32_store_registers (struct target_ops *ops,
- struct regcache *regcache, int regno)
+void
+go32_nat_target::store_registers (struct regcache *regcache, int regno)
{
unsigned r;
/* Target to_xfer_partial implementation. */
-static enum target_xfer_status
-go32_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
- ULONGEST *xfered_len)
+enum target_xfer_status
+go32_nat_target::xfer_partial (enum target_object object,
+ const char *annex, gdb_byte *readbuf,
+ const gdb_byte *writebuf, ULONGEST offset,
+ ULONGEST len,
+ ULONGEST *xfered_len)
{
switch (object)
{
return go32_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
default:
- return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
- readbuf, writebuf, offset, len,
- xfered_len);
+ return this->beneath ()->xfer_partial (object, annex,
+ readbuf, writebuf, offset, len,
+ xfered_len);
}
}
static cmdline_t child_cmd; /* Parsed child's command line kept here. */
-static void
-go32_files_info (struct target_ops *target)
+void
+go32_nat_target::files_info ()
{
printf_unfiltered ("You are running a DJGPP V2 program.\n");
}
-static void
-go32_kill_inferior (struct target_ops *ops)
+void
+go32_nat_target::kill_inferior ()
{
- go32_mourn_inferior (ops);
+ mourn_inferior ();
}
-static void
-go32_create_inferior (struct target_ops *ops,
- const char *exec_file,
- const std::string &allargs, char **env, int from_tty)
+void
+go32_nat_target::create_inferior (const char *exec_file,
+ const std::string &allargs,
+ char **env, int from_tty)
{
extern char **environ;
jmp_buf start_state;
save_npx ();
#endif
- inferior_ptid = pid_to_ptid (SOME_PID);
+ inferior_ptid = ptid_t (SOME_PID);
inf = current_inferior ();
inferior_appeared (inf, SOME_PID);
- if (!target_is_pushed (ops))
- push_target (ops);
+ if (!target_is_pushed (this))
+ push_target (this);
add_thread_silent (inferior_ptid);
prog_has_started = 1;
}
-static void
-go32_mourn_inferior (struct target_ops *ops)
+void
+go32_nat_target::mourn_inferior ()
{
ptid_t ptid;
ptid = inferior_ptid;
inferior_ptid = null_ptid;
- delete_thread_silent (ptid);
prog_has_started = 0;
generic_mourn_inferior ();
- inf_child_maybe_unpush_target (ops);
+ maybe_unpush_target ();
}
/* Hardware watchpoint support. */
second call will always see GDB's own cooked terminal. */
static int terminal_is_ours = 1;
-static void
-go32_terminal_init (struct target_ops *self)
+void
+go32_nat_target::terminal_init ()
{
inf_mode_valid = 0; /* Reinitialize, in case they are restarting child. */
terminal_is_ours = 1;
}
-static void
-go32_terminal_info (struct target_ops *self, const char *args, int from_tty)
+void
+go32_nat_target::terminal_info (const char *args, int from_tty)
{
printf_unfiltered ("Inferior's terminal is in %s mode.\n",
!inf_mode_valid
#endif
}
-static void
-go32_terminal_inferior (struct target_ops *self)
+void
+go32_nat_target::terminal_inferior ()
{
/* Redirect standard handles as child wants them. */
errno = 0;
}
}
-static void
-go32_terminal_ours (struct target_ops *self)
+void
+go32_nat_target::terminal_ours ()
{
/* Switch to cooked mode on the gdb terminal and save the inferior
terminal mode to be restored when it is resumed. */
}
}
-static int
-go32_thread_alive (struct target_ops *ops, ptid_t ptid)
+void
+go32_nat_target::pass_ctrlc ()
{
- return !ptid_equal (ptid, null_ptid);
}
-static const char *
-go32_pid_to_str (struct target_ops *ops, ptid_t ptid)
+bool
+go32_nat_target::thread_alive (ptid_t ptid)
{
- return normal_pid_to_str (ptid);
+ return ptid != null_ptid;
}
-/* Create a go32 target. */
-
-static struct target_ops *
-go32_target (void)
+std::string
+go32_nat_target::pid_to_str (ptid_t ptid)
{
- struct target_ops *t = inf_child_target ();
-
- t->to_attach = go32_attach;
- t->to_resume = go32_resume;
- t->to_wait = go32_wait;
- t->to_fetch_registers = go32_fetch_registers;
- t->to_store_registers = go32_store_registers;
- t->to_xfer_partial = go32_xfer_partial;
- t->to_files_info = go32_files_info;
- t->to_terminal_init = go32_terminal_init;
- t->to_terminal_inferior = go32_terminal_inferior;
- t->to_terminal_ours_for_output = go32_terminal_ours;
- t->to_terminal_ours = go32_terminal_ours;
- t->to_terminal_info = go32_terminal_info;
- t->to_kill = go32_kill_inferior;
- t->to_create_inferior = go32_create_inferior;
- t->to_mourn_inferior = go32_mourn_inferior;
- t->to_thread_alive = go32_thread_alive;
- t->to_pid_to_str = go32_pid_to_str;
-
- return t;
+ return normal_pid_to_str (ptid);
}
/* Return the current DOS codepage number. */
unsigned brand_idx;
int intel_p = strcmp (cpuid_vendor, "GenuineIntel") == 0;
int amd_p = strcmp (cpuid_vendor, "AuthenticAMD") == 0;
+ int hygon_p = strcmp (cpuid_vendor, "HygonGenuine") == 0;
unsigned cpu_family, cpu_model;
#if 0
}
}
xsnprintf (cpu_string, sizeof (cpu_string), "%s%s Model %d Stepping %d",
- intel_p ? "Pentium" : (amd_p ? "AMD" : "ix86"),
+ intel_p ? "Pentium" : (amd_p ? "AMD" : (hygon_p ? "Hygon" : "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))
+ || ((amd_p || hygon_p) && (cpuid_edx & (3 << 30)) != 0))
{
puts_filtered ("CPU Features...................");
/* We only list features which might be useful in the DPMI
puts_filtered ("SSE ");
if ((cpuid_edx & (1 << 26)) != 0)
puts_filtered ("SSE2 ");
- if (amd_p)
+ if (amd_p || hygon_p)
{
if ((cpuid_edx & (1 << 31)) != 0)
puts_filtered ("3DNow! ");
cr3 = _farnspeekl (taskbase + 0x1c) & ~0xfff;
if (cr3 > 0xfffff)
{
-#if 0 /* Not fullly supported yet. */
+#if 0 /* Not fully 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
Directory entry for that Page Table will hold the same
physical address. The loop below searches the entire UMB
- range of addresses for such an occurence. */
+ range of addresses for such an occurrence. */
unsigned long addr, pte_idx;
for (addr = 0xb0000, pte_idx = 0xb0;
void
_initialize_go32_nat (void)
{
- struct target_ops *t = go32_target ();
-
x86_dr_low.set_control = go32_set_dr7;
x86_dr_low.set_addr = go32_set_dr;
x86_dr_low.get_status = go32_get_dr6;
x86_dr_low.get_addr = go32_get_dr;
x86_set_debug_register_length (4);
- x86_use_watchpoints (t);
- add_target (t);
+ add_inf_child_target (&the_go32_nat_target);
/* Initialize child's cwd as empty to be initialized when starting
the child. */