Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [RFA/commit] Port GDB to powerpc-lynx178.
@ 2012-12-17 17:18 Joel Brobecker
  2012-12-17 18:41 ` Tom Tromey
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Joel Brobecker @ 2012-12-17 17:18 UTC (permalink / raw)
  To: gdb-patches; +Cc: Joel Brobecker

Hello,

This patch adds support for ppc-lynx178.  Still missing is NEWS
entry, which I will provide tomorrow (too tired tonight).

gdb/ChangeLog:

        * defs.h (enum gdb_osabi): Add GDB_OSABI_LYNXOS178.
        * osabi.c (gdb_osabi_names): Add entry for GDB_OSABI_LYNXOS178.
        * xcoffread.c (xcoff_get_core_n_import_files): New function.
        (xcoff_get_n_import_files): New function.
        * xcoffread.h (xcoffread.h): Add declaration.
        * rs6000-aix-tdep.c: #include "xcoffread.h".
        (rs6000_aix_osabi_sniffer): Do not return GDB_OSABI_AIX for
        XCOFF executables that do not depend on any shared library.
        * rs6000-lynx178-tdep.c: New file.
        * configure.tgt: Add powerpc-*-lynx*178 handling.
        * Makefile.in (ALL_TARGET_OBS): Add rs6000-lynx178-tdep.o.
        (ALLDEPFILES): Add rs6000-lynx178-tdep.c.

Tested on ppc-lynx178.  Any comments before I commit?

Thanks,
-- 
Joel

---
 gdb/Makefile.in           |    2 +
 gdb/configure.tgt         |    6 +
 gdb/defs.h                |    1 +
 gdb/osabi.c               |    1 +
 gdb/rs6000-aix-tdep.c     |    8 +
 gdb/rs6000-lynx178-tdep.c |  420 +++++++++++++++++++++++++++++++++++++++++++++
 gdb/xcoffread.c           |   61 +++++++
 gdb/xcoffread.h           |    2 +
 8 files changed, 501 insertions(+), 0 deletions(-)
 create mode 100644 gdb/rs6000-lynx178-tdep.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 244694c..194568b 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -565,6 +565,7 @@ ALL_TARGET_OBS = \
 	ppc-linux-tdep.o ppcnbsd-tdep.o ppcobsd-tdep.o ppc-sysv-tdep.o \
 	rl78-tdep.o \
 	rs6000-aix-tdep.o rs6000-tdep.o ppc-ravenscar-thread.o \
+	rs6000-lynx178-tdep.o \
 	rx-tdep.o \
 	s390-tdep.o \
 	score-tdep.o \
@@ -1488,6 +1489,7 @@ ALLDEPFILES = \
 	dcache.c \
 	rl78-tdep.c \
 	rs6000-nat.c rs6000-tdep.c ppc-ravenscar-thread.c \
+	rs6000-lynx178-tdep.c \
 	rx-tdep.c \
 	s390-tdep.c s390-nat.c \
 	score-tdep.c \
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 6aa2dfd..5b77bb2 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -411,6 +411,12 @@ powerpc-*-linux* | powerpc64-*-linux*)
 	gdb_sim=../sim/ppc/libsim.a
 	build_gdbserver=yes
 	;;
+powerpc-*-lynx*178)
+	# Target: PowerPC running Lynx178.
+	gdb_target_obs="rs6000-tdep.o rs6000-lynx178-tdep.o \
+			xcoffread.o monitor.o dsrec.o ppc-sysv-tdep.o \
+			ravenscar-thread.o ppc-ravenscar-thread.o"
+	;;
 powerpc*-*-*)
 	# Target: PowerPC running eabi
 	gdb_target_obs="rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o \
diff --git a/gdb/defs.h b/gdb/defs.h
index ee49a89..2e0bff3 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -597,6 +597,7 @@ enum gdb_osabi
   GDB_OSABI_DARWIN,
   GDB_OSABI_SYMBIAN,
   GDB_OSABI_OPENVMS,
+  GDB_OSABI_LYNXOS178,
 
   GDB_OSABI_INVALID		/* keep this last */
 };
diff --git a/gdb/osabi.c b/gdb/osabi.c
index 7f60984..42cb8a0 100644
--- a/gdb/osabi.c
+++ b/gdb/osabi.c
@@ -73,6 +73,7 @@ static const char * const gdb_osabi_names[] =
   "Darwin",
   "Symbian",
   "OpenVMS",
+  "LynxOS178",
 
   "<invalid>"
 };
diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
index b4fc931..8b1c416 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -35,6 +35,7 @@
 #include "rs6000-tdep.h"
 #include "ppc-tdep.h"
 #include "exceptions.h"
+#include "xcoffread.h"
 
 /* Hook for determining the TOC address when calling functions in the
    inferior under AIX.  The initialization code in rs6000-nat.c sets
@@ -739,6 +740,13 @@ rs6000_aix_osabi_sniffer (bfd *abfd)
 {
   gdb_assert (bfd_get_flavour (abfd) == bfd_target_xcoff_flavour);
 
+  /* The only noticeable difference between Lynx178 XCOFF files and
+     AIX XCOFF files comes from the fact that there are no shared
+     libraries on Lynx178.  On AIX, we are betting that an executable
+     linked with no shared library will never exist.  */
+  if (xcoff_get_n_import_files (abfd) <= 0)
+    return GDB_OSABI_UNKNOWN;
+
   return GDB_OSABI_AIX;
 }
 
diff --git a/gdb/rs6000-lynx178-tdep.c b/gdb/rs6000-lynx178-tdep.c
new file mode 100644
index 0000000..21d6d84
--- /dev/null
+++ b/gdb/rs6000-lynx178-tdep.c
@@ -0,0 +1,420 @@
+/* Copyright (C) 2006-2012 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "osabi.h"
+#include "regcache.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "infcall.h"
+#include "ppc-tdep.h"
+#include "value.h"
+#include "xcoffread.h"
+
+/* Implement the "push_dummy_call" gdbarch method.  */
+
+static CORE_ADDR
+rs6000_lynx178_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+			struct regcache *regcache, CORE_ADDR bp_addr,
+			int nargs, struct value **args, CORE_ADDR sp,
+			int struct_return, CORE_ADDR struct_addr)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int ii;
+  int len = 0;
+  int argno;			/* current argument number */
+  int argbytes;			/* current argument byte */
+  gdb_byte tmp_buffer[50];
+  int f_argno = 0;		/* current floating point argno */
+  int wordsize = gdbarch_tdep (gdbarch)->wordsize;
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
+
+  struct value *arg = 0;
+  struct type *type;
+
+  ULONGEST saved_sp;
+
+  /* The calling convention this function implements assumes the
+     processor has floating-point registers.  We shouldn't be using it
+     on PPC variants that lack them.  */
+  gdb_assert (ppc_floating_point_unit_p (gdbarch));
+
+  /* The first eight words of ther arguments are passed in registers.
+     Copy them appropriately.  */
+  ii = 0;
+
+  /* If the function is returning a `struct', then the first word
+     (which will be passed in r3) is used for struct return address.
+     In that case we should advance one word and start from r4
+     register to copy parameters.  */
+  if (struct_return)
+    {
+      regcache_raw_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+				   struct_addr);
+      ii++;
+    }
+
+  /* Effectively indirect call... gcc does...
+
+     return_val example( float, int);
+
+     eabi:
+     float in fp0, int in r3
+     offset of stack on overflow 8/16
+     for varargs, must go by type.
+     power open:
+     float in r3&r4, int in r5
+     offset of stack on overflow different
+     both:
+     return in r3 or f0.  If no float, must study how gcc emulates floats;
+     pay attention to arg promotion.
+     User may have to cast\args to handle promotion correctly
+     since gdb won't know if prototype supplied or not.  */
+
+  for (argno = 0, argbytes = 0; argno < nargs && ii < 8; ++ii)
+    {
+      int reg_size = register_size (gdbarch, ii + 3);
+
+      arg = args[argno];
+      type = check_typedef (value_type (arg));
+      len = TYPE_LENGTH (type);
+
+      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+	{
+
+	  /* Floating point arguments are passed in fpr's, as well as gpr's.
+	     There are 13 fpr's reserved for passing parameters.  At this point
+	     there is no way we would run out of them.  */
+
+	  gdb_assert (len <= 8);
+
+	  regcache_cooked_write (regcache,
+	                         tdep->ppc_fp0_regnum + 1 + f_argno,
+	                         value_contents (arg));
+	  ++f_argno;
+	}
+
+      if (len > reg_size)
+	{
+
+	  /* Argument takes more than one register.  */
+	  while (argbytes < len)
+	    {
+	      gdb_byte word[MAX_REGISTER_SIZE];
+	      memset (word, 0, reg_size);
+	      memcpy (word,
+		      ((char *) value_contents (arg)) + argbytes,
+		      (len - argbytes) > reg_size
+		        ? reg_size : len - argbytes);
+	      regcache_cooked_write (regcache,
+	                            tdep->ppc_gp0_regnum + 3 + ii,
+				    word);
+	      ++ii, argbytes += reg_size;
+
+	      if (ii >= 8)
+		goto ran_out_of_registers_for_arguments;
+	    }
+	  argbytes = 0;
+	  --ii;
+	}
+      else
+	{
+	  /* Argument can fit in one register.  No problem.  */
+	  int adj = gdbarch_byte_order (gdbarch)
+		    == BFD_ENDIAN_BIG ? reg_size - len : 0;
+	  gdb_byte word[MAX_REGISTER_SIZE];
+
+	  memset (word, 0, reg_size);
+	  memcpy (word, value_contents (arg), len);
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3 +ii, word);
+	}
+      ++argno;
+    }
+
+ran_out_of_registers_for_arguments:
+
+  regcache_cooked_read_unsigned (regcache,
+				 gdbarch_sp_regnum (gdbarch),
+				 &saved_sp);
+
+  /* Location for 8 parameters are always reserved.  */
+  sp -= wordsize * 8;
+
+  /* Another six words for back chain, TOC register, link register, etc.  */
+  sp -= wordsize * 6;
+
+  /* Stack pointer must be quadword aligned.  */
+  sp &= -16;
+
+  /* If there are more arguments, allocate space for them in
+     the stack, then push them starting from the ninth one.  */
+
+  if ((argno < nargs) || argbytes)
+    {
+      int space = 0, jj;
+
+      if (argbytes)
+	{
+	  space += ((len - argbytes + 3) & -4);
+	  jj = argno + 1;
+	}
+      else
+	jj = argno;
+
+      for (; jj < nargs; ++jj)
+	{
+	  struct value *val = args[jj];
+	  space += ((TYPE_LENGTH (value_type (val))) + 3) & -4;
+	}
+
+      /* Add location required for the rest of the parameters.  */
+      space = (space + 15) & -16;
+      sp -= space;
+
+      /* This is another instance we need to be concerned about
+         securing our stack space.  If we write anything underneath %sp
+         (r1), we might conflict with the kernel who thinks he is free
+         to use this area.  So, update %sp first before doing anything
+         else.  */
+
+      regcache_raw_write_signed (regcache,
+				 gdbarch_sp_regnum (gdbarch), sp);
+
+      /* If the last argument copied into the registers didn't fit there
+         completely, push the rest of it into stack.  */
+
+      if (argbytes)
+	{
+	  write_memory (sp + 24 + (ii * 4),
+			value_contents (arg) + argbytes,
+			len - argbytes);
+	  ++argno;
+	  ii += ((len - argbytes + 3) & -4) / 4;
+	}
+
+      /* Push the rest of the arguments into stack.  */
+      for (; argno < nargs; ++argno)
+	{
+
+	  arg = args[argno];
+	  type = check_typedef (value_type (arg));
+	  len = TYPE_LENGTH (type);
+
+
+	  /* Float types should be passed in fpr's, as well as in the
+             stack.  */
+	  if (TYPE_CODE (type) == TYPE_CODE_FLT && f_argno < 13)
+	    {
+
+	      gdb_assert (len <= 8);
+
+	      regcache_cooked_write (regcache,
+				     tdep->ppc_fp0_regnum + 1 + f_argno,
+				     value_contents (arg));
+	      ++f_argno;
+	    }
+
+	  write_memory (sp + 24 + (ii * 4), value_contents (arg), len);
+	  ii += ((len + 3) & -4) / 4;
+	}
+    }
+
+  /* Set the stack pointer.  According to the ABI, the SP is meant to
+     be set _before_ the corresponding stack space is used.  On AIX,
+     this even applies when the target has been completely stopped!
+     Not doing this can lead to conflicts with the kernel which thinks
+     that it still has control over this not-yet-allocated stack
+     region.  */
+  regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
+
+  /* Set back chain properly.  */
+  store_unsigned_integer (tmp_buffer, wordsize, byte_order, saved_sp);
+  write_memory (sp, tmp_buffer, wordsize);
+
+  /* Point the inferior function call's return address at the dummy's
+     breakpoint.  */
+  regcache_raw_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
+
+  target_store_registers (regcache, -1);
+  return sp;
+}
+
+/* Implement the "return_value" gdbarch method.  */
+
+static enum return_value_convention
+rs6000_lynx178_return_value (struct gdbarch *gdbarch, struct value *function,
+			     struct type *valtype, struct regcache *regcache,
+			     gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+  /* The calling convention this function implements assumes the
+     processor has floating-point registers.  We shouldn't be using it
+     on PowerPC variants that lack them.  */
+  gdb_assert (ppc_floating_point_unit_p (gdbarch));
+
+  /* AltiVec extension: Functions that declare a vector data type as a
+     return value place that return value in VR2.  */
+  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
+      && TYPE_LENGTH (valtype) == 16)
+    {
+      if (readbuf)
+	regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
+      if (writebuf)
+	regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf);
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+
+  /* If the called subprogram returns an aggregate, there exists an
+     implicit first argument, whose value is the address of a caller-
+     allocated buffer into which the callee is assumed to store its
+     return value.  All explicit parameters are appropriately
+     relabeled.  */
+  if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
+      || TYPE_CODE (valtype) == TYPE_CODE_UNION
+      || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
+    return RETURN_VALUE_STRUCT_CONVENTION;
+
+  /* Scalar floating-point values are returned in FPR1 for float or
+     double, and in FPR1:FPR2 for quadword precision.  Fortran
+     complex*8 and complex*16 are returned in FPR1:FPR2, and
+     complex*32 is returned in FPR1:FPR4.  */
+  if (TYPE_CODE (valtype) == TYPE_CODE_FLT
+      && (TYPE_LENGTH (valtype) == 4 || TYPE_LENGTH (valtype) == 8))
+    {
+      struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
+      gdb_byte regval[8];
+
+      /* FIXME: kettenis/2007-01-01: Add support for quadword
+	 precision and complex.  */
+
+      if (readbuf)
+	{
+	  regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
+	  convert_typed_floating (regval, regtype, readbuf, valtype);
+	}
+      if (writebuf)
+	{
+	  convert_typed_floating (writebuf, valtype, regval, regtype);
+	  regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
+	}
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+  }
+
+  /* Values of the types int, long, short, pointer, and char (length
+     is less than or equal to four bytes), as well as bit values of
+     lengths less than or equal to 32 bits, must be returned right
+     justified in GPR3 with signed values sign extended and unsigned
+     values zero extended, as necessary.  */
+  if (TYPE_LENGTH (valtype) <= tdep->wordsize)
+    {
+      if (readbuf)
+	{
+	  ULONGEST regval;
+
+	  /* For reading we don't have to worry about sign extension.  */
+	  regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+					 &regval);
+	  store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), byte_order,
+				  regval);
+	}
+      if (writebuf)
+	{
+	  /* For writing, use unpack_long since that should handle any
+	     required sign extension.  */
+	  regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+					  unpack_long (valtype, writebuf));
+	}
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+
+  /* Eight-byte non-floating-point scalar values must be returned in
+     GPR3:GPR4.  */
+
+  if (TYPE_LENGTH (valtype) == 8)
+    {
+      gdb_assert (TYPE_CODE (valtype) != TYPE_CODE_FLT);
+      gdb_assert (tdep->wordsize == 4);
+
+      if (readbuf)
+	{
+	  gdb_byte regval[8];
+
+	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, regval);
+	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+				regval + 4);
+	  memcpy (readbuf, regval, 8);
+	}
+      if (writebuf)
+	{
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+				 writebuf + 4);
+	}
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+
+  return RETURN_VALUE_STRUCT_CONVENTION;
+}
+
+/* PowerPC Lynx178 OSABI sniffer.  */
+
+static enum gdb_osabi
+rs6000_lynx178_osabi_sniffer (bfd *abfd)
+{
+  if (bfd_get_flavour (abfd) != bfd_target_xcoff_flavour)
+    return GDB_OSABI_UNKNOWN;
+
+  /* The only noticeable difference between Lynx178 XCOFF files and
+     AIX XCOFF files comes from the fact that there are no shared
+     libraries on Lynx178.  So if the number of import files is
+     different from zero, it cannot be a Lynx178 binary.  */
+  if (xcoff_get_n_import_files (abfd) != 0)
+    return GDB_OSABI_UNKNOWN;
+
+  return GDB_OSABI_LYNXOS178;
+}
+
+/* Callback for powerpc-lynx178 initialization.  */
+
+static void
+rs6000_lynx178_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  set_gdbarch_push_dummy_call (gdbarch, rs6000_lynx178_push_dummy_call);
+  set_gdbarch_return_value (gdbarch, rs6000_lynx178_return_value);
+  set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+}
+
+/* -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_rs6000_lynx178_tdep;
+
+void
+_initialize_rs6000_lynx178_tdep (void)
+{
+  gdbarch_register_osabi_sniffer (bfd_arch_rs6000,
+                                  bfd_target_xcoff_flavour,
+                                  rs6000_lynx178_osabi_sniffer);
+  gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_LYNXOS178,
+                          rs6000_lynx178_init_osabi);
+}
+
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 10c93cc..7838ac1 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -3113,6 +3113,67 @@ static const struct sym_fns xcoff_sym_fns =
   &psym_functions
 };
 
+/* Same as xcoff_get_n_import_files, but for core files.  */
+
+static int
+xcoff_get_core_n_import_files (bfd *abfd)
+{
+  asection *sect = bfd_get_section_by_name (abfd, ".ldinfo");
+  gdb_byte buf[4];
+  file_ptr offset = 0;
+  int n_entries = 0;
+
+  if (sect == NULL)
+    return -1;  /* Not a core file.  */
+
+  for (offset = 0; offset < bfd_get_section_size (sect);)
+    {
+      int next;
+
+      n_entries++;
+
+      if (!bfd_get_section_contents (abfd, sect, buf, offset, 4))
+	return -1;
+      next = bfd_get_32 (abfd, buf);
+      if (next == 0)
+	break;  /* This is the last entry.  */
+      offset += next;
+    }
+
+  /* Return the number of entries, excluding the first one, which is
+     the path to the executable that produced this core file.  */
+  return n_entries - 1;
+}
+
+/* Return the number of import files (shared libraries) that the given
+   BFD depends on.  Return -1 if this number could not be computed.  */
+
+extern int
+xcoff_get_n_import_files (bfd *abfd)
+{
+  asection *sect = bfd_get_section_by_name (abfd, ".loader");
+  gdb_byte buf[4];
+  int l_nimpid;
+
+  /* If the ".loader" section does not exist, the objfile is probably
+     not an executable.  Might be a core file...  */
+  if (sect == NULL)
+    return xcoff_get_core_n_import_files (abfd);
+
+  /* The number of entries in the Import Files Table is stored in
+     field l_nimpid.  This field is always at offset 16, and is
+     always 4 bytes long.  Read those 4 bytes.  */
+
+  if (!bfd_get_section_contents (abfd, sect, buf, 16, 4))
+    return -1;
+  l_nimpid = bfd_get_32 (abfd, buf);
+
+  /* By convention, the first entry is the default LIBPATH value
+     to be used by the system loader, so it does not count towards
+     the number of import files.  */
+  return l_nimpid - 1;
+}
+
 /* Free the per-objfile xcoff data.  */
 
 static void
diff --git a/gdb/xcoffread.h b/gdb/xcoffread.h
index 3df08ee..86e1d07 100644
--- a/gdb/xcoffread.h
+++ b/gdb/xcoffread.h
@@ -21,4 +21,6 @@
 
 extern CORE_ADDR xcoff_get_toc_offset (struct objfile *);
 
+extern int xcoff_get_n_import_files (bfd *abfd);
+
 #endif /* xcoffread.h */
-- 
1.7.0.4


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFA/commit] Port GDB to powerpc-lynx178.
  2012-12-17 17:18 [RFA/commit] Port GDB to powerpc-lynx178 Joel Brobecker
@ 2012-12-17 18:41 ` Tom Tromey
  2012-12-18  4:56 ` Yao Qi
  2012-12-18 15:00 ` Joel Brobecker
  2 siblings, 0 replies; 6+ messages in thread
From: Tom Tromey @ 2012-12-17 18:41 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:

Joel> Tested on ppc-lynx178.  Any comments before I commit?

Just a nit...

Joel> +/* Return the number of import files (shared libraries) that the given
Joel> +   BFD depends on.  Return -1 if this number could not be computed.  */
Joel> +
Joel> +extern int
Joel> +xcoff_get_n_import_files (bfd *abfd)
Joel> +{

It's unusual to put 'extern' on the definition.

Tom


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFA/commit] Port GDB to powerpc-lynx178.
  2012-12-17 17:18 [RFA/commit] Port GDB to powerpc-lynx178 Joel Brobecker
  2012-12-17 18:41 ` Tom Tromey
@ 2012-12-18  4:56 ` Yao Qi
  2012-12-18  6:17   ` Joel Brobecker
  2012-12-18 15:00 ` Joel Brobecker
  2 siblings, 1 reply; 6+ messages in thread
From: Yao Qi @ 2012-12-18  4:56 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

On 12/18/2012 01:18 AM, Joel Brobecker wrote:
> diff --git a/gdb/rs6000-lynx178-tdep.c b/gdb/rs6000-lynx178-tdep.c
> new file mode 100644
> index 0000000..21d6d84
> --- /dev/null
> +++ b/gdb/rs6000-lynx178-tdep.c
> @@ -0,0 +1,420 @@
> +/* Copyright (C) 2006-2012 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 3 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, see<http://www.gnu.org/licenses/>.  */
> +
> +#include "defs.h"
> +#include "osabi.h"
> +#include "regcache.h"
> +#include "gdbcore.h"
> +#include "gdbtypes.h"
> +#include "infcall.h"
> +#include "ppc-tdep.h"
> +#include "value.h"
> +#include "xcoffread.h"
> +
> +/* Implement the "push_dummy_call" gdbarch method.  */
> +
> +static CORE_ADDR
> +rs6000_lynx178_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
> +			struct regcache *regcache, CORE_ADDR bp_addr,
> +			int nargs, struct value **args, CORE_ADDR sp,
> +			int struct_return, CORE_ADDR struct_addr)
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +  int ii;
> +  int len = 0;
> +  int argno;			/* current argument number */
> +  int argbytes;			/* current argument byte */
> +  gdb_byte tmp_buffer[50];
> +  int f_argno = 0;		/* current floating point argno */
> +  int wordsize = gdbarch_tdep (gdbarch)->wordsize;
> +  CORE_ADDR func_addr = find_function_addr (function, NULL);
> +
> +  struct value *arg = 0;
> +  struct type *type;
> +
> +  ULONGEST saved_sp;
> +
> +  /* The calling convention this function implements assumes the
> +     processor has floating-point registers.  We shouldn't be using it
> +     on PPC variants that lack them.  */
> +  gdb_assert (ppc_floating_point_unit_p (gdbarch));
> +
> +  /* The first eight words of ther arguments are passed in registers.
> +     Copy them appropriately.  */
> +  ii = 0;
> +
> +  /* If the function is returning a `struct', then the first word
> +     (which will be passed in r3) is used for struct return address.
> +     In that case we should advance one word and start from r4
> +     register to copy parameters.  */
> +  if (struct_return)
> +    {
> +      regcache_raw_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
> +				   struct_addr);
> +      ii++;
> +    }
> +
> +  /* Effectively indirect call... gcc does...
> +
> +     return_val example( float, int);
> +
> +     eabi:
> +     float in fp0, int in r3
> +     offset of stack on overflow 8/16
> +     for varargs, must go by type.
> +     power open:
> +     float in r3&r4, int in r5
> +     offset of stack on overflow different
> +     both:
> +     return in r3 or f0.  If no float, must study how gcc emulates floats;
> +     pay attention to arg promotion.
> +     User may have to cast\args to handle promotion correctly
> +     since gdb won't know if prototype supplied or not.  */
> +
> +  for (argno = 0, argbytes = 0; argno < nargs && ii < 8; ++ii)
> +    {
> +      int reg_size = register_size (gdbarch, ii + 3);
> +
> +      arg = args[argno];
> +      type = check_typedef (value_type (arg));
> +      len = TYPE_LENGTH (type);
> +
> +      if (TYPE_CODE (type) == TYPE_CODE_FLT)
> +	{
> +
> +	  /* Floating point arguments are passed in fpr's, as well as gpr's.
> +	     There are 13 fpr's reserved for passing parameters.  At this point
> +	     there is no way we would run out of them.  */
> +
> +	  gdb_assert (len <= 8);
> +
> +	  regcache_cooked_write (regcache,
> +	                         tdep->ppc_fp0_regnum + 1 + f_argno,
> +	                         value_contents (arg));
> +	  ++f_argno;
> +	}
> +
> +      if (len > reg_size)
> +	{
> +
> +	  /* Argument takes more than one register.  */
> +	  while (argbytes < len)
> +	    {
> +	      gdb_byte word[MAX_REGISTER_SIZE];
> +	      memset (word, 0, reg_size);
> +	      memcpy (word,
> +		      ((char *) value_contents (arg)) + argbytes,
> +		      (len - argbytes) > reg_size
> +		        ? reg_size : len - argbytes);
> +	      regcache_cooked_write (regcache,
> +	                            tdep->ppc_gp0_regnum + 3 + ii,
> +				    word);
> +	      ++ii, argbytes += reg_size;
> +
> +	      if (ii >= 8)
> +		goto ran_out_of_registers_for_arguments;
> +	    }
> +	  argbytes = 0;
> +	  --ii;
> +	}
> +      else
> +	{
> +	  /* Argument can fit in one register.  No problem.  */
> +	  int adj = gdbarch_byte_order (gdbarch)
> +		    == BFD_ENDIAN_BIG ? reg_size - len : 0;
> +	  gdb_byte word[MAX_REGISTER_SIZE];
> +
> +	  memset (word, 0, reg_size);
> +	  memcpy (word, value_contents (arg), len);
> +	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3 +ii, word);
> +	}
> +      ++argno;
> +    }
> +
> +ran_out_of_registers_for_arguments:
> +
> +  regcache_cooked_read_unsigned (regcache,
> +				 gdbarch_sp_regnum (gdbarch),
> +				 &saved_sp);
> +
> +  /* Location for 8 parameters are always reserved.  */
> +  sp -= wordsize * 8;
> +
> +  /* Another six words for back chain, TOC register, link register, etc.  */
> +  sp -= wordsize * 6;
> +
> +  /* Stack pointer must be quadword aligned.  */
> +  sp &= -16;

How about 'sp = align_down (sp, 16);'?

> +
> +  /* If there are more arguments, allocate space for them in
> +     the stack, then push them starting from the ninth one.  */
> +
> +  if ((argno < nargs) || argbytes)
> +    {
> +      int space = 0, jj;
> +
> +      if (argbytes)
> +	{
> +	  space += ((len - argbytes + 3) & -4);
> +	  jj = argno + 1;
> +	}
> +      else
> +	jj = argno;
> +
> +      for (; jj < nargs; ++jj)
> +	{
> +	  struct value *val = args[jj];
> +	  space += ((TYPE_LENGTH (value_type (val))) + 3) & -4;
> +	}
> +
> +      /* Add location required for the rest of the parameters.  */
> +      space = (space + 15) & -16;

How about 'space = align_up (space, 16);'? and we may use
'align_up (XXX, 4)' somewhere else in this patch.

> +
> +/* PowerPC Lynx178 OSABI sniffer.  */
> +
> +static enum gdb_osabi
> +rs6000_lynx178_osabi_sniffer (bfd *abfd)
> +{
> +  if (bfd_get_flavour (abfd) != bfd_target_xcoff_flavour)
> +    return GDB_OSABI_UNKNOWN;
> +
> +  /* The only noticeable difference between Lynx178 XCOFF files and
> +     AIX XCOFF files comes from the fact that there are no shared
> +     libraries on Lynx178.  So if the number of import files is
> +     different from zero, it cannot be a Lynx178 binary.  */
> +  if (xcoff_get_n_import_files (abfd) != 0)
> +    return GDB_OSABI_UNKNOWN;

As your comments said, we need the function returning a flag indicating 
'the xcoff file has shared libraries or not', and looks the precise 
number of import files doesn't matter here.  I suggest that rename 
function 'xcoff_get_n_import_files' to 'xcoff_has_import_files'.

> +
> diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
> index 10c93cc..7838ac1 100644
> --- a/gdb/xcoffread.c
> +++ b/gdb/xcoffread.c
> @@ -3113,6 +3113,67 @@ static const struct sym_fns xcoff_sym_fns =
>     &psym_functions
>   };
>

> +
> +/* Return the number of import files (shared libraries) that the given
> +   BFD depends on.  Return -1 if this number could not be computed.  */
> +
> +extern int
> +xcoff_get_n_import_files (bfd *abfd)

As I said above, we can define this function:

int xcoff_has_import_files (bfd *abfd)

which returns 1 when the BFD has the import files and returns 0 when the 
BFD doesn't.  Returns -1 when it is unknown.

-- 
Yao (齐尧)


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFA/commit] Port GDB to powerpc-lynx178.
  2012-12-18  4:56 ` Yao Qi
@ 2012-12-18  6:17   ` Joel Brobecker
  2012-12-18  8:29     ` Yao Qi
  0 siblings, 1 reply; 6+ messages in thread
From: Joel Brobecker @ 2012-12-18  6:17 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Yao,

Thanks for your comments.

Just one request: Would you mind cutting out the quoted test that
you are not replying to? It makes no sense to see emails where
you have to scroll pages and pages before seeing a one-line comment.

> >+  /* Stack pointer must be quadword aligned.  */
> >+  sp &= -16;
> 
> How about 'sp = align_down (sp, 16);'?
[...]
> >+      /* Add location required for the rest of the parameters.  */
> >+      space = (space + 15) & -16;
> 
> How about 'space = align_up (space, 16);'? and we may use
> 'align_up (XXX, 4)' somewhere else in this patch.

Why not indeed.

> >+  /* The only noticeable difference between Lynx178 XCOFF files and
> >+     AIX XCOFF files comes from the fact that there are no shared
> >+     libraries on Lynx178.  So if the number of import files is
> >+     different from zero, it cannot be a Lynx178 binary.  */
> >+  if (xcoff_get_n_import_files (abfd) != 0)
> >+    return GDB_OSABI_UNKNOWN;
> 
> As your comments said, we need the function returning a flag
> indicating 'the xcoff file has shared libraries or not', and looks
> the precise number of import files doesn't matter here.  I suggest
> that rename function 'xcoff_get_n_import_files' to
> 'xcoff_has_import_files'.

While your suggestion may be good enough for today, there might
come a day where someone will want the actual number of imports.
Since it does not cost anything to provide that information,
it would seem silly to spend any effort downgrading the function,
and take the risk of having to undo those changes someday.

Thanks,
-- 
Joel


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFA/commit] Port GDB to powerpc-lynx178.
  2012-12-18  6:17   ` Joel Brobecker
@ 2012-12-18  8:29     ` Yao Qi
  0 siblings, 0 replies; 6+ messages in thread
From: Yao Qi @ 2012-12-18  8:29 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

On 12/18/2012 02:17 PM, Joel Brobecker wrote:
> Just one request: Would you mind cutting out the quoted test that
> you are not replying to? It makes no sense to see emails where
> you have to scroll pages and pages before seeing a one-line comment.
>

OK, no problem.  I am used to giving comments with the context on 
function level, to make it clear where my comments apply.  I'll shorten 
the context if it is too long next time.

>>> > >+     AIX XCOFF files comes from the fact that there are no shared
>>> > >+     libraries on Lynx178.  So if the number of import files is
>>> > >+     different from zero, it cannot be a Lynx178 binary.  */
>>> > >+  if (xcoff_get_n_import_files (abfd) != 0)
>>> > >+    return GDB_OSABI_UNKNOWN;
>> >
>> >As your comments said, we need the function returning a flag
>> >indicating 'the xcoff file has shared libraries or not', and looks
>> >the precise number of import files doesn't matter here.  I suggest
>> >that rename function 'xcoff_get_n_import_files' to
>> >'xcoff_has_import_files'.
> While your suggestion may be good enough for today, there might
> come a day where someone will want the actual number of imports.
> Since it does not cost anything to provide that information,
> it would seem silly to spend any effort downgrading the function,
> and take the risk of having to undo those changes someday.

That is fine to me.

-- 
Yao (齐尧)


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [RFA/commit] Port GDB to powerpc-lynx178.
  2012-12-17 17:18 [RFA/commit] Port GDB to powerpc-lynx178 Joel Brobecker
  2012-12-17 18:41 ` Tom Tromey
  2012-12-18  4:56 ` Yao Qi
@ 2012-12-18 15:00 ` Joel Brobecker
  2 siblings, 0 replies; 6+ messages in thread
From: Joel Brobecker @ 2012-12-18 15:00 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 987 bytes --]

> This patch adds support for ppc-lynx178.  Still missing is NEWS
> entry, which I will provide tomorrow (too tired tonight).

Attached is the patch I checked in, after having applied Tom's
and Yao's comments.

gdb/ChangeLog:

        * defs.h (enum gdb_osabi): Add GDB_OSABI_LYNXOS178.
        * osabi.c (gdb_osabi_names): Add entry for GDB_OSABI_LYNXOS178.
        * xcoffread.c (xcoff_get_core_n_import_files): New function.
        (xcoff_get_n_import_files): New function.
        * xcoffread.h (xcoffread.h): Add declaration.
        * rs6000-aix-tdep.c: #include "xcoffread.h".
        (rs6000_aix_osabi_sniffer): Do not return GDB_OSABI_AIX for
        XCOFF executables that do not depend on any shared library.
        * rs6000-lynx178-tdep.c: New file.
        * configure.tgt: Add powerpc-*-lynx*178 handling.
        * Makefile.in (ALL_TARGET_OBS): Add rs6000-lynx178-tdep.o.
        (ALLDEPFILES): Add rs6000-lynx178-tdep.c.

Tested on ppc-lynx178 again.

Cheers,
-- 
Joel

[-- Attachment #2: 0001-Port-GDB-to-powerpc-lynx178.patch --]
[-- Type: text/x-diff, Size: 21058 bytes --]

From 4672edbe9f565e37d0bdd37813d1dd41c694528c Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Mon, 17 Dec 2012 10:28:40 -0500
Subject: [PATCH] Port GDB to powerpc-lynx178.

gdb/ChangeLog:

        * defs.h (enum gdb_osabi): Add GDB_OSABI_LYNXOS178.
        * osabi.c (gdb_osabi_names): Add entry for GDB_OSABI_LYNXOS178.
        * xcoffread.c (xcoff_get_core_n_import_files): New function.
        (xcoff_get_n_import_files): New function.
        * xcoffread.h (xcoffread.h): Add declaration.
        * rs6000-aix-tdep.c: #include "xcoffread.h".
        (rs6000_aix_osabi_sniffer): Do not return GDB_OSABI_AIX for
        XCOFF executables that do not depend on any shared library.
        * rs6000-lynx178-tdep.c: New file.
        * configure.tgt: Add powerpc-*-lynx*178 handling.
        * Makefile.in (ALL_TARGET_OBS): Add rs6000-lynx178-tdep.o.
        (ALLDEPFILES): Add rs6000-lynx178-tdep.c.
---
 gdb/ChangeLog             |   15 ++
 gdb/Makefile.in           |    2 +
 gdb/configure.tgt         |    6 +
 gdb/defs.h                |    1 +
 gdb/osabi.c               |    1 +
 gdb/rs6000-aix-tdep.c     |    8 +
 gdb/rs6000-lynx178-tdep.c |  422 +++++++++++++++++++++++++++++++++++++++++++++
 gdb/xcoffread.c           |   61 +++++++
 gdb/xcoffread.h           |    2 +
 9 files changed, 518 insertions(+), 0 deletions(-)
 create mode 100644 gdb/rs6000-lynx178-tdep.c

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c7549c3..48c10b9 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,18 @@
+2012-12-18  Joel Brobecker  <brobecker@adacore.com>
+
+	* defs.h (enum gdb_osabi): Add GDB_OSABI_LYNXOS178.
+	* osabi.c (gdb_osabi_names): Add entry for GDB_OSABI_LYNXOS178.
+	* xcoffread.c (xcoff_get_core_n_import_files): New function.
+	(xcoff_get_n_import_files): New function.
+	* xcoffread.h (xcoffread.h): Add declaration.
+	* rs6000-aix-tdep.c: #include "xcoffread.h".
+	(rs6000_aix_osabi_sniffer): Do not return GDB_OSABI_AIX for
+	XCOFF executables that do not depend on any shared library.
+	* rs6000-lynx178-tdep.c: New file.
+	* configure.tgt: Add powerpc-*-lynx*178 handling.
+	* Makefile.in (ALL_TARGET_OBS): Add rs6000-lynx178-tdep.o.
+	(ALLDEPFILES): Add rs6000-lynx178-tdep.c.
+
 2012-12-18  Hui Zhu  <hui_zhu@mentor.com>
 
 	* ui-file.c (ui_file): Add to_fseek.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 244694c..194568b 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -565,6 +565,7 @@ ALL_TARGET_OBS = \
 	ppc-linux-tdep.o ppcnbsd-tdep.o ppcobsd-tdep.o ppc-sysv-tdep.o \
 	rl78-tdep.o \
 	rs6000-aix-tdep.o rs6000-tdep.o ppc-ravenscar-thread.o \
+	rs6000-lynx178-tdep.o \
 	rx-tdep.o \
 	s390-tdep.o \
 	score-tdep.o \
@@ -1488,6 +1489,7 @@ ALLDEPFILES = \
 	dcache.c \
 	rl78-tdep.c \
 	rs6000-nat.c rs6000-tdep.c ppc-ravenscar-thread.c \
+	rs6000-lynx178-tdep.c \
 	rx-tdep.c \
 	s390-tdep.c s390-nat.c \
 	score-tdep.c \
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 6aa2dfd..5b77bb2 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -411,6 +411,12 @@ powerpc-*-linux* | powerpc64-*-linux*)
 	gdb_sim=../sim/ppc/libsim.a
 	build_gdbserver=yes
 	;;
+powerpc-*-lynx*178)
+	# Target: PowerPC running Lynx178.
+	gdb_target_obs="rs6000-tdep.o rs6000-lynx178-tdep.o \
+			xcoffread.o monitor.o dsrec.o ppc-sysv-tdep.o \
+			ravenscar-thread.o ppc-ravenscar-thread.o"
+	;;
 powerpc*-*-*)
 	# Target: PowerPC running eabi
 	gdb_target_obs="rs6000-tdep.o monitor.o dsrec.o ppcbug-rom.o \
diff --git a/gdb/defs.h b/gdb/defs.h
index ee49a89..2e0bff3 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -597,6 +597,7 @@ enum gdb_osabi
   GDB_OSABI_DARWIN,
   GDB_OSABI_SYMBIAN,
   GDB_OSABI_OPENVMS,
+  GDB_OSABI_LYNXOS178,
 
   GDB_OSABI_INVALID		/* keep this last */
 };
diff --git a/gdb/osabi.c b/gdb/osabi.c
index 7f60984..42cb8a0 100644
--- a/gdb/osabi.c
+++ b/gdb/osabi.c
@@ -73,6 +73,7 @@ static const char * const gdb_osabi_names[] =
   "Darwin",
   "Symbian",
   "OpenVMS",
+  "LynxOS178",
 
   "<invalid>"
 };
diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c
index b4fc931..8b1c416 100644
--- a/gdb/rs6000-aix-tdep.c
+++ b/gdb/rs6000-aix-tdep.c
@@ -35,6 +35,7 @@
 #include "rs6000-tdep.h"
 #include "ppc-tdep.h"
 #include "exceptions.h"
+#include "xcoffread.h"
 
 /* Hook for determining the TOC address when calling functions in the
    inferior under AIX.  The initialization code in rs6000-nat.c sets
@@ -739,6 +740,13 @@ rs6000_aix_osabi_sniffer (bfd *abfd)
 {
   gdb_assert (bfd_get_flavour (abfd) == bfd_target_xcoff_flavour);
 
+  /* The only noticeable difference between Lynx178 XCOFF files and
+     AIX XCOFF files comes from the fact that there are no shared
+     libraries on Lynx178.  On AIX, we are betting that an executable
+     linked with no shared library will never exist.  */
+  if (xcoff_get_n_import_files (abfd) <= 0)
+    return GDB_OSABI_UNKNOWN;
+
   return GDB_OSABI_AIX;
 }
 
diff --git a/gdb/rs6000-lynx178-tdep.c b/gdb/rs6000-lynx178-tdep.c
new file mode 100644
index 0000000..92a6bc2
--- /dev/null
+++ b/gdb/rs6000-lynx178-tdep.c
@@ -0,0 +1,422 @@
+/* Copyright (C) 2012 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 3 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, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "osabi.h"
+#include "regcache.h"
+#include "gdbcore.h"
+#include "gdbtypes.h"
+#include "infcall.h"
+#include "ppc-tdep.h"
+#include "value.h"
+#include "xcoffread.h"
+
+/* Implement the "push_dummy_call" gdbarch method.  */
+
+static CORE_ADDR
+rs6000_lynx178_push_dummy_call (struct gdbarch *gdbarch,
+				struct value *function,
+				struct regcache *regcache, CORE_ADDR bp_addr,
+				int nargs, struct value **args, CORE_ADDR sp,
+				int struct_return, CORE_ADDR struct_addr)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int ii;
+  int len = 0;
+  int argno;			/* current argument number */
+  int argbytes;			/* current argument byte */
+  gdb_byte tmp_buffer[50];
+  int f_argno = 0;		/* current floating point argno */
+  int wordsize = gdbarch_tdep (gdbarch)->wordsize;
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
+
+  struct value *arg = 0;
+  struct type *type;
+
+  ULONGEST saved_sp;
+
+  /* The calling convention this function implements assumes the
+     processor has floating-point registers.  We shouldn't be using it
+     on PPC variants that lack them.  */
+  gdb_assert (ppc_floating_point_unit_p (gdbarch));
+
+  /* The first eight words of ther arguments are passed in registers.
+     Copy them appropriately.  */
+  ii = 0;
+
+  /* If the function is returning a `struct', then the first word
+     (which will be passed in r3) is used for struct return address.
+     In that case we should advance one word and start from r4
+     register to copy parameters.  */
+  if (struct_return)
+    {
+      regcache_raw_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+				   struct_addr);
+      ii++;
+    }
+
+  /* Effectively indirect call... gcc does...
+
+     return_val example( float, int);
+
+     eabi:
+     float in fp0, int in r3
+     offset of stack on overflow 8/16
+     for varargs, must go by type.
+     power open:
+     float in r3&r4, int in r5
+     offset of stack on overflow different
+     both:
+     return in r3 or f0.  If no float, must study how gcc emulates floats;
+     pay attention to arg promotion.
+     User may have to cast\args to handle promotion correctly
+     since gdb won't know if prototype supplied or not.  */
+
+  for (argno = 0, argbytes = 0; argno < nargs && ii < 8; ++ii)
+    {
+      int reg_size = register_size (gdbarch, ii + 3);
+
+      arg = args[argno];
+      type = check_typedef (value_type (arg));
+      len = TYPE_LENGTH (type);
+
+      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+	{
+
+	  /* Floating point arguments are passed in fpr's, as well as gpr's.
+	     There are 13 fpr's reserved for passing parameters.  At this point
+	     there is no way we would run out of them.  */
+
+	  gdb_assert (len <= 8);
+
+	  regcache_cooked_write (regcache,
+	                         tdep->ppc_fp0_regnum + 1 + f_argno,
+	                         value_contents (arg));
+	  ++f_argno;
+	}
+
+      if (len > reg_size)
+	{
+
+	  /* Argument takes more than one register.  */
+	  while (argbytes < len)
+	    {
+	      gdb_byte word[MAX_REGISTER_SIZE];
+	      memset (word, 0, reg_size);
+	      memcpy (word,
+		      ((char *) value_contents (arg)) + argbytes,
+		      (len - argbytes) > reg_size
+		        ? reg_size : len - argbytes);
+	      regcache_cooked_write (regcache,
+	                            tdep->ppc_gp0_regnum + 3 + ii,
+				    word);
+	      ++ii, argbytes += reg_size;
+
+	      if (ii >= 8)
+		goto ran_out_of_registers_for_arguments;
+	    }
+	  argbytes = 0;
+	  --ii;
+	}
+      else
+	{
+	  /* Argument can fit in one register.  No problem.  */
+	  int adj = gdbarch_byte_order (gdbarch)
+		    == BFD_ENDIAN_BIG ? reg_size - len : 0;
+	  gdb_byte word[MAX_REGISTER_SIZE];
+
+	  memset (word, 0, reg_size);
+	  memcpy (word, value_contents (arg), len);
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3 +ii, word);
+	}
+      ++argno;
+    }
+
+ran_out_of_registers_for_arguments:
+
+  regcache_cooked_read_unsigned (regcache,
+				 gdbarch_sp_regnum (gdbarch),
+				 &saved_sp);
+
+  /* Location for 8 parameters are always reserved.  */
+  sp -= wordsize * 8;
+
+  /* Another six words for back chain, TOC register, link register, etc.  */
+  sp -= wordsize * 6;
+
+  /* Stack pointer must be quadword aligned.  */
+  sp = align_down (sp, 16);
+
+  /* If there are more arguments, allocate space for them in
+     the stack, then push them starting from the ninth one.  */
+
+  if ((argno < nargs) || argbytes)
+    {
+      int space = 0, jj;
+
+      if (argbytes)
+	{
+	  space += align_up (len - argbytes, 4);
+	  jj = argno + 1;
+	}
+      else
+	jj = argno;
+
+      for (; jj < nargs; ++jj)
+	{
+	  struct value *val = args[jj];
+
+	  space += align_up (TYPE_LENGTH (value_type (val)), 4);
+	}
+
+      /* Add location required for the rest of the parameters.  */
+      space = align_up (space, 16);
+      sp -= space;
+
+      /* This is another instance we need to be concerned about
+         securing our stack space.  If we write anything underneath %sp
+         (r1), we might conflict with the kernel who thinks he is free
+         to use this area.  So, update %sp first before doing anything
+         else.  */
+
+      regcache_raw_write_signed (regcache,
+				 gdbarch_sp_regnum (gdbarch), sp);
+
+      /* If the last argument copied into the registers didn't fit there
+         completely, push the rest of it into stack.  */
+
+      if (argbytes)
+	{
+	  write_memory (sp + 24 + (ii * 4),
+			value_contents (arg) + argbytes,
+			len - argbytes);
+	  ++argno;
+	  ii += align_up (len - argbytes, 4) / 4;
+	}
+
+      /* Push the rest of the arguments into stack.  */
+      for (; argno < nargs; ++argno)
+	{
+
+	  arg = args[argno];
+	  type = check_typedef (value_type (arg));
+	  len = TYPE_LENGTH (type);
+
+
+	  /* Float types should be passed in fpr's, as well as in the
+             stack.  */
+	  if (TYPE_CODE (type) == TYPE_CODE_FLT && f_argno < 13)
+	    {
+
+	      gdb_assert (len <= 8);
+
+	      regcache_cooked_write (regcache,
+				     tdep->ppc_fp0_regnum + 1 + f_argno,
+				     value_contents (arg));
+	      ++f_argno;
+	    }
+
+	  write_memory (sp + 24 + (ii * 4), value_contents (arg), len);
+	  ii += align_up (len, 4) / 4;
+	}
+    }
+
+  /* Set the stack pointer.  According to the ABI, the SP is meant to
+     be set _before_ the corresponding stack space is used.  On AIX,
+     this even applies when the target has been completely stopped!
+     Not doing this can lead to conflicts with the kernel which thinks
+     that it still has control over this not-yet-allocated stack
+     region.  */
+  regcache_raw_write_signed (regcache, gdbarch_sp_regnum (gdbarch), sp);
+
+  /* Set back chain properly.  */
+  store_unsigned_integer (tmp_buffer, wordsize, byte_order, saved_sp);
+  write_memory (sp, tmp_buffer, wordsize);
+
+  /* Point the inferior function call's return address at the dummy's
+     breakpoint.  */
+  regcache_raw_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
+
+  target_store_registers (regcache, -1);
+  return sp;
+}
+
+/* Implement the "return_value" gdbarch method.  */
+
+static enum return_value_convention
+rs6000_lynx178_return_value (struct gdbarch *gdbarch, struct value *function,
+			     struct type *valtype, struct regcache *regcache,
+			     gdb_byte *readbuf, const gdb_byte *writebuf)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+  /* The calling convention this function implements assumes the
+     processor has floating-point registers.  We shouldn't be using it
+     on PowerPC variants that lack them.  */
+  gdb_assert (ppc_floating_point_unit_p (gdbarch));
+
+  /* AltiVec extension: Functions that declare a vector data type as a
+     return value place that return value in VR2.  */
+  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
+      && TYPE_LENGTH (valtype) == 16)
+    {
+      if (readbuf)
+	regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
+      if (writebuf)
+	regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf);
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+
+  /* If the called subprogram returns an aggregate, there exists an
+     implicit first argument, whose value is the address of a caller-
+     allocated buffer into which the callee is assumed to store its
+     return value.  All explicit parameters are appropriately
+     relabeled.  */
+  if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
+      || TYPE_CODE (valtype) == TYPE_CODE_UNION
+      || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
+    return RETURN_VALUE_STRUCT_CONVENTION;
+
+  /* Scalar floating-point values are returned in FPR1 for float or
+     double, and in FPR1:FPR2 for quadword precision.  Fortran
+     complex*8 and complex*16 are returned in FPR1:FPR2, and
+     complex*32 is returned in FPR1:FPR4.  */
+  if (TYPE_CODE (valtype) == TYPE_CODE_FLT
+      && (TYPE_LENGTH (valtype) == 4 || TYPE_LENGTH (valtype) == 8))
+    {
+      struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
+      gdb_byte regval[8];
+
+      /* FIXME: kettenis/2007-01-01: Add support for quadword
+	 precision and complex.  */
+
+      if (readbuf)
+	{
+	  regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
+	  convert_typed_floating (regval, regtype, readbuf, valtype);
+	}
+      if (writebuf)
+	{
+	  convert_typed_floating (writebuf, valtype, regval, regtype);
+	  regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
+	}
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+  }
+
+  /* Values of the types int, long, short, pointer, and char (length
+     is less than or equal to four bytes), as well as bit values of
+     lengths less than or equal to 32 bits, must be returned right
+     justified in GPR3 with signed values sign extended and unsigned
+     values zero extended, as necessary.  */
+  if (TYPE_LENGTH (valtype) <= tdep->wordsize)
+    {
+      if (readbuf)
+	{
+	  ULONGEST regval;
+
+	  /* For reading we don't have to worry about sign extension.  */
+	  regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+					 &regval);
+	  store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), byte_order,
+				  regval);
+	}
+      if (writebuf)
+	{
+	  /* For writing, use unpack_long since that should handle any
+	     required sign extension.  */
+	  regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+					  unpack_long (valtype, writebuf));
+	}
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+
+  /* Eight-byte non-floating-point scalar values must be returned in
+     GPR3:GPR4.  */
+
+  if (TYPE_LENGTH (valtype) == 8)
+    {
+      gdb_assert (TYPE_CODE (valtype) != TYPE_CODE_FLT);
+      gdb_assert (tdep->wordsize == 4);
+
+      if (readbuf)
+	{
+	  gdb_byte regval[8];
+
+	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, regval);
+	  regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+				regval + 4);
+	  memcpy (readbuf, regval, 8);
+	}
+      if (writebuf)
+	{
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
+	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+				 writebuf + 4);
+	}
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+
+  return RETURN_VALUE_STRUCT_CONVENTION;
+}
+
+/* PowerPC Lynx178 OSABI sniffer.  */
+
+static enum gdb_osabi
+rs6000_lynx178_osabi_sniffer (bfd *abfd)
+{
+  if (bfd_get_flavour (abfd) != bfd_target_xcoff_flavour)
+    return GDB_OSABI_UNKNOWN;
+
+  /* The only noticeable difference between Lynx178 XCOFF files and
+     AIX XCOFF files comes from the fact that there are no shared
+     libraries on Lynx178.  So if the number of import files is
+     different from zero, it cannot be a Lynx178 binary.  */
+  if (xcoff_get_n_import_files (abfd) != 0)
+    return GDB_OSABI_UNKNOWN;
+
+  return GDB_OSABI_LYNXOS178;
+}
+
+/* Callback for powerpc-lynx178 initialization.  */
+
+static void
+rs6000_lynx178_init_osabi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  set_gdbarch_push_dummy_call (gdbarch, rs6000_lynx178_push_dummy_call);
+  set_gdbarch_return_value (gdbarch, rs6000_lynx178_return_value);
+  set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
+}
+
+/* -Wmissing-prototypes.  */
+extern initialize_file_ftype _initialize_rs6000_lynx178_tdep;
+
+void
+_initialize_rs6000_lynx178_tdep (void)
+{
+  gdbarch_register_osabi_sniffer (bfd_arch_rs6000,
+                                  bfd_target_xcoff_flavour,
+                                  rs6000_lynx178_osabi_sniffer);
+  gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_LYNXOS178,
+                          rs6000_lynx178_init_osabi);
+}
+
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 10c93cc..f3562ff 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -3113,6 +3113,67 @@ static const struct sym_fns xcoff_sym_fns =
   &psym_functions
 };
 
+/* Same as xcoff_get_n_import_files, but for core files.  */
+
+static int
+xcoff_get_core_n_import_files (bfd *abfd)
+{
+  asection *sect = bfd_get_section_by_name (abfd, ".ldinfo");
+  gdb_byte buf[4];
+  file_ptr offset = 0;
+  int n_entries = 0;
+
+  if (sect == NULL)
+    return -1;  /* Not a core file.  */
+
+  for (offset = 0; offset < bfd_get_section_size (sect);)
+    {
+      int next;
+
+      n_entries++;
+
+      if (!bfd_get_section_contents (abfd, sect, buf, offset, 4))
+	return -1;
+      next = bfd_get_32 (abfd, buf);
+      if (next == 0)
+	break;  /* This is the last entry.  */
+      offset += next;
+    }
+
+  /* Return the number of entries, excluding the first one, which is
+     the path to the executable that produced this core file.  */
+  return n_entries - 1;
+}
+
+/* Return the number of import files (shared libraries) that the given
+   BFD depends on.  Return -1 if this number could not be computed.  */
+
+int
+xcoff_get_n_import_files (bfd *abfd)
+{
+  asection *sect = bfd_get_section_by_name (abfd, ".loader");
+  gdb_byte buf[4];
+  int l_nimpid;
+
+  /* If the ".loader" section does not exist, the objfile is probably
+     not an executable.  Might be a core file...  */
+  if (sect == NULL)
+    return xcoff_get_core_n_import_files (abfd);
+
+  /* The number of entries in the Import Files Table is stored in
+     field l_nimpid.  This field is always at offset 16, and is
+     always 4 bytes long.  Read those 4 bytes.  */
+
+  if (!bfd_get_section_contents (abfd, sect, buf, 16, 4))
+    return -1;
+  l_nimpid = bfd_get_32 (abfd, buf);
+
+  /* By convention, the first entry is the default LIBPATH value
+     to be used by the system loader, so it does not count towards
+     the number of import files.  */
+  return l_nimpid - 1;
+}
+
 /* Free the per-objfile xcoff data.  */
 
 static void
diff --git a/gdb/xcoffread.h b/gdb/xcoffread.h
index 3df08ee..86e1d07 100644
--- a/gdb/xcoffread.h
+++ b/gdb/xcoffread.h
@@ -21,4 +21,6 @@
 
 extern CORE_ADDR xcoff_get_toc_offset (struct objfile *);
 
+extern int xcoff_get_n_import_files (bfd *abfd);
+
 #endif /* xcoffread.h */
-- 
1.7.0.4


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-12-18 15:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-17 17:18 [RFA/commit] Port GDB to powerpc-lynx178 Joel Brobecker
2012-12-17 18:41 ` Tom Tromey
2012-12-18  4:56 ` Yao Qi
2012-12-18  6:17   ` Joel Brobecker
2012-12-18  8:29     ` Yao Qi
2012-12-18 15:00 ` Joel Brobecker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox