aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-interix-nat.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/i386-interix-nat.c')
-rw-r--r--gdb/i386-interix-nat.c190
1 files changed, 190 insertions, 0 deletions
diff --git a/gdb/i386-interix-nat.c b/gdb/i386-interix-nat.c
new file mode 100644
index 0000000..9c4daed
--- /dev/null
+++ b/gdb/i386-interix-nat.c
@@ -0,0 +1,190 @@
+/* Native-dependent code for Interix running on i386's, for GDB.
+ Copyright 2002 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+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. */
+
+#include "defs.h"
+
+#include <sys/procfs.h>
+#include <inferior.h>
+#include <fcntl.h>
+
+#include <i386-tdep.h>
+#include "gdb_string.h"
+#include "gdbcore.h"
+#include "gregset.h"
+#include "regcache.h"
+
+typedef unsigned long greg_t;
+
+/* This is a duplicate of the table in i386-linux-nat.c. */
+
+static int regmap[] = {
+ EAX, ECX, EDX, EBX,
+ UESP, EBP, ESI, EDI,
+ EIP, EFL, CS, SS,
+ DS, ES, FS, GS,
+};
+
+/* Forward declarations. */
+extern void _initialize_core_interix (void);
+extern initialize_file_ftype _initialize_core_interix;
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregset_t *gregsetp)
+{
+ int regi;
+ greg_t *regp = (greg_t *) & gregsetp->gregs;
+
+ for (regi = 0; regi < I386_NUM_GREGS; regi++)
+ {
+ supply_register (regi, (char *) (regp + regmap[regi]));
+ }
+}
+
+/* Store GDB's value for REGNO in *GREGSETP. If REGNO is -1, do all
+ of them. */
+
+void
+fill_gregset (gregset_t *gregsetp, int regno)
+{
+ int regi;
+ greg_t *regp = (greg_t *) gregsetp->gregs;
+
+ for (regi = 0; regi < I386_NUM_GREGS; regi++)
+ if (regno == -1 || regi == regno)
+ regcache_collect (regi, (void *) (regp + regmap[regi]));
+}
+
+/* Fill GDB's register file with the floating-point register values in
+ *FPREGSETP. */
+
+void
+supply_fpregset (fpregset_t *fpregsetp)
+{
+ i387_supply_fsave ((char *) fpregsetp);
+}
+
+/* Given a pointer to a floating point register set in (fpregset_t *)
+ format, update all of the registers from gdb's idea of the current
+ floating point register set. */
+
+void
+fill_fpregset (fpregset_t *fpregsetp, int regno)
+{
+ i387_fill_fsave ((char *) fpregsetp, regno);
+}
+
+/* Read the values of either the general register set (WHICH equals 0)
+ or the floating point register set (WHICH equals 2) from the core
+ file data (pointed to by CORE_REG_SECT), and update gdb's idea of
+ their current values. The CORE_REG_SIZE parameter is compared to
+ the size of the gregset or fpgregset structures (as appropriate) to
+ validate the size of the structure from the core file. The
+ REG_ADDR parameter is ignored. */
+
+static void
+fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
+ CORE_ADDR reg_addr)
+{
+ gdb_gregset_t gregset;
+ gdb_fpregset_t fpregset;
+
+ if (which == 0)
+ {
+ if (core_reg_size != sizeof (gregset))
+ {
+ warning ("wrong size gregset struct in core file");
+ }
+ else
+ {
+ memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
+ supply_gregset (&gregset);
+ }
+ }
+ else if (which == 2)
+ {
+ if (core_reg_size != sizeof (fpregset))
+ {
+ warning ("wrong size fpregset struct in core file");
+ }
+ else
+ {
+ memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
+ supply_fpregset (&fpregset);
+ }
+ }
+}
+
+#include <setjmp.h>
+
+static struct core_fns interix_core_fns =
+{
+ bfd_target_coff_flavour, /* core_flavour (more or less) */
+ default_check_format, /* check_format */
+ default_core_sniffer, /* core_sniffer */
+ fetch_core_registers, /* core_read_registers */
+ NULL /* next */
+};
+
+void
+_initialize_core_interix (void)
+{
+ add_core_fns (&interix_core_fns);
+}
+
+/* We don't have a /proc/pid/file or /proc/pid/exe to read a link from,
+ so read it from the same place ps gets the name. */
+
+char *
+child_pid_to_exec_file (int pid)
+{
+ char *path;
+ char *buf;
+ int fd, c;
+ char *p;
+
+ xasprintf (&path, "/proc/%d/stat", pid);
+ buf = xcalloc (MAXPATHLEN + 1, sizeof (char));
+ make_cleanup (xfree, path);
+ make_cleanup (xfree, buf);
+
+ fd = open (path, O_RDONLY);
+
+ if (fd < 0)
+ return NULL;
+
+ /* Skip over "Argv0\t". */
+ lseek (fd, 6, SEEK_SET);
+
+ c = read (fd, buf, MAXPATHLEN);
+ close (fd);
+
+ if (c < 0)
+ return NULL;
+
+ buf[c] = '\0'; /* Ensure null termination. */
+ p = strchr (buf, '\n');
+ if (p != NULL)
+ *p = '\0';
+
+ return buf;
+}