]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
This commit was manufactured by cvs2svn to create branch
authornobody <>
Sat, 2 Nov 2002 15:13:35 +0000 (15:13 +0000)
committernobody <>
Sat, 2 Nov 2002 15:13:35 +0000 (15:13 +0000)
'kseitz_interps-20020528-branch'.

Cherrypick from master 2002-11-02 15:13:34 UTC Andrew Cagney <cagney@redhat.com> '2002-11-02  Andrew Cagney  <cagney@redhat.com>':
    bfd/elf32-qnx.c
    bfd/simple.c
    gdb/config/i386/interix.mh
    gdb/config/i386/interix.mt
    gdb/config/i386/nm-interix.h
    gdb/i386-interix-nat.c
    gdb/i386-interix-tdep.c
    gdb/i386obsd-tdep.c
    gdb/reggroups.c
    gdb/reggroups.h
    gdb/testsuite/gdb.asm/mips.inc
    gdb/testsuite/gdb.c++/casts.cc
    gdb/testsuite/gdb.c++/casts.exp
    gdb/testsuite/gdb.mi/mi1-pthreads.exp

14 files changed:
bfd/elf32-qnx.c [new file with mode: 0644]
bfd/simple.c [new file with mode: 0644]
gdb/config/i386/interix.mh [new file with mode: 0644]
gdb/config/i386/interix.mt [new file with mode: 0644]
gdb/config/i386/nm-interix.h [new file with mode: 0644]
gdb/i386-interix-nat.c [new file with mode: 0644]
gdb/i386-interix-tdep.c [new file with mode: 0644]
gdb/i386obsd-tdep.c [new file with mode: 0644]
gdb/reggroups.c [new file with mode: 0644]
gdb/reggroups.h [new file with mode: 0644]
gdb/testsuite/gdb.asm/mips.inc [new file with mode: 0644]
gdb/testsuite/gdb.c++/casts.cc [new file with mode: 0644]
gdb/testsuite/gdb.c++/casts.exp [new file with mode: 0644]
gdb/testsuite/gdb.mi/mi1-pthreads.exp [new file with mode: 0644]

diff --git a/bfd/elf32-qnx.c b/bfd/elf32-qnx.c
new file mode 100644 (file)
index 0000000..b397c38
--- /dev/null
@@ -0,0 +1,92 @@
+/* QNX specific support for 32-bit ELF
+   Copyright 2002  Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   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 "bfd.h"
+#include "sysdep.h"
+#include "elf-bfd.h"
+#include "elf32-qnx.h"
+
+/* Returns the end address of the segment + 1.  */
+#define SEGMENT_END(segment, start)                     \
+  (start + (segment->p_memsz > segment->p_filesz        \
+   ? segment->p_memsz : segment->p_filesz))
+
+boolean
+elf_qnx_copy_private_bfd_data_p (ibfd, isec, obfd, osec)
+     bfd *ibfd ATTRIBUTE_UNUSED;
+     asection *isec;
+     bfd *obfd ATTRIBUTE_UNUSED;
+     asection *osec ATTRIBUTE_UNUSED;
+{
+  return isec->next == NULL;
+}
+
+boolean
+elf_qnx_is_contained_by_filepos (section, segment)
+     asection *section;
+     Elf_Internal_Phdr *segment;
+{
+  return ((bfd_vma) section->filepos >= segment->p_offset
+          && ((bfd_vma) section->filepos + section->_raw_size
+             <= SEGMENT_END (segment, segment->p_offset)));
+}
+
+void
+elf_qnx_set_nonloadable_filepos (abfd, phdrs)
+     bfd *abfd;
+     Elf_Internal_Phdr *phdrs;
+{
+  struct elf_segment_map *m;
+  Elf_Internal_Phdr *p;
+  file_ptr off = 0;
+
+  for (m = elf_tdata (abfd)->segment_map, p = phdrs;
+       m != NULL;
+       m = m->next, p++)
+    {
+      unsigned int i;
+      asection **secpp;
+
+      for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
+        {
+          asection *sec;
+
+          sec = *secpp;
+
+          if (p->p_type == PT_LOAD)
+           off = sec->filepos;
+          else
+            {
+              if (i == 0)
+                {
+                  if (sec->filepos)
+                    p->p_offset = sec->filepos;
+                  else
+                    p->p_offset = off;
+                }
+              if (!sec->filepos)
+                {
+                  off += sec->_raw_size;
+                  p->p_filesz += sec->_raw_size;
+                }
+            }
+        }
+    }
+  return;
+}
diff --git a/bfd/simple.c b/bfd/simple.c
new file mode 100644 (file)
index 0000000..10178a4
--- /dev/null
@@ -0,0 +1,197 @@
+/* simple.c -- BFD simple client routines
+   Copyright 2002
+   Free Software Foundation, Inc.
+   Contributed by MontaVista Software, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   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 "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+
+static boolean simple_dummy_warning
+  PARAMS ((struct bfd_link_info *, const char *, const char *, bfd *,
+          asection *, bfd_vma));
+
+static boolean simple_dummy_undefined_symbol
+  PARAMS ((struct bfd_link_info *, const char *, bfd *, asection *,
+          bfd_vma, boolean));
+
+static boolean simple_dummy_reloc_overflow 
+  PARAMS ((struct bfd_link_info *, const char *, const char *, bfd_vma,
+          bfd *, asection *, bfd_vma));
+
+static boolean simple_dummy_reloc_dangerous
+  PARAMS ((struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma));
+
+static boolean simple_dummy_unattached_reloc
+  PARAMS ((struct bfd_link_info *, const char *, bfd *, asection *, bfd_vma));
+
+bfd_byte * bfd_simple_get_relocated_section_contents
+  PARAMS ((bfd *, asection *, bfd_byte *));
+
+static boolean
+simple_dummy_warning (link_info, warning, symbol, abfd, section, address)
+     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
+     const char *warning ATTRIBUTE_UNUSED;
+     const char *symbol ATTRIBUTE_UNUSED;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *section ATTRIBUTE_UNUSED;
+     bfd_vma address ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+static boolean
+simple_dummy_undefined_symbol (link_info, name, abfd, section, address, fatal)
+     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
+     const char *name ATTRIBUTE_UNUSED;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *section ATTRIBUTE_UNUSED;
+     bfd_vma address ATTRIBUTE_UNUSED;
+     boolean fatal ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+static boolean
+simple_dummy_reloc_overflow (link_info, name, reloc_name, addend, abfd,
+                            section, address)
+     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
+     const char *name ATTRIBUTE_UNUSED;
+     const char *reloc_name ATTRIBUTE_UNUSED;
+     bfd_vma addend ATTRIBUTE_UNUSED;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *section ATTRIBUTE_UNUSED;
+     bfd_vma address ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+static boolean
+simple_dummy_reloc_dangerous (link_info, message, abfd, section, address)
+     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
+     const char *message ATTRIBUTE_UNUSED;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *section ATTRIBUTE_UNUSED;
+     bfd_vma address ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+static boolean
+simple_dummy_unattached_reloc (link_info, name, abfd, section, address)
+     struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
+     const char *name ATTRIBUTE_UNUSED;
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *section ATTRIBUTE_UNUSED;
+     bfd_vma address ATTRIBUTE_UNUSED;
+{
+  return true;
+}
+
+/*
+FUNCTION
+       bfd_simple_relocate_secton
+
+SYNOPSIS
+       bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf);
+
+DESCRIPTION
+       Returns the relocated contents of section @var{sec}.  Only symbols
+       from @var{abfd} and the output offsets assigned to sections in
+       @var{abfd} are used.  The result will be stored at @var{outbuf}
+       or allocated with @code{bfd_malloc} if @var{outbuf} is @code{NULL}.
+
+       Generally all sections in @var{abfd} should have their
+       @code{output_section} pointing back to the original section.
+
+       Returns @code{NULL} on a fatal error; ignores errors applying
+       particular relocations.
+*/
+
+bfd_byte *
+bfd_simple_get_relocated_section_contents (abfd, sec, outbuf)
+     bfd *abfd;
+     asection *sec;
+     bfd_byte *outbuf;
+{
+  struct bfd_link_info link_info;
+  struct bfd_link_order link_order;
+  struct bfd_link_callbacks callbacks;
+  bfd_byte *contents, *data;
+  int storage_needed, number_of_symbols;
+  asymbol **symbol_table;
+
+  /* In order to use bfd_get_relocated_section_contents, we need
+     to forge some data structures that it expects.  */
+
+  /* Fill in the bare minimum number of fields for our purposes.  */
+  memset (&link_info, 0, sizeof (link_info));
+  link_info.input_bfds = abfd;
+
+  link_info.hash = bfd_link_hash_table_create (abfd);
+  link_info.callbacks = &callbacks;
+  callbacks.warning = simple_dummy_warning;
+  callbacks.undefined_symbol = simple_dummy_undefined_symbol;
+  callbacks.reloc_overflow = simple_dummy_reloc_overflow;
+  callbacks.reloc_dangerous = simple_dummy_reloc_dangerous;
+  callbacks.unattached_reloc = simple_dummy_unattached_reloc;
+
+  memset (&link_order, 0, sizeof (link_order));
+  link_order.next = NULL;
+  link_order.type = bfd_indirect_link_order;
+  link_order.offset = 0;
+  link_order.size = bfd_section_size (abfd, sec);
+  link_order.u.indirect.section = sec;
+
+  data = NULL;
+  if (outbuf == NULL)
+    {
+      data = bfd_malloc (bfd_section_size (abfd, sec));
+      if (data == NULL)
+       return NULL;
+      outbuf = data;
+    }
+  bfd_link_add_symbols (abfd, &link_info);
+
+  storage_needed = bfd_get_symtab_upper_bound (abfd);
+  symbol_table = (asymbol **) bfd_malloc (storage_needed);
+  number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+
+  contents = bfd_get_relocated_section_contents (abfd,
+                                                &link_info,
+                                                &link_order,
+                                                outbuf,
+                                                0,
+                                                symbol_table);
+  if (contents == NULL && data != NULL)
+    free (data);
+
+  /* Foul hack to prevent bfd_section_size aborts.  This flag only controls
+     that macro (and the related size macros), selecting between _raw_size
+     and _cooked_size.  Debug sections won't change size while we're only
+     relocating.  There may be trouble here someday if it tries to run
+     relaxation unexpectedly, so make sure.  */
+  BFD_ASSERT (sec->_raw_size == sec->_cooked_size);
+  sec->reloc_done = 0;
+
+  bfd_link_hash_table_free (abfd, link_info.hash);
+
+  return contents;
+}
diff --git a/gdb/config/i386/interix.mh b/gdb/config/i386/interix.mh
new file mode 100644 (file)
index 0000000..23311d6
--- /dev/null
@@ -0,0 +1,9 @@
+# Host: Intel 386 running Interix
+XDEPFILES= 
+NATDEPFILES= corelow.o core-regset.o fork-child.o i386-interix-nat.o \
+       procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o
+NAT_FILE= nm-interix.h
+XM_FILE= xm-interix.h
+# The below may be temporary; mmalloc relies on sbrk() at the moment
+MMALLOC=
+MMALLOC_CFLAGS=-DNO_MMALLOC
diff --git a/gdb/config/i386/interix.mt b/gdb/config/i386/interix.mt
new file mode 100644 (file)
index 0000000..8d60962
--- /dev/null
@@ -0,0 +1,3 @@
+# Target: Intel 386 running Interix
+TDEPFILES= i386-tdep.o i387-tdep.o i386-interix-tdep.o solib.o solib-pei.o
+TM_FILE= tm-i386.h
diff --git a/gdb/config/i386/nm-interix.h b/gdb/config/i386/nm-interix.h
new file mode 100644 (file)
index 0000000..b8b003a
--- /dev/null
@@ -0,0 +1,35 @@
+/* Native-dependent definitions for Intel 386 running Interix, for GDB.
+   Copyright 1986, 1987, 1989, 1992, 1996 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.  */
+
+#ifndef NM_INTERIX_H
+#define NM_INTERIX_H
+
+/* Be shared lib aware.  */
+#include "solib.h"
+
+/* submodes of USE_PROC_FS.  */
+#define UNIXWARE
+
+/* It's ALMOST coff; bfd does the same thing. Mostly used in coffread.c.  */
+#define COFF_IMAGE_WITH_PE
+
+/* Turn on our own child_pid_to_exec_file.  */
+#define CHILD_PID_TO_EXEC_FILE
+
+#endif /* NM_INTERIX_H */
diff --git a/gdb/i386-interix-nat.c b/gdb/i386-interix-nat.c
new file mode 100644 (file)
index 0000000..9c4daed
--- /dev/null
@@ -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;
+}
diff --git a/gdb/i386-interix-tdep.c b/gdb/i386-interix-tdep.c
new file mode 100644 (file)
index 0000000..ff310ec
--- /dev/null
@@ -0,0 +1,365 @@
+/* Target-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 "arch-utils.h"
+
+#include "frame.h"
+#include "gdb_string.h"
+#include "gdb-stabs.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "i386-tdep.h"
+#include "inferior.h"
+#include "libbfd.h"
+#include "objfiles.h"
+#include "osabi.h"
+#include "regcache.h"
+
+/* offsetof (mcontext_t, gregs.gregs[EBP]) */
+static const int mcontext_EBP_greg_offset = 180;
+
+/* offsetof (mcontext_t, gregs.gregs[EIP]) */
+static const int mcontext_EIP_greg_offset = 184;
+
+/* offsetof (mcontext_t, gregs.gregs[UESP]) */
+static const int mcontext_UESP_greg_offset = 196;
+
+/* offsetof (mcontext_t, gregs.reserved[1]) */
+static const int mcontext_syscall_greg_offset = 4;
+
+/* offsetof (_JUMP_BUFFER, Eip) */
+static const int jump_buffer_Eip_offset = 20;
+
+/* See procfs.c and *interix*.h in config/[alpha,i386].  */
+/* ??? These should be static, but this needs a bit of work before this
+   can be done.  */
+CORE_ADDR tramp_start;
+CORE_ADDR tramp_end;
+CORE_ADDR null_start;
+CORE_ADDR null_end;
+int winver;                     /* Windows NT version number */
+
+/* Forward declarations.  */
+extern void _initialize_i386_interix_tdep (void);
+extern initialize_file_ftype _initialize_i386_interix_tdep;
+
+/* Adjust the section offsets in an objfile structure so that it's correct
+   for the type of symbols being read (or undo it with the _restore
+   arguments).  
+
+   If main programs ever start showing up at other than the default Image
+   Base, this is where that would likely be applied.  */
+
+void
+pei_adjust_objfile_offsets (struct objfile *objfile,
+                            enum objfile_adjusts type)
+{
+  int i;
+  CORE_ADDR symbols_offset;
+
+  switch (type)
+    {
+    case adjust_for_symtab:
+      symbols_offset = NONZERO_LINK_BASE (objfile->obfd);
+      break;
+    case adjust_for_symtab_restore:
+      symbols_offset = -NONZERO_LINK_BASE (objfile->obfd);
+      break;
+    case adjust_for_stabs:
+    case adjust_for_stabs_restore:
+    case adjust_for_dwarf:
+    case adjust_for_dwarf_restore:
+    default:
+      return;
+    }
+
+  for (i = 0; i < SECT_OFF_MAX; i++)
+    {
+      (objfile->section_offsets)->offsets[i] += symbols_offset;
+    }
+}
+
+static int
+i386_interix_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  /* This is sufficient, where used, but is NOT a complete test; There
+     is more in INIT_EXTRA_FRAME_INFO (a.k.a. interix_back_one_frame).  */
+  return ((pc >= tramp_start && pc < tramp_end)
+          || (pc >= null_start && pc < null_end));
+}
+
+static int
+i386_interix_in_solib_call_trampoline (CORE_ADDR pc, char *name)
+{
+  return i386_pe_skip_trampoline_code (pc, name);
+}
+
+static CORE_ADDR
+i386_interix_skip_trampoline_code (CORE_ADDR pc)
+{
+  return i386_pe_skip_trampoline_code (pc, 0);
+}
+
+static void
+i386_interix_init_frame_pc (int fromleaf, struct frame_info *prev)
+{
+  /* Nothing to do on Interix.  */
+}
+
+static int
+i386_interix_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
+{
+  /* In the context where this is used, we get the saved PC before we've
+     successfully unwound far enough to be sure what we've got (it may
+     be a signal handler caller).  If we're dealing with a signal
+     handler caller, this will return valid, which is fine.  If not,
+     it'll make the correct test.  */
+  return (thisframe->signal_handler_caller
+          || (chain != 0
+              && !inside_entry_file (read_memory_integer
+                                     (thisframe->frame + 4, 4))));
+}
+
+/* We want to find the previous frame, which on Interix is tricky when signals
+   are involved; set frame->frame appropriately, and also get the pc
+   and tweak signal_handler_caller; this replaces a boatload of nested
+   macros, as well.  */
+static void
+i386_interix_back_one_frame (int fromleaf, struct frame_info *frame)
+{
+  CORE_ADDR ra;
+  CORE_ADDR fm;
+  CORE_ADDR context;
+  long t;
+
+  if (frame == NULL)
+    internal_error (__FILE__, __LINE__, "unexpected NULL frame");
+
+  if (fromleaf)
+    {
+      frame->pc = SAVED_PC_AFTER_CALL (frame->next);
+      return;
+    }
+
+  if (!frame->next)
+    {
+      frame->pc = read_pc ();
+
+      /* Part of the signal stuff...  See below.  */
+      if (stopped_by_random_signal)
+        {
+          /* We know we're in a system call mini-frame; was it
+             NullApi or something else?  */
+          ra = SAVED_PC_AFTER_CALL (frame);
+          if (ra >= null_start && ra < null_end)
+            frame->signal_handler_caller = 1;
+          /* There might also be an indirect call to the mini-frame,
+             putting one more return address on the stack.  (XP only,
+             I think?)  This can't (reasonably) return the address of the 
+             signal handler caller unless it's that situation, so this
+             is safe.  */
+          ra = read_memory_unsigned_integer (read_register (SP_REGNUM) + 4, 4);
+          if (ra >= null_start && ra < null_end)
+            frame->signal_handler_caller = 1;
+        }
+      return;
+    }
+
+  if (!frame->next->signal_handler_caller)
+    {
+      frame->pc = read_memory_integer (frame->next->frame + 4, 4);
+      return;
+    }
+
+  /* This is messy (actually AWFUL)...  The "trampoline" might be 2, 3 
+     or all 5 entities on the frame. 
+
+     Chunk 1 will be present when we're actually in a signal handler.
+     Chunk 2 will be present when an asynchronous signal (one that
+     didn't come in with a system call) is present.
+     We may not (yet) be in the handler, if we're just returning
+     from the call.
+     When we're actually in a handler taken from an asynchronous
+     signal, both will be present.
+
+     Chunk 1:
+     PdxSignalDeliverer's frame 
+     + Context struct    -- not accounted for in any frame
+
+     Chunk 2:
+     + PdxNullPosixApi's frame 
+     + PdxNullApiCaller's frame
+     + Context struct = 0x230  not accounted for in any frame
+
+     The symbol names come from examining objdumps of psxdll.dll;
+     they don't appear in the runtime image.
+
+     For gdb's purposes, we can pile all this into one frame.  */
+
+  ra = frame->next->pc;
+  /* Are we already pointing at PdxNullPosixApi?  We are if
+     this is a signal frame, we're at next-to-top, and were stopped
+     by a random signal (if it wasn't the right address under
+     these circumstances, we wouldn't be here at all by tests above
+     on the prior frame).  */
+  if (frame->next->next == NULL && stopped_by_random_signal)
+    {
+      /* We're pointing at the frame FOR PdxNullApi.  */
+      fm = frame->frame;
+    }
+  else
+    {
+      /* No...  We must be pointing at the frame that was called
+         by PdxSignalDeliverer; back up across the whole mess.  */
+
+      /* Extract the frame for PdxSignalDeliverer.
+         Note: FRAME_CHAIN used the "old" frame pointer because we were
+         a deliverer.  Get the address of the context record that's on
+         here frameless.  */
+      context = read_memory_integer (frame->frame, 4);  /* an Arg */
+
+      /* Now extract the frame pointer contained in the context.  */
+      fm = read_memory_integer (context + mcontext_EBP_greg_offset, 4);
+
+      ra = read_memory_integer (context + mcontext_EIP_greg_offset, 4);
+
+      /* We need to know if we're in a system call because we'll be
+         in a syscall mini-frame, if so, and the rules are different.  */
+      t = (long) read_memory_integer (context + mcontext_syscall_greg_offset,
+                                      4);
+      /* t contains 0 if running free, 1 if blocked on a system call,
+         and 2 if blocked on an exception message (e.g. a trap);
+         we don't expect to get here with a 2.  */
+      if (t != 1)
+        {
+          /* Not at a system call, therefore it can't be NullApi.  */
+          frame->pc = ra;
+          frame->frame = fm;
+          return;
+        }
+
+      /* It's a system call...  Mini frame, then look for NullApi.  */
+      /* Get the RA (on the stack) associated with this...  It's
+         a system call mini-frame.  */
+      ra = read_memory_integer (context + mcontext_UESP_greg_offset, 4);
+
+      if (winver >= 51)
+        {
+          /* Newer versions of Windows NT interpose another return
+             address (but no other "stack frame" stuff) that we need
+             to simply ignore here.  */
+          ra += 4;
+        }
+
+      ra = read_memory_integer (ra, 4);
+
+      if (!(ra >= null_start && ra < null_end))
+        {
+          /* No Null API present; we're done.  */
+          frame->pc = ra;
+          frame->frame = fm;
+          return;
+        }
+    }
+
+  /* At this point, we're looking at the frame for PdxNullPosixApi,
+     in either case.
+
+     PdxNullPosixApi is called by PdxNullApiCaller (which in turn
+     is called by _PdxNullApiCaller (note the _).)
+     PdxNullPosixApiCaller (no _) is a frameless function.
+
+     The saved frame pointer is as fm, but it's not of interest
+     to us because it skips us over the saved context, which is
+     the wrong thing to do, because it skips the interrrupted
+     routine!  PdxNullApiCaller takes as its only argument the
+     address of the context of the interrupded function (which
+     is really in no frame, but jammed on the stack by the system)
+
+     So: fm+0: saved bp
+     fm+4: return address to _PdxNullApiCaller
+     fm+8: arg to PdxNullApiCaller pushed by _Pdx...  */
+
+  fm = read_memory_integer (fm + 0x8, 4);
+
+  /* Extract the second context record.  */
+
+  ra = read_memory_integer (fm + mcontext_EIP_greg_offset, 4);
+  fm = read_memory_integer (fm + mcontext_EBP_greg_offset, 4);
+
+  frame->frame = fm;
+  frame->pc = ra;
+
+  return;
+}
+
+static CORE_ADDR
+i386_interix_frame_saved_pc (struct frame_info *fi)
+{
+  /* Assume that we've already unwound enough to have the caller's address
+     if we're dealing with a signal handler caller (And if that fails,
+     return 0).  */
+  if (fi->signal_handler_caller)
+    return fi->next ? fi->next->pc : 0;
+  else
+    return read_memory_integer (fi->frame + 4, 4);
+}
+
+static void
+i386_interix_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  tdep->struct_return = reg_struct_return;
+  tdep->jb_pc_offset = jump_buffer_Eip_offset;
+
+  set_gdbarch_decr_pc_after_break (gdbarch, 0);
+  set_gdbarch_pc_in_sigtramp (gdbarch, i386_interix_pc_in_sigtramp);
+  set_gdbarch_in_solib_call_trampoline (gdbarch,
+                                        i386_interix_in_solib_call_trampoline);
+  set_gdbarch_skip_trampoline_code (gdbarch,
+                                    i386_interix_skip_trampoline_code);
+  set_gdbarch_init_extra_frame_info (gdbarch, i386_interix_back_one_frame);
+  set_gdbarch_init_frame_pc (gdbarch, i386_interix_init_frame_pc);
+  set_gdbarch_frame_chain_valid (gdbarch, i386_interix_frame_chain_valid);
+  set_gdbarch_frame_saved_pc (gdbarch, i386_interix_frame_saved_pc);
+  set_gdbarch_name_of_malloc (gdbarch, "_malloc");
+}
+
+static enum gdb_osabi
+i386_interix_osabi_sniffer (bfd * abfd)
+{
+  char *target_name = bfd_get_target (abfd);
+
+  if (strcmp (target_name, "pei-i386") == 0)
+    return GDB_OSABI_INTERIX;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+void
+_initialize_i386_interix_tdep (void)
+{
+  gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
+                                  i386_interix_osabi_sniffer);
+
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_INTERIX,
+                          i386_interix_init_abi);
+}
diff --git a/gdb/i386obsd-tdep.c b/gdb/i386obsd-tdep.c
new file mode 100644 (file)
index 0000000..7f16237
--- /dev/null
@@ -0,0 +1,122 @@
+/* Target-dependent code for OpenBSD/i386.
+   Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 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 "arch-utils.h"
+#include "gdbcore.h"
+#include "regcache.h"
+
+#include "i386-tdep.h"
+#include "i387-tdep.h"
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_i386obsd_tdep (void);
+
+#define SIZEOF_STRUCT_REG      (16 * 4)
+
+static void
+i386obsd_supply_reg (char *regs, int regno)
+{
+  int i;
+
+  for (i = 0; i <= 15; i++)
+    if (regno == i || regno == -1)
+      supply_register (i, regs + i * 4);
+}
+
+static void
+fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
+                      CORE_ADDR ignore)
+{
+  char *regs, *fsave;
+
+  /* We get everything from one section.  */
+  if (which != 0)
+    return;
+
+  if (core_reg_size < (SIZEOF_STRUCT_REG + 108))
+    {
+      warning ("Wrong size register set in core file.");
+      return;
+    }
+
+  regs = core_reg_sect;
+  fsave = core_reg_sect + SIZEOF_STRUCT_REG;
+
+  /* Integer registers.  */
+  i386obsd_supply_reg (regs, -1);
+
+  /* Floating point registers.  */
+  i387_supply_fsave (fsave);
+}
+
+static struct core_fns i386obsd_core_fns =
+{
+  bfd_target_unknown_flavour,          /* core_flavour */
+  default_check_format,                        /* check_format */
+  default_core_sniffer,                        /* core_sniffer */
+  fetch_core_registers,                        /* core_read_registers */
+  NULL                                 /* next */
+};
+\f
+
+CORE_ADDR i386obsd_sigtramp_start = 0xbfbfdf20;
+CORE_ADDR i386obsd_sigtramp_end = 0xbfbfdff0;
+
+/* From <machine/signal.h>.  */
+int i386obsd_sc_pc_offset = 44;
+int i386obsd_sc_sp_offset = 56;
+
+static void 
+i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* Obviously OpenBSD is BSD-based.  */
+  i386bsd_init_abi (info, gdbarch);
+
+  /* OpenBSD uses -freg-struct-return by default.  */
+  tdep->struct_return = reg_struct_return;
+
+  /* OpenBSD uses a different memory layout.  */
+  tdep->sigtramp_start = i386obsd_sigtramp_start;
+  tdep->sigtramp_end = i386obsd_sigtramp_end;
+
+  /* OpenBSD has a `struct sigcontext' that's different from the
+     origional 4.3 BSD.  */
+  tdep->sc_pc_offset = i386obsd_sc_pc_offset;
+  tdep->sc_sp_offset = i386obsd_sc_sp_offset;
+}
+
+void
+_initialize_i386obsd_tdep (void)
+{
+  add_core_fns (&i386obsd_core_fns);
+
+  /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are
+     indistingushable from NetBSD/i386 a.out binaries, building a GDB
+     that should support both these targets will probably not work as
+     expected.  */
+#define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT
+
+  gdbarch_register_osabi (bfd_arch_i386, GDB_OSABI_OPENBSD_AOUT,
+                         i386obsd_init_abi);
+}
diff --git a/gdb/reggroups.c b/gdb/reggroups.c
new file mode 100644 (file)
index 0000000..8c3cbb7
--- /dev/null
@@ -0,0 +1,268 @@
+/* Register groupings for GDB, the GNU debugger.
+
+   Copyright 2002 Free Software Foundation, Inc.
+
+   Contributed by Red Hat.
+
+   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 "reggroups.h"
+#include "gdbtypes.h"
+#include "gdb_assert.h"
+#include "regcache.h"
+#include "command.h"
+#include "gdbcmd.h"            /* For maintenanceprintlist.  */
+
+/* Individual register groups.  */
+
+struct reggroup
+{
+  const char *name;
+  enum reggroup_type type;
+};
+
+struct reggroup *
+reggroup_new (const char *name, enum reggroup_type type)
+{
+  struct reggroup *group = XMALLOC (struct reggroup);
+  group->name = name;
+  group->type = type;
+  return group;
+}
+
+/* Register group attributes.  */
+
+const char *
+reggroup_name (struct reggroup *group)
+{
+  return group->name;
+}
+
+enum reggroup_type
+reggroup_type (struct reggroup *group)
+{
+  return group->type;
+}
+
+/* All the groups for a given architecture.  */
+
+struct reggroups
+{
+  int nr_group;
+  struct reggroup **group;
+};
+
+static struct gdbarch_data *reggroups_data;
+
+static void *
+reggroups_init (struct gdbarch *gdbarch)
+{
+  struct reggroups *groups = XMALLOC (struct reggroups);
+  groups->nr_group = 0;
+  groups->group = NULL;
+  return groups;
+}
+
+static void
+reggroups_free (struct gdbarch *gdbarch, void *data)
+{
+  struct reggroups *groups = data;
+  xfree (groups->group);
+  xfree (groups);
+}
+
+/* Add a register group (with attribute values) to the pre-defined
+   list.  This function can be called during architecture
+   initialization and hence needs to handle NULL architecture groups.  */
+
+static void
+add_group (struct reggroups *groups, struct reggroup *group)
+{
+  gdb_assert (group != NULL);
+  groups->nr_group++;
+  groups->group = xrealloc (groups->group, (sizeof (struct reggroup *)
+                                           * (groups->nr_group + 1)));
+  groups->group[groups->nr_group - 1] = group;
+  groups->group[groups->nr_group] = NULL;
+}
+
+void
+reggroup_add (struct gdbarch *gdbarch, struct reggroup *group)
+{
+  struct reggroups *groups = gdbarch_data (gdbarch, reggroups_data);
+  if (groups == NULL)
+    {
+      /* ULGH, called during architecture initialization.  Patch
+         things up.  */
+      groups = reggroups_init (gdbarch);
+      set_gdbarch_data (gdbarch, reggroups_data, groups);
+    }
+  add_group (groups, group);
+}
+
+/* The register groups for the current architecture.  Mumble something
+   about the lifetime of the buffer....  */
+
+static struct reggroups *default_groups;
+
+struct reggroup * const*
+reggroups (struct gdbarch *gdbarch)
+{
+  struct reggroups *groups = gdbarch_data (gdbarch, reggroups_data);
+  /* Don't allow this function to be called during architecture
+     creation.  */
+  gdb_assert (groups != NULL);
+  if (groups->group == NULL)
+    return default_groups->group;
+  else
+    return groups->group;
+}
+
+/* Is REGNUM a member of REGGROUP?  */
+int
+default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                            struct reggroup *group)
+{
+  int vector_p;
+  int float_p;
+  int raw_p;
+  if (REGISTER_NAME (regnum) == NULL
+      || *REGISTER_NAME (regnum) == '\0')
+    return 0;
+  if (group == all_reggroup)
+    return 1;
+  vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
+  float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
+  raw_p = regnum < gdbarch_num_regs (gdbarch);
+  if (group == float_reggroup)
+    return float_p;
+  if (group == vector_reggroup)
+    return vector_p;
+  if (group == general_reggroup)
+    return (!vector_p && !float_p);
+  if (group == save_reggroup || group == restore_reggroup)
+    return raw_p;
+  return 0;   
+}
+
+/* Dump out a table of register groups for the current architecture.  */
+
+static void
+reggroups_dump (struct gdbarch *gdbarch, struct ui_file *file)
+{
+  struct reggroup *const *groups = reggroups (gdbarch);
+  int i = -1;
+  do
+    {
+      /* Group name.  */
+      {
+       const char *name;
+       if (i < 0)
+         name = "Group";
+       else
+         name = reggroup_name (groups[i]);
+       fprintf_unfiltered (file, " %-10s", name);
+      }
+      
+      /* Group type.  */
+      {
+       const char *type;
+       if (i < 0)
+         type = "Type";
+       else
+         {
+           switch (reggroup_type (groups[i]))
+             {
+             case USER_REGGROUP:
+               type = "user";
+               break;
+             case INTERNAL_REGGROUP:
+               type = "internal";
+               break;
+             default:
+               internal_error (__FILE__, __LINE__, "bad switch");
+             }
+         }
+       fprintf_unfiltered (file, " %-10s", type);
+      }
+
+      /* Note: If you change this, be sure to also update the
+         documentation.  */
+      
+      fprintf_unfiltered (file, "\n");
+      i++;
+    }
+  while (groups[i] != NULL);
+}
+
+static void
+maintenance_print_reggroups (char *args, int from_tty)
+{
+  if (args == NULL)
+    reggroups_dump (current_gdbarch, gdb_stdout);
+  else
+    {
+      struct ui_file *file = gdb_fopen (args, "w");
+      if (file == NULL)
+       perror_with_name ("maintenance print reggroups");
+      reggroups_dump (current_gdbarch, file);    
+      ui_file_delete (file);
+    }
+}
+
+/* Pre-defined register groups.  */
+static struct reggroup general_group = { "general", USER_REGGROUP };
+static struct reggroup float_group = { "float", USER_REGGROUP };
+static struct reggroup system_group = { "system", USER_REGGROUP };
+static struct reggroup vector_group = { "vector", USER_REGGROUP };
+static struct reggroup all_group = { "all", USER_REGGROUP };
+static struct reggroup save_group = { "save", INTERNAL_REGGROUP };
+static struct reggroup restore_group = { "restore", INTERNAL_REGGROUP };
+
+struct reggroup *const general_reggroup = &general_group;
+struct reggroup *const float_reggroup = &float_group;
+struct reggroup *const system_reggroup = &system_group;
+struct reggroup *const vector_reggroup = &vector_group;
+struct reggroup *const all_reggroup = &all_group;
+struct reggroup *const save_reggroup = &save_group;
+struct reggroup *const restore_reggroup = &restore_group;
+
+void
+_initialize_reggroup (void)
+{
+  reggroups_data = register_gdbarch_data (reggroups_init, reggroups_free);
+
+  /* The pre-defined list of groups.  */
+  default_groups = reggroups_init (NULL);
+  add_group (default_groups, general_reggroup);
+  add_group (default_groups, float_reggroup);
+  add_group (default_groups, system_reggroup);
+  add_group (default_groups, vector_reggroup);
+  add_group (default_groups, all_reggroup);
+  add_group (default_groups, save_reggroup);
+  add_group (default_groups, restore_reggroup);
+
+
+  add_cmd ("reggroups", class_maintenance,
+          maintenance_print_reggroups, "\
+Print the internal register group names.\n\
+Takes an optional file parameter.",
+          &maintenanceprintlist);
+
+}
diff --git a/gdb/reggroups.h b/gdb/reggroups.h
new file mode 100644 (file)
index 0000000..0088a85
--- /dev/null
@@ -0,0 +1,61 @@
+/* Register groupings for GDB, the GNU debugger.
+
+   Copyright 2002 Free Software Foundation, Inc.
+
+   Contributed by Red Hat.
+
+   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.  */
+
+#ifndef REGGROUPS_H
+#define REGGROUPS_H
+
+struct gdbarch;
+struct reggroup;
+
+enum reggroup_type { USER_REGGROUP, INTERNAL_REGGROUP };
+
+/* Pre-defined, user visible, register groups.  */
+extern struct reggroup *const general_reggroup;
+extern struct reggroup *const float_reggroup;
+extern struct reggroup *const system_reggroup;
+extern struct reggroup *const vector_reggroup;
+extern struct reggroup *const all_reggroup;
+
+/* Pre-defined, internal, register groups.  */
+extern struct reggroup *const save_reggroup;
+extern struct reggroup *const restore_reggroup;
+
+/* Create a new local register group.  */
+extern struct reggroup *reggroup_new (const char *name,
+                                     enum reggroup_type type);
+
+/* Add a register group (with attribute values) to the pre-defined list.  */
+extern void reggroup_add (struct gdbarch *gdbarch, struct reggroup *group);
+
+/* Register group attributes.  */
+extern const char *reggroup_name (struct reggroup *reggroup);
+extern enum reggroup_type reggroup_type (struct reggroup *reggroup);
+
+/* The register groups for the current architecture.  */
+extern struct reggroup *const *reggroups (struct gdbarch *gdbarch);
+
+/* Is REGNUM a member of REGGROUP?  */
+extern int default_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                                       struct reggroup *reggroup);
+
+#endif
diff --git a/gdb/testsuite/gdb.asm/mips.inc b/gdb/testsuite/gdb.asm/mips.inc
new file mode 100644 (file)
index 0000000..751f73f
--- /dev/null
@@ -0,0 +1,64 @@
+       comment "subroutine declare"
+       .macro gdbasm_declare name
+       .align  2
+       .ent    \name
+       .type   \name,@function
+\name:
+       .endm
+
+       comment "subroutine prologue"
+       .macro gdbasm_enter
+       .frame  $fp, 32, $31
+       .mask   0xd0000000,-4
+       .set    noreorder
+       .cpload $25
+       .set    reorder
+       subu    $sp, $sp, 32
+       .cprestore 16
+       sw      $31, 28($sp)
+       sw      $fp, 24($sp)
+       sw      $28, 20($sp)
+       move    $fp, $sp
+       .endm
+
+       comment "subroutine epilogue"
+       .macro gdbasm_leave
+       lw      $31, 28($sp)
+       lw      $fp, 24($sp)
+       .set    noreorder
+       .set    nomacro
+       j       $31
+       addu    $sp, $sp, 32
+       .set    macro
+       .set    reorder
+       .endm
+
+       comment "subroutine end"
+       .macro gdbasm_end name
+       .end    \name
+       .endm
+
+       .macro gdbasm_call subr
+       la      $25, \subr
+       jal     $31, $25
+       .endm
+
+       .macro gdbasm_several_nops
+       nop
+       nop
+       nop
+       nop
+       .endm
+
+       comment "exit (0)"
+       .macro gdbasm_exit0
+       comment "Don't know how to exit, but this will certainly halt..."
+       lw      $2, 0($0)
+       .endm
+
+       comment "crt0 startup"
+       .macro gdbasm_startup
+       .global __start
+__start:
+       move    $fp, $sp
+       .endm
diff --git a/gdb/testsuite/gdb.c++/casts.cc b/gdb/testsuite/gdb.c++/casts.cc
new file mode 100644 (file)
index 0000000..831add9
--- /dev/null
@@ -0,0 +1,20 @@
+struct A
+{
+  int a;
+  A (int aa): a (aa) {}
+};
+
+struct B: public A
+{
+  int b;
+  B (int aa, int bb): A (aa), b(bb) {}
+};
+
+int
+main (int argc, char **argv)
+{
+  A *a = new B(42, 1729);
+  B *b = (B *) a;
+
+  return 0;  /* breakpoint spot: casts.exp: 1 */
+}
diff --git a/gdb/testsuite/gdb.c++/casts.exp b/gdb/testsuite/gdb.c++/casts.exp
new file mode 100644 (file)
index 0000000..68ce704
--- /dev/null
@@ -0,0 +1,80 @@
+# Copyright 2002 Free Software Foundation, Inc.
+
+# 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.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file is part of the gdb testsuite
+
+# Test casting, especially between class types or pointer-to-class
+# types.
+
+# This file is part of the gdb testsuite
+
+if $tracelevel then {
+        strace $tracelevel
+        }
+
+#
+# test running programs
+#
+
+set prms_id 0
+set bug_id 0
+
+if { [skip_cplus_tests] } { continue }
+
+set testfile "casts"
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+
+if [get_compiler_info ${binfile} "c++"] {
+    return -1;
+}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "break [gdb_get_line_number "casts.exp: 1"]" \
+    "Breakpoint.*at.* file .*" \
+    ""
+
+gdb_test "run" "Breakpoint .* at casts.cc" ""
+
+# Casting a pointer to a base class to a pointer to a derived class
+# should yield the entire derived class.  Until August 2002, GDB got
+# the enclosing type on `(B *) a' wrong: while the value's static type
+# was `B *', as it should be, the enclosing type (which is supposed to
+# be the dynamic type) was `A *'.  It's senseless to have a static
+# type derived from the dynamic type; it should be the other way
+# 'round.  Dereferencing this oddly typed pointer yielded a value in
+# which only the base class's members were initialized, since GDB uses
+# the enclosing type to decide how many bytes to read.  Members from
+# the derived class were garbage, from GDB's address space.
+gdb_test "print * (B *) a" ".* = {<A> = {a = 42}, b = 1729}" \
+    "cast base class pointer to derived class pointer"
+
+# Check also that we get the same results from letting the compiler do
+# the dereference.
+gdb_test "print * b" ".* = {<A> = {a = 42}, b = 1729}" \
+    "let compiler cast base class pointer to derived class pointer"
diff --git a/gdb/testsuite/gdb.mi/mi1-pthreads.exp b/gdb/testsuite/gdb.mi/mi1-pthreads.exp
new file mode 100644 (file)
index 0000000..aea4f58
--- /dev/null
@@ -0,0 +1,220 @@
+# Copyright 2002 Free Software Foundation, Inc.
+
+# 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.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file tests MI thread commands.
+# Specifically, we are testing the MI command set and the console (in MI)
+# command set ("interpreter-exec") and that the commands that are executed
+# via these command pathways are properly executed. Console commands
+# executed via MI should use MI output wrappers, MI event handlers, etc.
+
+# This only works with native configurations
+if {![isnative]} {
+  return
+}
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi1"
+
+gdb_exit
+if {[mi_gdb_start]} {
+    continue
+}
+
+# The procs below dealing with parsing cli/mi output for the threadlist
+# is duplicated in gdb669.exp. Any changes here will probably need to
+# be made there as well.
+
+proc get_mi_thread_list {name} {
+  global expect_out
+
+  # MI will return a list of thread ids:
+  #
+  # -thread-list-ids
+  # ^done,thread-ids=[thread-id="1",thread-id="2",...],number-of-threads="N"
+  # (gdb)
+  mi_gdb_test "-thread-list-ids" \
+    {\^done,thread-ids={(thread-id="[0-9]+"(,)?)+},number-of-threads="[0-9]+"} \
+    "-thread_list_ids ($name)"
+
+  set output {}
+  if {[info exists expect_out(buffer)]} {
+    set output $expect_out(buffer)
+  }
+
+  set thread_list {}
+  if {![regexp {thread-ids=\{(thread-id="[0-9]+"(,)?)*\}} $output threads]} {
+    fail "finding threads in MI output ($name)"
+  } else {
+    pass "finding threads in MI output ($name)"
+
+    # Make list of console threads
+    set start [expr {[string first \{ $threads] + 1}]
+    set end   [expr {[string first \} $threads] - 1}]
+    set threads [string range $threads $start $end]
+    foreach thread [split $threads ,] {
+      if {[scan $thread {thread-id="%d"} num]} {
+       lappend thread_list $num
+      }
+    }
+  }
+
+  return $thread_list
+}
+
+# Check that MI and the console know of the same threads.
+# Appends NAME to all test names.
+proc check_mi_and_console_threads {name} {
+  global expect_out
+
+  mi_gdb_test "-thread-list-ids" \
+    {\^done,thread-ids={(thread-id="[0-9]+"(,)*)+},number-of-threads="[0-9]+"} \
+    "-thread-list-ids ($name)"
+  set mi_output {}
+  if {[info exists expect_out(buffer)]} {
+    set mi_output $expect_out(buffer)
+  }
+
+  # GDB will return a list of thread ids and some more info:
+  #
+  # (gdb) 
+  # -interpreter-exec console "info threads"
+  # ~"  4 Thread 2051 (LWP 7734)  0x401166b1 in __libc_nanosleep () at __libc_nanosleep:-1"
+  # ~"  3 Thread 1026 (LWP 7733)   () at __libc_nanosleep:-1"
+  # ~"  2 Thread 2049 (LWP 7732)  0x401411f8 in __poll (fds=0x804bb24, nfds=1, timeout=2000) at ../sysdeps/unix/sysv/linux/poll.c:63"
+  # ~"* 1 Thread 1024 (LWP 7731)  main (argc=1, argv=0xbfffdd94) at ../../../src/gdb/testsuite/gdb.mi/pthreads.c:160"
+  # FIXME: kseitz/2002-09-05: Don't use the hack-cli method.
+  mi_gdb_test "info threads" \
+    {.*(~".*"[\r\n]*)+.*} \
+    "info threads ($name)"
+  set console_output {}
+  if {[info exists $expect_out(buffer)]} {
+    set console_output $expect_out(buffer)
+  }
+
+  # Make a list of all known threads to console (gdb's thread IDs)
+  set console_thread_list {}
+  foreach line [split $console_output \n] {
+    if {[string index $line 0] == "~"} {
+      # This is a line from the console; trim off "~", " ", "*", and "\""
+      set line [string trim $line ~\ \"\*]
+      if {[scan $line "%d" id] == 1} {
+       lappend console_thread_list $id
+      }
+    }
+  }
+
+  # Now find the result string from MI
+  set mi_result ""
+  foreach line [split $mi_output \n] {
+    if {[string range $line 0 4] == "^done"} {
+      set mi_result $line
+    }
+  }
+  if {$mi_result == ""} {
+    fail "finding MI result string ($name)"
+  } else {
+    pass "finding MI result string ($name)"
+  }
+
+  # Finally, extract the thread ids and compare them to the console
+  set num_mi_threads_str ""
+  if {![regexp {number-of-threads="[0-9]+"} $mi_result num_mi_threads_str]} {
+    fail "finding number of threads in MI output ($name)"
+  } else {
+    pass "finding number of threads in MI output ($name)"
+
+    # Extract the number of threads from the MI result
+    if {![scan $num_mi_threads_str {number-of-threads="%d"} num_mi_threads]} {
+      fail "got number of threads from MI ($name)"
+    } else {
+      pass "got number of threads from MI ($name)"
+
+      # Check if MI and console have same number of threads
+      if {$num_mi_threads != [llength $console_thread_list]} {
+       fail "console and MI have same number of threads ($name)"
+      } else {
+       pass "console and MI have same number of threads ($name)"
+
+       # Get MI thread list
+       set mi_thread_list [get_mi_thread_list $name]
+
+       # Check if MI and console have the same threads
+       set fails 0
+       foreach ct [lsort $console_thread_list] mt [lsort $mi_thread_list] {
+         if {$ct != $mt} {
+           incr fails
+         }
+       }
+       if {$fails > 0} {
+         fail "MI and console have same threads ($name)"
+
+         # Send a list of failures to the log
+         send_log "Console has thread ids: $console_thread_list\n"
+         send_log "MI has thread ids: $mi_thread_list\n"
+       } else {
+         pass "MI and console have same threads ($name)"
+       }
+      }
+    }
+  }
+}
+
+# This procedure tests the various thread commands in MI.
+proc check_mi_thread_command_set {} {
+
+  mi_runto done_making_threads
+
+  set thread_list [get_mi_thread_list "in check_mi_thread_command_set"]
+  
+  mi_gdb_test "-thread-select" \
+    {\^error,msg="mi_cmd_thread_select: USAGE: threadnum."} \
+    "check_mi_thread_command_set: -thread-select"
+
+  mi_gdb_test "-thread-select 123456789" \
+    {\^error,msg="Thread ID 123456789 not known\."} \
+    "check_mi_thread_command_set: -thread-select 123456789"
+
+  foreach thread $thread_list {
+    mi_gdb_test "-thread-select $thread" \
+      "\\^done,new-thread-id=\"$thread\",frame={.*},line=\"(-)?\[0-9\]+\",file=\".*\"" \
+      "check_mi_thread_command_set: -thread-select $thread"
+  }
+}
+
+#
+# Start here
+#
+set testfile "pthreads"
+set srcfile "$testfile.c"
+set binfile "$objdir/$subdir/$testfile"
+
+set options [list debug incdir=$subdir]
+if  {[gdb_compile_pthreads "$srcdir/$subdir/$srcfile" $binfile executable $options]
+     != "" } {
+  gdb_suppress_entire_file \
+    "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load $binfile
+
+check_mi_thread_command_set
+
+mi_gdb_exit
+