Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH]  new support for PPC64 architecture
@ 2003-04-17 22:44 Will Schmidt
  2003-05-07 20:14 ` Andrew Cagney
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Will Schmidt @ 2003-04-17 22:44 UTC (permalink / raw)
  To: gdb-patches; +Cc: will_schmidt, Elena Zannoni

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

All,

   This patch contains code that provides support for GDB on the PPC64
architecture.     This patch will apply clean on top of the RedHat
gdb-5.3post-0.20021129.29.src.rpm.         (A patch against CVS will
happen, but not today.. )


(See attached file: gdb-5.3post-ppc64-support.patch)


-Will


Will Schmidt
willschm@us.ibm.com     will_schmidt@vnet.ibm.com
Linux on PowerPC-64 Development
IBM Rochester

[-- Attachment #2: gdb-5.3post-ppc64-support.patch --]
[-- Type: application/octet-stream, Size: 34384 bytes --]

diff -rupPN gdb-5.2.1/gdb/config/powerpc/ppc64linux.mh src.ppc64/gdb/config/powerpc/ppc64linux.mh
--- gdb-5.2.1/gdb/config/powerpc/ppc64linux.mh	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/ppc64linux.mh	2003-03-05 13:00:33.000000000 -0600
@@ -0,0 +1,14 @@
+# Host: PowerPC, running Linux
+
+XM_FILE= xm-linux.h
+XM_CLIBS=
+
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o linux-proc.o \
+	core-regset.o ppc-linux-nat.o proc-service.o thread-db.o lin-lwp.o  \
+	gcore.o ppc-sysv-tdep.o
+
+LOADLIBES = -ldl -lthread_db
+
+GDBSERVER_DEPFILES= low-linux.o
+GDBSERVER_LIBS= -lnss_dns  -lnss_files -lresolv
diff -rupPN gdb-5.2.1/gdb/config/powerpc/ppc64linux.mt src.ppc64/gdb/config/powerpc/ppc64linux.mt
--- gdb-5.2.1/gdb/config/powerpc/ppc64linux.mt	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/ppc64linux.mt	2003-03-05 16:32:12.000000000 -0600
@@ -0,0 +1,4 @@
+# Target: PPC running Linux 64bit programs
+TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o ppc64-linux-tdep.o solib.o solib-svr4.o solib-legacy.o 
+TM_FILE= tm-ppc64linux.h
+
diff -rupPN gdb-5.2.1/gdb/solib-svr4.c src.ppc64/gdb/solib-svr4.c
--- gdb-5.2.1/gdb/solib-svr4.c	2002-02-05 17:28:13.000000000 -0600
+++ src.ppc64/gdb/solib-svr4.c	2003-01-28 13:28:24.000000000 -0600
@@ -75,6 +75,9 @@ struct lm_info
 
 static char *solib_break_names[] =
 {
+#if defined (SOLIB_BREAK_NAME)
+  SOLIB_BREAK_NAME,
+#endif
   "r_debug_state",
   "_r_debug_state",
   "_dl_debug_state",
@@ -998,7 +1001,7 @@ enable_break (void)
 	 the current pc (which should point at the entry point for the
 	 dynamic linker) and subtracting the offset of the entry point.  */
       if (!load_addr_found)
-	load_addr = read_pc () - tmp_bfd->start_address;
+	load_addr = read_pc () - CONVERT_FROM_FUNC_PTR_ADDR(tmp_bfd->start_address);
 
       /* Record the relocated start and end address of the dynamic linker
          text and plt section for svr4_in_dynsym_resolve_code.  */

diff -rupPN gdb-5.2.1/gdb/config/powerpc/tm-linux.h src.ppc64/gdb/config/powerpc/tm-linux.h
--- gdb-5.2.1/gdb/config/powerpc/tm-linux.h	2002-02-24 16:56:06.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/tm-linux.h	2003-01-28 13:28:24.000000000 -0600
@@ -67,4 +67,9 @@ extern int ppc_linux_in_sigtramp (CORE_A
    to be relocated. */
 #define SOFUN_ADDRESS_MAYBE_MISSING
 
+/* used for ppc64 only, but added here because code is common between ppc and ppc64 */
+struct link_map_offsets *ppc64_linux_svr4_fetch_link_map_offsets (void);
+extern CORE_ADDR ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr);
+
+
 #endif  /* #ifndef TM_LINUX_H */
diff -rupPN gdb-5.2.1/gdb/config/powerpc/tm-ppc64linux.h src.ppc64/gdb/config/powerpc/tm-ppc64linux.h
--- gdb-5.2.1/gdb/config/powerpc/tm-ppc64linux.h	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/tm-ppc64linux.h	2003-01-28 13:28:24.000000000 -0600
@@ -0,0 +1,80 @@
+#ifndef TM_PPC64LINUX_H
+#define TM_PPC64LINUX_H
+
+#include "rs6000/tm-rs6000.h"
+
+/* Avoid warning from redefinition in tm-sysv4.h (included from tm-linux.h) */
+#undef SKIP_TRAMPOLINE_CODE
+#include "tm-linux.h"
+
+#include "gdbarch.h"
+/* Reset these back to the default.  Should really fix this for other
+   powerpc tm.h so it can be chosen at runtime  */
+#undef SOFTWARE_SINGLE_STEP_P
+#define SOFTWARE_SINGLE_STEP_P() (gdbarch_software_single_step_p (current_gdbarch))
+#undef SOFTWARE_SINGLE_STEP
+#define SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p) (gdbarch_software_single_step (current_gdbarch, sig, insert_breakpoints_p))
+
+#ifdef DEAD_CODE
+/* FIXME: tm-linux defines this which a dead interface, as far as I
+   can tell. The macro is unused and there is no definition for the
+   function the macro calls. It is here so we know to get rid of it
+   there. */
+/* Make sure nexti gets the help it needs for debugging assembly code
+   without symbols */
+
+#define AT_SUBROUTINE_CALL_INSTRUCTION_TARGET(prevpc,stoppc) \
+   at_subroutine_call_instruction_target(prevpc,stoppc)
+extern int at_subroutine_call_instruction_target();
+#endif /* DEAD_CODE */
+
+/* We _want_ the SVR4 section offset calculations (see syms_from_objfile()
+   in symfile.c) */
+#undef IBM6000_TARGET
+
+/* Default offset from SP where the LR is stored */
+#undef DEFAULT_LR_SAVE
+#define	DEFAULT_LR_SAVE 16
+
+/* Say that we're using ELF, not XCOFF.  */
+#define ELF_OBJECT_FORMAT 1
+
+/* Say that we're using ELF64 since ABI is closer to XCOFF64. */
+#define ELF64_OBJECT_FORMAT 1
+
+#undef PROCESS_LINENUMBER_HOOK
+
+#undef TEXT_SEGMENT_BASE
+#define TEXT_SEGMENT_BASE 1
+
+/* don't think it is but it can't hurt (can it?) */
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+
+/* The value of symbols of type N_SO and N_FUN maybe null when 
+   it shouldn't be. */
+#define SOFUN_ADDRESS_MAYBE_MISSING
+
+#undef CHILD_SPECIAL_WAITSTATUS
+
+/* Use generic shared library machinery.  */
+#include "solib.h"
+
+/* function entrypoints have a '.' prepended to them (elfread.c) */
+#define DROP_TEXT_NAME_PREFIX_CHAR '.'
+/* skip data symbols if they are from the .opd section (elfread.c) */
+#define SKIP_DATA_IN_OPD
+
+/* define our own child_xfer_memory() ppc-linux-nat.c */
+#define CHILD_XFER_MEMORY
+
+#undef bfd_get_start_address
+#define bfd_get_start_address(abfd) ppc64_bfd_get_start_address (abfd)
+extern  CORE_ADDR ppc64_bfd_get_start_address (bfd *);
+struct link_map_offsets *ppc64_linux_svr4_fetch_link_map_offsets (void);
+extern CORE_ADDR ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr);
+
+/* define additional name for solib functions (solib-svr4.c) to hinge on. */
+#define SOLIB_BREAK_NAME "._dl_debug_state"
+
+
+#endif  /* #ifndef TM_PPC64LINUX_H */
diff -rupPN gdb-5.2.1/gdb/configure.host src.ppc64/gdb/configure.host
--- gdb-5.2.1/gdb/configure.host	2002-03-01 12:35:23.000000000 -0600
+++ src.ppc64/gdb/configure.host	2003-01-28 13:28:24.000000000 -0600
@@ -136,6 +136,8 @@ powerpc-*-aix*)		gdb_host=aix ;;
 powerpc-*-linux*)	gdb_host=linux ;;
 powerpc-*-netbsd*)	gdb_host=nbsd ;;
 
+powerpc64-*-linux*)	gdb_host=ppc64linux ;;
+
 rs6000-*-lynxos*)	gdb_host=rs6000lynx ;;
 rs6000-*-aix4*)		gdb_host=aix4 ;;
 rs6000-*-*)		gdb_host=rs6000 ;;
diff -rupPN gdb-5.2.1/gdb/configure.tgt src.ppc64/gdb/configure.tgt
--- gdb-5.2.1/gdb/configure.tgt	2002-05-28 21:36:55.000000000 -0500
+++ src.ppc64/gdb/configure.tgt	2003-01-28 13:28:24.000000000 -0600
@@ -222,6 +222,15 @@ powerpcle-*-eabi* | powerpcle-*-sysv* | 
 powerpc-*-linux*)	gdb_target=linux
 			build_gdbserver=yes
 			;;
+powerpc64-*-linux*)	gdb_target=ppc64linux
+			###HACK -JX
+			case "${host}" in
+			powerpc-*-linux*)
+			  ## This host can treat target as native
+			  nativefile=nm-linux.h
+			  ;;
+			esac
+			;;
 powerpc-*-vxworks*)	gdb_target=vxworks ;;
 powerpc*-*-*)		if test -f ../sim/ppc/Makefile; then
 			  gdb_target=ppc-sim

diff -rupPN gdb-5.2.1/gdb/elfread.c src.ppc64/gdb/elfread.c
--- gdb-5.2.1/gdb/elfread.c	2002-03-25 10:50:20.000000000 -0600
+++ src.ppc64/gdb/elfread.c	2003-01-28 13:28:24.000000000 -0600
@@ -154,6 +154,12 @@ record_minimal_symbol_and_info (char *na
   if (ms_type == mst_text || ms_type == mst_file_text)
     address = SMASH_TEXT_ADDRESS (address);
 
+#ifdef DROP_TEXT_NAME_PREFIX_CHAR
+  if ((ms_type == mst_text || ms_type == mst_file_text)
+      && name[0] == DROP_TEXT_NAME_PREFIX_CHAR)
+    ++name;
+#endif /* DROP_TEXT_NAME_PREFIX_CHAR */
+
   return prim_record_minimal_symbol_and_info
     (name, address, ms_type, info, bfd_section->index, bfd_section, objfile);
 }
@@ -376,6 +382,10 @@ elf_symtab_read (struct objfile *objfile
 		    {
 		      if (sym->section->flags & SEC_LOAD)
 			{
+#ifdef SKIP_DATA_IN_OPD
+			  if (strcmp(sym->section->name, ".opd") == 0)
+			    continue;
+#endif /* SKIP_DATA_IN_OPD */
 			  ms_type = mst_data;
 			}
 		      else
@@ -455,6 +465,10 @@ elf_symtab_read (struct objfile *objfile
 		         symbol processing. */
 		      if (sym->section->flags & SEC_LOAD)
 			{
+#ifdef SKIP_DATA_IN_OPD
+			  if (strcmp(sym->section->name, ".opd") == 0)
+			    continue;
+#endif /* SKIP_DATA_IN_OPD */
 			  ms_type = mst_file_data;
 			}
 		      else
diff -rupPN gdb-5.2.1/gdb/ppc-linux-nat.c src.ppc64/gdb/ppc-linux-nat.c
--- gdb-5.2.1/gdb/ppc-linux-nat.c	2002-02-21 16:04:46.000000000 -0600
+++ src.ppc64/gdb/ppc-linux-nat.c	2003-01-28 13:28:24.000000000 -0600
@@ -47,11 +47,108 @@
 #define PT_WRITE_U PTRACE_POKEUSR
 #endif
 
-/* Default the type of the ptrace transfer to int.  */
+/* Default the type of the ptrace transfer to long.  */
 #ifndef PTRACE_XFER_TYPE
-#define PTRACE_XFER_TYPE int
+#define PTRACE_XFER_TYPE long
 #endif
 
+/* Write DATA into location ADDR within the "user area" on a 64-bit
+   process from a 32-bit process. */
+#ifndef PPC_PTRACE_POKEUSR_3264
+#define PPC_PTRACE_POKEUSR_3264   0x90 
+#endif
+
+/* Read a register (specified by ADDR) out of the "user area" on a
+   64-bit process from a 32-bit process. */
+#ifndef PPC_PTRACE_PEEKUSR_3264
+#define PPC_PTRACE_PEEKUSR_3264   0x91
+#endif
+
+/* Write word at location ADDR on a 64-bit process from a 32-bit process. */
+#ifndef PPC_PTRACE_POKEDATA_3264
+#define PPC_PTRACE_POKEDATA_3264   0x92
+#endif
+
+/* Read word at location ADDR on a 64-bit process from a 32-bit
+   process. */
+#ifndef PPC_PTRACE_PEEKDATA_3264
+#define PPC_PTRACE_PEEKDATA_3264   0x94
+#endif
+
+#define ARCH64() (REGISTER_RAW_SIZE (0) == 8)
+
+/* REALLY SHAMELESS HACK:
+
+   32 bit programs can exec 64 bit programs and so forth. GDB launches
+   the inferior process by lauching ${SHELL} -c <program and args>.
+   Fortunately, we know that it only tries to get the PC so we only
+   have to hack that.. I THINK.
+
+   At this time we are not ready to unify ppc32 and ppc64 as
+   rs/6000-aix is. and there is know easy way to find out if a process
+   is running 32 or 64 bits so we have this little hack.
+
+   EVEN MORE SHAMELESS HACK: rs6000-nat.c solves this problem by
+   expecting the first few ptracex() calls to fail.
+
+*/
+#include <sys/stat.h>
+#include "bfd/elf-bfd.h"
+static int
+ppc_wordsize_pid(pid_t pid)
+{
+  static ino_t fino = 0;
+  static int last = 0;
+  struct stat sb;
+  const char fmt[] = "/proc/%u/exe";
+  FILE *file;
+  char *fname = alloca (sizeof(fmt) + 10); /* 10 digit pid.. why not */
+  Elf_Internal_Ehdr elfh;
+
+  if ((gdbarch_tdep (current_gdbarch))->wordsize == 4)
+    return 4;
+
+  sprintf (fname, fmt, pid);
+
+  if (stat(fname, &sb) == -1)
+    {
+      internal_error (__FILE__, __LINE__,
+		      "could not stat executable from /proc.");
+      return 0;
+    }
+
+  if (fino == sb.st_ino)
+      return last;
+
+  fino = sb.st_ino;
+
+  /* FIXME: could stat the file and check if inode changed. */
+  file = fopen (fname, "rb");
+  if (file == NULL)
+    {
+      internal_error (__FILE__, __LINE__,
+		      "could not open executable from /proc.");
+      return 0;
+    }
+
+  if (fread (elfh.e_ident, EI_NIDENT, 1, file) == 1)
+    {
+      if (elfh.e_ident [EI_CLASS] == ELFCLASS64)
+	last = 8;
+      else
+	last = 4;
+    }
+  else
+    {
+      last = 0;
+      internal_error (__FILE__, __LINE__,
+		      "could not read executable from /proc.");
+    }
+  fclose (file);
+  
+  return last;
+}
+
 /* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a
    configure time check.  Some older glibc's (for instance 2.2.1)
    don't have a specific powerpc version of ptrace.h, and fall back on
@@ -105,7 +202,15 @@ int have_ptrace_getvrregs = 1;
 int
 kernel_u_size (void)
 {
-  return (sizeof (struct user));
+  if ((gdbarch_tdep (current_gdbarch))->wordsize == sizeof (PTRACE_XFER_TYPE))
+    return (sizeof (struct user));
+  else
+    {
+      /* with a 64-bit kernel, all members of struct user go from 32
+         to 64 bit except for the u_comm character array so we can
+         double everything and subtract sizeof u_comm. */
+      return ((sizeof (struct user) * 2) - sizeof (((struct user*)0)->u_comm));
+    }
 }
 
 /* *INDENT-OFF* */
@@ -125,33 +125,34 @@
 ppc_register_u_addr (int regno)
 {
   int u_addr = -1;
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  int wordsize = tdep->wordsize;
 
   /* General purpose registers occupy 1 slot each in the buffer */
   if (regno >= tdep->ppc_gp0_regnum && regno <= tdep->ppc_gplast_regnum )
-    u_addr =  ((PT_R0 + regno) * 4);
+    u_addr =  ((PT_R0 + regno) * wordsize);
 
   /* Floating point regs: 2 slots each */
   if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM)
-    u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4);
+    u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * wordsize);
 
   /* UISA special purpose registers: 1 slot each */
   if (regno == PC_REGNUM)
-    u_addr = PT_NIP * 4;
+    u_addr = PT_NIP * wordsize;
   if (regno == tdep->ppc_lr_regnum)
-    u_addr = PT_LNK * 4;
+    u_addr = PT_LNK * wordsize;
   if (regno == tdep->ppc_cr_regnum)
-    u_addr = PT_CCR * 4;
+    u_addr = PT_CCR * wordsize;
   if (regno == tdep->ppc_xer_regnum)
-    u_addr = PT_XER * 4;
+    u_addr = PT_XER * wordsize;
   if (regno == tdep->ppc_ctr_regnum)
-    u_addr = PT_CTR * 4;
+    u_addr = PT_CTR * wordsize;
   if (regno == tdep->ppc_mq_regnum)
-    u_addr = PT_MQ * 4;
+    u_addr = PT_MQ * wordsize;
   if (regno == tdep->ppc_ps_regnum)
-    u_addr = PT_MSR * 4;
+    u_addr = PT_MSR * wordsize;
   if (regno == tdep->ppc_fpscr_regnum)
-    u_addr = PT_FPSCR * 4;
+    u_addr = PT_FPSCR * wordsize;
 
   return u_addr;
 }
@@ -205,6 +322,16 @@ fetch_register (int tid, int regno)
   unsigned int offset;         /* Offset of registers within the u area. */
   char *buf = alloca (MAX_REGISTER_RAW_SIZE);
   CORE_ADDR regaddr = ppc_register_u_addr (regno);
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
+
+  /* Do the easy thing for now which is to silently succeed if we are
+     attached to a 32-bit process when we are expecting 64-bits */
+  if (wordsize != ppc_wordsize_pid(tid))
+    {
+      /* supplying garbage.. but that's ok */
+      supply_register (regno, buf);
+      return;
+    }
 
   if (altivec_register_p (regno))
     {
@@ -232,8 +359,19 @@ fetch_register (int tid, int regno)
   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
-					       (PTRACE_ARG3_TYPE) regaddr, 0);
+      if (wordsize != sizeof (PTRACE_XFER_TYPE))
+	{
+	  PTRACE_XFER_TYPE reg;
+	  ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
+		  (PTRACE_ARG3_TYPE) regaddr, &reg);
+	  *(PTRACE_XFER_TYPE *) & buf[i] = reg;
+	}
+      else
+      {
+	  *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
+						   (PTRACE_ARG3_TYPE) regaddr, 0);
+      }
+
       regaddr += sizeof (PTRACE_XFER_TYPE);
       if (errno != 0)
 	{
@@ -364,6 +452,7 @@ store_register (int tid, int regno)
   register int i;
   unsigned int offset;         /* Offset of registers within the u area.  */
   char *buf = alloca (MAX_REGISTER_RAW_SIZE);
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
 
   if (altivec_register_p (regno))
     {
@@ -378,8 +517,18 @@ store_register (int tid, int regno)
   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
-	      *(PTRACE_XFER_TYPE *) & buf[i]);
+      if (wordsize != sizeof (PTRACE_XFER_TYPE))
+	{
+	  PTRACE_XFER_TYPE reg;
+	  ptrace (PPC_PTRACE_POKEUSR_3264, tid, (PTRACE_ARG3_TYPE) regaddr,
+		  *(PTRACE_XFER_TYPE *) & buf[i]);
+	}
+      else
+      {
+	  ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+		  *(PTRACE_XFER_TYPE *) & buf[i]);
+      }
+
       regaddr += sizeof (PTRACE_XFER_TYPE);

       if (errno == EIO 
@@ -533,3 +682,243 @@ fill_fpregset (gdb_fpregset_t *fpregsetp
   if ((regno == -1) || regno == tdep->ppc_fpscr_regnum)
     regcache_collect (tdep->ppc_fpscr_regnum, (char *) (*fpregsetp + regi));
 }
+
+
+#ifdef CHILD_XFER_MEMORY
+
+/* this is a complete rip off from infptrace.c */
+
+#ifndef GDB_MAX_ALLOCA
+#define GDB_MAX_ALLOCA 0x1000
+#endif /* GDB_MAX_ALLOCA */
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR to
+   debugger memory starting at MYADDR.  Copy to inferior if WRITE is
+   nonzero.  TARGET is ignored.
+
+   Returns the length copied, which is either the LEN argument or
+   zero.  This xfer function does not do partial moves, since
+   child_ops doesn't allow memory operations to cross below us in the
+   target stack anyway.  */
+
+int
+child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+		   struct mem_attrib *attrib, struct target_ops *target)
+{
+    int i;
+  /* Round starting address down to longword boundary.  */
+    CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
+  /* Round ending address up; get number of longwords that makes.  */
+    int count = ((((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+		 / sizeof (PTRACE_XFER_TYPE));
+    int alloc = count * sizeof (PTRACE_XFER_TYPE);
+    PTRACE_XFER_TYPE *buffer;
+    struct cleanup *old_chain = NULL;
+    int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
+    int arch64 = ARCH64();
+
+  /* Allocate buffer of that many longwords.  */
+    if (len < GDB_MAX_ALLOCA)
+    {
+	buffer = (PTRACE_XFER_TYPE *) alloca (alloc);
+    }
+    else
+    {
+	buffer = (PTRACE_XFER_TYPE *) xmalloc (alloc);
+	old_chain = make_cleanup (xfree, buffer);
+    }
+
+  /* WARNING: from kernel source: "when I and D space are separate,
+     these will need to be fixed." */
+    if (write)
+    {
+      /* Fill start and end extra bytes of buffer with existing memory
+	 data.  */
+	if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE))
+	{
+	  /* Need part of initial word -- fetch it.  */
+	    if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	    {
+		buffer[0] = ptrace (PT_READ_I, PIDGET (inferior_ptid), 
+				    (PTRACE_ARG3_TYPE) addr, 0);
+	    }
+	    else
+	    {
+		if (arch64) {
+		    buffer[0] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid), 
+					(unsigned long) addr, 0);
+		}
+		else 
+		{
+		    ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid), 
+			    (PTRACE_ARG3_TYPE) &addr, buffer);
+		}
+	    }
+	}
+	if (count > 1)		/* FIXME, avoid if even boundary.  */
+	{
+	    CORE_ADDR a64 = (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE));
+	    if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	    {
+		buffer[count - 1] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
+					    (PTRACE_ARG3_TYPE) a64, 0);
+	    }
+	    else
+		if (arch64) {
+		    buffer[count-1] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid),
+					      (PTRACE_ARG3_TYPE) &a64, 0);
+		}
+		else
+		{
+		    ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid),
+			    (PTRACE_ARG3_TYPE) &a64, &buffer[count - 1]);
+		}
+	}
+
+      /* Copy data to be written over corresponding part of buffer.  */
+	memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+		myaddr, len);
+
+      /* Write the entire buffer.  */
+	for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+	{
+	    errno = 0;
+	    if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	    {
+		ptrace (PT_WRITE_D, PIDGET (inferior_ptid), 
+			(PTRACE_ARG3_TYPE) addr, buffer[i]);
+	    }
+	    else
+		if (arch64) {
+		    ptrace (PT_WRITE_D, PIDGET (inferior_ptid), 
+			    (unsigned long) addr, buffer[i]);  
+		}
+		else 
+		{
+		    ptrace (PPC_PTRACE_POKEDATA_3264, PIDGET (inferior_ptid), 
+			    (PTRACE_ARG3_TYPE) &addr, buffer[i]);
+		}
+	    if (errno)
+	    {
+		errno = 0;
+		if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+		{
+		    ptrace (PT_WRITE_I, PIDGET (inferior_ptid), 
+			    (PTRACE_ARG3_TYPE) addr, buffer[i]);
+		}
+		else
+		    if (arch64) {
+			ptrace (PTRACE_POKEDATA, PIDGET (inferior_ptid),  
+				(PTRACE_ARG3_TYPE) addr, buffer[i]); 
+		    }
+		    else 
+		    {
+			ptrace (PPC_PTRACE_POKEDATA_3264, PIDGET (inferior_ptid), 
+				(PTRACE_ARG3_TYPE) &addr, buffer[i]);
+		    }
+	    }
+	    if (errno)
+		return 0;
+	}
+#ifdef CLEAR_INSN_CACHE
+	    CLEAR_INSN_CACHE ();
+#endif
+    }
+  else
+  {
+      /* Read all the longwords.  */
+      for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+      {
+	  errno = 0;
+	  if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	  {
+	      buffer[i] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
+				  (PTRACE_ARG3_TYPE) addr, 0);
+	  }
+	  else
+	  {
+	      if (arch64) {
+		  buffer[i] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid),
+				      (unsigned long) addr, 0);
+	      }
+	      else
+	      {
+		  ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid),
+			  (PTRACE_ARG3_TYPE) &addr, &buffer[i]);
+	      }
+	      if (errno)
+		  return 0;
+	      QUIT;
+	  }
+
+      /* Copy appropriate bytes out of the buffer.  */
+	  memcpy (myaddr,
+		  (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+		  len);
+      }
+  }
+  if (old_chain != NULL)
+    do_cleanups (old_chain);
+  return len;
+    }
+
+\f
+/* Did not want to add this originally since the kernel will give us a
+   lot of gargabe (and would probably fail if it wasn't for the
+   FPU's). But at least you can get the other registers in struct
+   pt_regs.  Perhaps we can get the kernels to co-operate. */
+static void
+udot_info (char *dummy1, int dummy2)
+{
+  int udot_off;			/* Offset into user struct */
+  int udot_val;			/* Value from user struct at udot_off */
+  char mess[128];		/* For messages */
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
+
+  if (!target_has_execution)
+    {
+      error ("The program is not being run.");
+    }
+
+  for (udot_off = 0; udot_off < KERNEL_U_SIZE; udot_off += sizeof (udot_val))
+    {
+      if ((udot_off % 24) == 0)
+	{
+	  if (udot_off > 0)
+	    {
+	      printf_filtered ("\n");
+	    }
+	  printf_filtered ("%04x:", udot_off);
+	}
+      if (wordsize != sizeof (PTRACE_XFER_TYPE))
+	{
+	  PTRACE_XFER_TYPE reg;
+	  /* ptrace will place contents in "data" pointer */
+	  ptrace (PPC_PTRACE_PEEKUSR_3264, PIDGET (inferior_ptid),
+		  (PTRACE_ARG3_TYPE) udot_off, &reg);
+	  udot_val = reg;
+	}
+      else
+	udot_val = ptrace (PT_READ_U, PIDGET (inferior_ptid),
+			   (PTRACE_ARG3_TYPE) udot_off, 0);
+      if (errno != 0)
+	{
+	  sprintf (mess, "\nreading user struct at offset 0x%x", udot_off);
+	  perror_with_name (mess);
+	}
+      /* Avoid using nonportable (?) "*" in print specs */
+      printf_filtered (sizeof (int) == 4 ? " 0x%08x" : " 0x%16x", udot_val);
+    }
+  printf_filtered ("\n");
+}
+#endif /* CHILD_XFER_MEMORY */
+
+#include "command.h"
+void
+_initialize_ppc_linux_nat (void)
+{
+#ifdef CHILD_XFER_MEMORY
+  add_info ("udot", udot_info,
+	    "Print contents of kernel ``struct user'' for current child.");
+#endif
+}
diff -rupPN gdb-5.2.1/gdb/ppc-linux-tdep.c src.ppc64/gdb/ppc-linux-tdep.c
--- gdb-5.2.1/gdb/ppc-linux-tdep.c	2002-02-24 16:31:19.000000000 -0600
+++ src.ppc64/gdb/ppc-linux-tdep.c	2003-01-28 13:28:24.000000000 -0600
@@ -57,6 +57,8 @@
    offsetof(struct sigcontext_struct, handler) == 0x14 */
 #define PPC_LINUX_HANDLER_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x14)
 
+#define TDEP	gdbarch_tdep (current_gdbarch)
+	
 /* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */
 #define PPC_LINUX_PT_R0		0
 #define PPC_LINUX_PT_R1		1
@@ -730,3 +732,64 @@ _initialize_ppc_linux_tdep (void)
 			  ppc_linux_init_abi);
   add_core_fns (&ppc_linux_regset_core_fns);
 }
+
+struct link_map_offsets *
+	ppc64_linux_svr4_fetch_link_map_offsets (void)
+{
+    static struct link_map_offsets lmo;
+    static struct link_map_offsets *lmp = NULL;
+
+    if (lmp == NULL)
+    {
+	lmp = &lmo;
+
+	lmo.r_debug_size = 16;/* The actual size is xx bytes, but
+					   this is all we need.  */
+	lmo.r_map_offset = 8;
+	lmo.r_map_size   = 8; 
+	lmo.link_map_size = 40;  /* The actual size is xxx bytes, but
+					   this is all we need.  */
+	lmo.l_addr_offset = 0;
+	lmo.l_addr_size   = 8;
+	lmo.l_name_offset = 8; 
+	lmo.l_name_size   = 8;
+	lmo.l_next_offset = 24;
+	lmo.l_next_size   = 8;
+	lmo.l_prev_offset = 32;
+	lmo.l_prev_size   = 8;
+    }
+
+    return lmp;
+}
+
+
+/* Support for CONVERT_FROM_FUNC_PTR_ADDR(ADDR).
+	   Duplicate of RS6000 function, except ppc64_linux requires relocated address. */
+static CORE_ADDR
+read_memory_addr (CORE_ADDR memaddr, int len)
+{
+    return read_memory_unsigned_integer (memaddr, len);
+}
+	
+	
+CORE_ADDR
+ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr)
+{
+    long long my_adder;
+    struct obj_section *s;
+    CORE_ADDR retval;
+    extern struct obj_section *find_pc_section(CORE_ADDR);
+
+	/* this should be the base address that the object (containing the func_ptr_addr) is loaded at. */
+    my_adder = 0x7fe0000000; 
+
+    s = find_pc_section (my_adder + addr);
+    if (s && s->the_bfd_section->flags & SEC_CODE)
+	return addr;
+
+	  /* ADDR is in the data space, so it's a special function pointer. */
+    retval = read_memory_addr (my_adder + addr, TDEP->wordsize);
+	/*  printf("reading 0x%lx ",my_adder+addr); */
+	/*  printf("ppc64...convert_func_ptr addr:0x%lx  new:0x%lx\n",addr,retval); */
+    return retval;
+}
diff -rupPN gdb-5.2.1/gdb/ppc64-linux-tdep.c src.ppc64/gdb/ppc64-linux-tdep.c
--- gdb-5.2.1/gdb/ppc64-linux-tdep.c	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/ppc64-linux-tdep.c	2003-01-28 13:28:24.000000000 -0600
@@ -0,0 +1,80 @@
+/* Target-dependent code for GDB, the GNU debugger.
+
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   2000, 2001 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"
+
+
+/* These elfcore fuctions are defined in libbfd.a but only when host
+   == target, once we can convince the bfd to supply it these can go */
+#define _SYSCALL32
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#define ARCH_SIZE 0
+#include "elf-bfd.h"
+#include "libiberty.h"
+#include <sys/procfs.h>
+
+
+/*
+ * Initialization
+ */
+void
+_initialize_ppc64_linux_tdep (void)
+{
+  /* hardware/kernel supports single stepping */
+  set_gdbarch_software_single_step (current_gdbarch, NULL);
+}
+
+/* the start_address stored in the bfd is a function descriptor */
+#include "gdb/target.h"
+CORE_ADDR
+ppc64_bfd_get_start_address (bfd *abfd)
+{
+  extern struct target_ops exec_ops;
+  CORE_ADDR myaddr;
+  xfer_memory(abfd->start_address, (char *)&myaddr, 8, 0, 0, &exec_ops);
+  return myaddr;
+}
+
+/* Fetch (and possibly build) an appropriate link_map_offsets
+   structure for GNU/Linux PPC targets using the struct offsets
+   defined in link.h (but without actual reference to that file).
+
+   This makes it possible to access GNU/Linux PPC shared libraries
+   from a GDB that was not built on an GNU/Linux PPC host (for cross
+   debugging).
+
+*/
+#include "gdbcore.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+#include "ppc-tdep.h"
+#define TDEP	gdbarch_tdep (current_gdbarch)
+
+static CORE_ADDR
+read_memory_addr (CORE_ADDR memaddr, int len)
+{
+  return read_memory_unsigned_integer (memaddr, len);
+}
diff -rupPN gdb-5.2.1/gdb/rs6000-tdep.c src.ppc64/gdb/rs6000-tdep.c
--- gdb-5.2.1/gdb/rs6000-tdep.c	2002-04-01 00:01:46.000000000 -0600
+++ src.ppc64/gdb/rs6000-tdep.c	2003-01-28 13:28:24.000000000 -0600
@@ -513,13 +508,13 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 
       if ((op & 0xfc1fffff) == 0x7c0802a6)
 	{			/* mflr Rx */
-	  lr_reg = (op & 0x03e00000) | 0x90010000;
+	  lr_reg = (op & 0x03e00000);
 	  continue;
 
 	}
       else if ((op & 0xfc1fffff) == 0x7c000026)
 	{			/* mfcr Rx */
-	  cr_reg = (op & 0x03e00000) | 0x90010000;
+	  cr_reg = (op & 0x03e00000);
 	  continue;
 
 	}
@@ -545,7 +540,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 	    {
 	      fdata->saved_gpr = reg;
 	      if ((op & 0xfc1f0003) == 0xf8010000)
-		op = (op >> 1) << 1;
+		op &= ~3UL;
 	      fdata->gpr_offset = SIGNED_SHORT (op) + offset;
 	    }
 	  continue;
@@ -577,19 +572,49 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 	  continue;
 
 	}
-      else if (lr_reg != -1 && (op & 0xffff0000) == lr_reg)
-	{			/* st Rx,NUM(r1) 
-				   where Rx == lr */
-	  fdata->lr_offset = SIGNED_SHORT (op) + offset;
+      else if (lr_reg != -1 &&
+	       /* std Rx || stdu Rx */
+	       (((op & 0xffff0000) == (lr_reg | 0xf8010000)) ||
+		/* stw Rx */
+		((op & 0xffff0000) == (lr_reg | 0x90010000)) ||
+		/* stwu Rx */
+		((op & 0xffff0000) == (lr_reg | 0x94010000))))
+	{	/* where Rx == lr */
+	  fdata->lr_offset = offset;
 	  fdata->nosavedpc = 0;
 	  lr_reg = 0;
+	  if ((op & 0xfc000003) == 0xf8000000 ||	/* std Rx */
+	      (op & 0xfc000000) == 0x90000000)		/* stw Rx */
+	    {
+	      /* does not update r1 add d to lr_offset */
+	      fdata->lr_offset = SIGNED_SHORT (op);
+	    }
 	  continue;
 
 	}
-      else if (cr_reg != -1 && (op & 0xffff0000) == cr_reg)
-	{			/* st Rx,NUM(r1) 
+      else if (cr_reg != -1 &&
+	       /* std Rx || stdu Rx */
+	       (((op & 0xffff0000) == (cr_reg | 0xf8010000)) ||
+		/* stw Rx */
+		((op & 0xffff0000) == (cr_reg | 0x90010000)) ||
+		/* stwu Rx */
+		((op & 0xffff0000) == (cr_reg | 0x94010000))))
+	{	/* where Rx == cr */
+	  fdata->cr_offset = offset;
+	  cr_reg = 0;
+	  if ((op & 0xfc000003) == 0xf8000000 ||
+	      (op & 0xfc000000) == 0x90000000)
+	    {
+	      /* does not update r1 add d to cr_offset */
+	      fdata->cr_offset += SIGNED_SHORT (op);
+	    }
+	  continue;
+
+	}
+      else if (cr_reg != -1 && (op & 0xffff0003) == cr_reg)
+	{			/* std Rx,NUM(r1) || stdu Rx,NUM(r1) 
 				   where Rx == cr */
-	  fdata->cr_offset = SIGNED_SHORT (op) + offset;
+	  fdata->cr_offset = SIGNED_SHORT (op & ~3UL) + offset;
 	  cr_reg = 0;
 	  continue;
 
@@ -634,30 +658,41 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 				   this branch */
 	  continue;
 
-	  /* update stack pointer */
 	}
-      else if ((op & 0xffff0000) == 0x94210000 ||	/* stu r1,NUM(r1) */
-	       (op & 0xffff0003) == 0xf8210001)		/* stdu r1,NUM(r1) */
-	{
+      /* update stack pointer */
+      else if ((op & 0xfc1f0000) == 0x94010000)
+	{		/* stu rX,NUM(r1) ||  stwu rX,NUM(r1) */
 	  fdata->frameless = 0;
-	  if ((op & 0xffff0003) == 0xf8210001)
-	    op = (op >> 1) << 1;
 	  fdata->offset = SIGNED_SHORT (op);
 	  offset = fdata->offset;
 	  continue;
-
 	}
-      else if (op == 0x7c21016e)
-	{			/* stwux 1,1,0 */
+      else if ((op & 0xfc1f016a) == 0x7c01016e)
+	{			/* stwux rX,r1,rY */
+	  /* no way to figure out what r1 is going to be */
+	  fdata->frameless = 0;
+	  offset = fdata->offset;
+	  continue;
+	}
+      else if ((op & 0xfc1f0003) == 0xf8010001)
+	{			/* stdu rX,NUM(r1) */
+	  fdata->frameless = 0;
+	  fdata->offset = SIGNED_SHORT (op & ~3UL);
+	  offset = fdata->offset;
+	  continue;
+	}
+      else if ((op & 0xfc1f016a) == 0x7c01016a)
+	{			/* stdux rX,r1,rY */
+	  /* no way to figure out what r1 is going to be */
 	  fdata->frameless = 0;
 	  offset = fdata->offset;
 	  continue;
-
-	  /* Load up minimal toc pointer */
 	}
-      else if ((op >> 22) == 0x20f
+      /* Load up minimal toc pointer */
+      else if (((op >> 22) == 0x20f	||	/* l r31,... or l r30,... */
+	       (op >> 22) == 0x3af)		/* ld r31,... or ld r30,... */
 	       && !minimal_toc_loaded)
-	{			/* l r31,... or l r30,... */
+	{
 	  minimal_toc_loaded = 1;
 	  continue;
 
@@ -2439,6 +2483,44 @@ static const struct reg registers_7400[]
   /* FIXME? Add more registers? */
 };
 
+
+/* PowerPC UISA - a PPC64 processor as viewed by user-level code. */
+/* Should be able to use the common registers_powerpc[] here, however
+   it does not define an fpscr, though both linux and aix get one from
+   ptrace(). Can only assume that there is a 32-bit core our there
+   that does not have an fpscr.  I think we can assert that all 64-bit
+   cores do. */
+static const struct reg registers_powerpc64[] =
+{
+  COMMON_UISA_REGS,
+  /* SPRs */
+  /*  66 */ R4(cr), R(lr), R(ctr), R4(xer),
+  /*  70 */ R4(fpscr), R0 /* mq? */
+};
+
+static const struct reg registers_a35[] =
+{
+  COMMON_UISA_REGS,
+  /* SPRs */
+  /*  66 */ R4(cr), R(lr), R(ctr), R4(xer),
+  /*  70 */ R4(fpscr), R0 /* mq? */,
+  /*  72 */ R(dabr), R(iabr), R4(dsisr),
+  /*  75 */ R(dar), R4(dec), R(sdr1), R(srr0), R(srr1),
+  /*  80 */ R(sprg0), R(sprg1), R(sprg2), R(sprg3),
+  /*  84 */ R64(asr), R4(ear), R4(tbl), R4(tbu),
+  /*  88 */ R(ibat0u), R(ibat0l), R(ibat1u), R(ibat1l),
+  /*  92 */ R(ibat2u), R(ibat2l), R(ibat3u), R(ibat3l),
+  /*  96 */ R(dbat0u), R(dbat0l), R(dbat1u), R(dbat1l),
+  /* 100 */ R(dbat2u), R(dbat2l), R(dbat3u), R(dbat3l),
+  /* 104 */ R(pir), R4(mmcr0),
+  /* 106..121 segment regs 0..15 */ 
+  /* 106 */ R(sr0), R(sr1), R(sr2), R(sr3),
+  /* 110 */ R(sr4), R(sr5), R(sr6), R(sr7),
+  /* 114 */ R(sr8), R(sr9), R(sr10), R(sr11),
+  /* 118 */ R(sr12), R(sr13), R(sr14), R(sr15),
+  /* 122 */ R4(pvr) /* processor version register */
+};
+
 /* Motorola e500.  */
 static const struct reg registers_e500[] =
 {
@@ -2947,6 +3051,15 @@ rs6000_gdbarch_init (struct gdbarch_info
          descriptors).  */
       set_gdbarch_convert_from_func_ptr_addr (gdbarch,
 	rs6000_convert_from_func_ptr_addr);
+
+      /* wordsize 8, ppc64 linux  functions */
+      if (osabi == ELFOSABI_LINUX)
+      {
+	  set_solib_svr4_fetch_link_map_offsets
+	    (gdbarch, ppc64_linux_svr4_fetch_link_map_offsets);
+	  set_gdbarch_convert_from_func_ptr_addr
+            (gdbarch, ppc64_linux_convert_from_func_ptr_addr);
+      }
     }
   set_gdbarch_frame_args_address (gdbarch, rs6000_frame_args_address);
   set_gdbarch_frame_locals_address (gdbarch, rs6000_frame_args_address);

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

* Re: [PATCH]  new support for PPC64 architecture
  2003-04-17 22:44 [PATCH] new support for PPC64 architecture Will Schmidt
@ 2003-05-07 20:14 ` Andrew Cagney
  2003-05-07 20:37 ` Elena Zannoni
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Andrew Cagney @ 2003-05-07 20:14 UTC (permalink / raw)
  To: Will Schmidt, Elena Zannoni; +Cc: gdb-patches, will_schmidt

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

For the record.  The software letter for this patch has been completed. 
  This making it possible for GDB developers to examine the actual changes.

 From a quick exmination:

- the patch is against a very old code base [20021129], the actual 
changes will most likely no longer be applicable.  GDB's frame, register 
and inferior-function-call code have, for instance, all been overhauled

- changes such as:
+void
+_initialize_ppc64_linux_tdep (void)
+{
+  /* hardware/kernel supports single stepping */
+  set_gdbarch_software_single_step (current_gdbarch, NULL);
+}
and:
+#if defined (SOLIB_BREAK_NAME)
+#ifdef DROP_TEXT_NAME_PREFIX_CHAR
+#ifdef SKIP_DATA_IN_OPD
+#undef SKIP_TRAMPOLINE_CODE
+#ifdef DEAD_CODE
are simply wrong wrong.  With one exception related to shared libraries, 
GDB only accepts strict multi-arch targets.

Someone has a lot of work ahead of them, sigh.

Andrew

[-- Attachment #2: gdb-5.3post-ppc64-support.patch --]
[-- Type: text/plain, Size: 34384 bytes --]

diff -rupPN gdb-5.2.1/gdb/config/powerpc/ppc64linux.mh src.ppc64/gdb/config/powerpc/ppc64linux.mh
--- gdb-5.2.1/gdb/config/powerpc/ppc64linux.mh	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/ppc64linux.mh	2003-03-05 13:00:33.000000000 -0600
@@ -0,0 +1,14 @@
+# Host: PowerPC, running Linux
+
+XM_FILE= xm-linux.h
+XM_CLIBS=
+
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o linux-proc.o \
+	core-regset.o ppc-linux-nat.o proc-service.o thread-db.o lin-lwp.o  \
+	gcore.o ppc-sysv-tdep.o
+
+LOADLIBES = -ldl -lthread_db
+
+GDBSERVER_DEPFILES= low-linux.o
+GDBSERVER_LIBS= -lnss_dns  -lnss_files -lresolv
diff -rupPN gdb-5.2.1/gdb/config/powerpc/ppc64linux.mt src.ppc64/gdb/config/powerpc/ppc64linux.mt
--- gdb-5.2.1/gdb/config/powerpc/ppc64linux.mt	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/ppc64linux.mt	2003-03-05 16:32:12.000000000 -0600
@@ -0,0 +1,4 @@
+# Target: PPC running Linux 64bit programs
+TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o ppc64-linux-tdep.o solib.o solib-svr4.o solib-legacy.o 
+TM_FILE= tm-ppc64linux.h
+
diff -rupPN gdb-5.2.1/gdb/solib-svr4.c src.ppc64/gdb/solib-svr4.c
--- gdb-5.2.1/gdb/solib-svr4.c	2002-02-05 17:28:13.000000000 -0600
+++ src.ppc64/gdb/solib-svr4.c	2003-01-28 13:28:24.000000000 -0600
@@ -75,6 +75,9 @@ struct lm_info
 
 static char *solib_break_names[] =
 {
+#if defined (SOLIB_BREAK_NAME)
+  SOLIB_BREAK_NAME,
+#endif
   "r_debug_state",
   "_r_debug_state",
   "_dl_debug_state",
@@ -998,7 +1001,7 @@ enable_break (void)
 	 the current pc (which should point at the entry point for the
 	 dynamic linker) and subtracting the offset of the entry point.  */
       if (!load_addr_found)
-	load_addr = read_pc () - tmp_bfd->start_address;
+	load_addr = read_pc () - CONVERT_FROM_FUNC_PTR_ADDR(tmp_bfd->start_address);
 
       /* Record the relocated start and end address of the dynamic linker
          text and plt section for svr4_in_dynsym_resolve_code.  */

diff -rupPN gdb-5.2.1/gdb/config/powerpc/tm-linux.h src.ppc64/gdb/config/powerpc/tm-linux.h
--- gdb-5.2.1/gdb/config/powerpc/tm-linux.h	2002-02-24 16:56:06.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/tm-linux.h	2003-01-28 13:28:24.000000000 -0600
@@ -67,4 +67,9 @@ extern int ppc_linux_in_sigtramp (CORE_A
    to be relocated. */
 #define SOFUN_ADDRESS_MAYBE_MISSING
 
+/* used for ppc64 only, but added here because code is common between ppc and ppc64 */
+struct link_map_offsets *ppc64_linux_svr4_fetch_link_map_offsets (void);
+extern CORE_ADDR ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr);
+
+
 #endif  /* #ifndef TM_LINUX_H */
diff -rupPN gdb-5.2.1/gdb/config/powerpc/tm-ppc64linux.h src.ppc64/gdb/config/powerpc/tm-ppc64linux.h
--- gdb-5.2.1/gdb/config/powerpc/tm-ppc64linux.h	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/tm-ppc64linux.h	2003-01-28 13:28:24.000000000 -0600
@@ -0,0 +1,80 @@
+#ifndef TM_PPC64LINUX_H
+#define TM_PPC64LINUX_H
+
+#include "rs6000/tm-rs6000.h"
+
+/* Avoid warning from redefinition in tm-sysv4.h (included from tm-linux.h) */
+#undef SKIP_TRAMPOLINE_CODE
+#include "tm-linux.h"
+
+#include "gdbarch.h"
+/* Reset these back to the default.  Should really fix this for other
+   powerpc tm.h so it can be chosen at runtime  */
+#undef SOFTWARE_SINGLE_STEP_P
+#define SOFTWARE_SINGLE_STEP_P() (gdbarch_software_single_step_p (current_gdbarch))
+#undef SOFTWARE_SINGLE_STEP
+#define SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p) (gdbarch_software_single_step (current_gdbarch, sig, insert_breakpoints_p))
+
+#ifdef DEAD_CODE
+/* FIXME: tm-linux defines this which a dead interface, as far as I
+   can tell. The macro is unused and there is no definition for the
+   function the macro calls. It is here so we know to get rid of it
+   there. */
+/* Make sure nexti gets the help it needs for debugging assembly code
+   without symbols */
+
+#define AT_SUBROUTINE_CALL_INSTRUCTION_TARGET(prevpc,stoppc) \
+   at_subroutine_call_instruction_target(prevpc,stoppc)
+extern int at_subroutine_call_instruction_target();
+#endif /* DEAD_CODE */
+
+/* We _want_ the SVR4 section offset calculations (see syms_from_objfile()
+   in symfile.c) */
+#undef IBM6000_TARGET
+
+/* Default offset from SP where the LR is stored */
+#undef DEFAULT_LR_SAVE
+#define	DEFAULT_LR_SAVE 16
+
+/* Say that we're using ELF, not XCOFF.  */
+#define ELF_OBJECT_FORMAT 1
+
+/* Say that we're using ELF64 since ABI is closer to XCOFF64. */
+#define ELF64_OBJECT_FORMAT 1
+
+#undef PROCESS_LINENUMBER_HOOK
+
+#undef TEXT_SEGMENT_BASE
+#define TEXT_SEGMENT_BASE 1
+
+/* don't think it is but it can't hurt (can it?) */
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+
+/* The value of symbols of type N_SO and N_FUN maybe null when 
+   it shouldn't be. */
+#define SOFUN_ADDRESS_MAYBE_MISSING
+
+#undef CHILD_SPECIAL_WAITSTATUS
+
+/* Use generic shared library machinery.  */
+#include "solib.h"
+
+/* function entrypoints have a '.' prepended to them (elfread.c) */
+#define DROP_TEXT_NAME_PREFIX_CHAR '.'
+/* skip data symbols if they are from the .opd section (elfread.c) */
+#define SKIP_DATA_IN_OPD
+
+/* define our own child_xfer_memory() ppc-linux-nat.c */
+#define CHILD_XFER_MEMORY
+
+#undef bfd_get_start_address
+#define bfd_get_start_address(abfd) ppc64_bfd_get_start_address (abfd)
+extern  CORE_ADDR ppc64_bfd_get_start_address (bfd *);
+struct link_map_offsets *ppc64_linux_svr4_fetch_link_map_offsets (void);
+extern CORE_ADDR ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr);
+
+/* define additional name for solib functions (solib-svr4.c) to hinge on. */
+#define SOLIB_BREAK_NAME "._dl_debug_state"
+
+
+#endif  /* #ifndef TM_PPC64LINUX_H */
diff -rupPN gdb-5.2.1/gdb/configure.host src.ppc64/gdb/configure.host
--- gdb-5.2.1/gdb/configure.host	2002-03-01 12:35:23.000000000 -0600
+++ src.ppc64/gdb/configure.host	2003-01-28 13:28:24.000000000 -0600
@@ -136,6 +136,8 @@ powerpc-*-aix*)		gdb_host=aix ;;
 powerpc-*-linux*)	gdb_host=linux ;;
 powerpc-*-netbsd*)	gdb_host=nbsd ;;
 
+powerpc64-*-linux*)	gdb_host=ppc64linux ;;
+
 rs6000-*-lynxos*)	gdb_host=rs6000lynx ;;
 rs6000-*-aix4*)		gdb_host=aix4 ;;
 rs6000-*-*)		gdb_host=rs6000 ;;
diff -rupPN gdb-5.2.1/gdb/configure.tgt src.ppc64/gdb/configure.tgt
--- gdb-5.2.1/gdb/configure.tgt	2002-05-28 21:36:55.000000000 -0500
+++ src.ppc64/gdb/configure.tgt	2003-01-28 13:28:24.000000000 -0600
@@ -222,6 +222,15 @@ powerpcle-*-eabi* | powerpcle-*-sysv* | 
 powerpc-*-linux*)	gdb_target=linux
 			build_gdbserver=yes
 			;;
+powerpc64-*-linux*)	gdb_target=ppc64linux
+			###HACK -JX
+			case "${host}" in
+			powerpc-*-linux*)
+			  ## This host can treat target as native
+			  nativefile=nm-linux.h
+			  ;;
+			esac
+			;;
 powerpc-*-vxworks*)	gdb_target=vxworks ;;
 powerpc*-*-*)		if test -f ../sim/ppc/Makefile; then
 			  gdb_target=ppc-sim

diff -rupPN gdb-5.2.1/gdb/elfread.c src.ppc64/gdb/elfread.c
--- gdb-5.2.1/gdb/elfread.c	2002-03-25 10:50:20.000000000 -0600
+++ src.ppc64/gdb/elfread.c	2003-01-28 13:28:24.000000000 -0600
@@ -154,6 +154,12 @@ record_minimal_symbol_and_info (char *na
   if (ms_type == mst_text || ms_type == mst_file_text)
     address = SMASH_TEXT_ADDRESS (address);
 
+#ifdef DROP_TEXT_NAME_PREFIX_CHAR
+  if ((ms_type == mst_text || ms_type == mst_file_text)
+      && name[0] == DROP_TEXT_NAME_PREFIX_CHAR)
+    ++name;
+#endif /* DROP_TEXT_NAME_PREFIX_CHAR */
+
   return prim_record_minimal_symbol_and_info
     (name, address, ms_type, info, bfd_section->index, bfd_section, objfile);
 }
@@ -376,6 +382,10 @@ elf_symtab_read (struct objfile *objfile
 		    {
 		      if (sym->section->flags & SEC_LOAD)
 			{
+#ifdef SKIP_DATA_IN_OPD
+			  if (strcmp(sym->section->name, ".opd") == 0)
+			    continue;
+#endif /* SKIP_DATA_IN_OPD */
 			  ms_type = mst_data;
 			}
 		      else
@@ -455,6 +465,10 @@ elf_symtab_read (struct objfile *objfile
 		         symbol processing. */
 		      if (sym->section->flags & SEC_LOAD)
 			{
+#ifdef SKIP_DATA_IN_OPD
+			  if (strcmp(sym->section->name, ".opd") == 0)
+			    continue;
+#endif /* SKIP_DATA_IN_OPD */
 			  ms_type = mst_file_data;
 			}
 		      else
diff -rupPN gdb-5.2.1/gdb/ppc-linux-nat.c src.ppc64/gdb/ppc-linux-nat.c
--- gdb-5.2.1/gdb/ppc-linux-nat.c	2002-02-21 16:04:46.000000000 -0600
+++ src.ppc64/gdb/ppc-linux-nat.c	2003-01-28 13:28:24.000000000 -0600
@@ -47,11 +47,108 @@
 #define PT_WRITE_U PTRACE_POKEUSR
 #endif
 
-/* Default the type of the ptrace transfer to int.  */
+/* Default the type of the ptrace transfer to long.  */
 #ifndef PTRACE_XFER_TYPE
-#define PTRACE_XFER_TYPE int
+#define PTRACE_XFER_TYPE long
 #endif
 
+/* Write DATA into location ADDR within the "user area" on a 64-bit
+   process from a 32-bit process. */
+#ifndef PPC_PTRACE_POKEUSR_3264
+#define PPC_PTRACE_POKEUSR_3264   0x90 
+#endif
+
+/* Read a register (specified by ADDR) out of the "user area" on a
+   64-bit process from a 32-bit process. */
+#ifndef PPC_PTRACE_PEEKUSR_3264
+#define PPC_PTRACE_PEEKUSR_3264   0x91
+#endif
+
+/* Write word at location ADDR on a 64-bit process from a 32-bit process. */
+#ifndef PPC_PTRACE_POKEDATA_3264
+#define PPC_PTRACE_POKEDATA_3264   0x92
+#endif
+
+/* Read word at location ADDR on a 64-bit process from a 32-bit
+   process. */
+#ifndef PPC_PTRACE_PEEKDATA_3264
+#define PPC_PTRACE_PEEKDATA_3264   0x94
+#endif
+
+#define ARCH64() (REGISTER_RAW_SIZE (0) == 8)
+
+/* REALLY SHAMELESS HACK:
+
+   32 bit programs can exec 64 bit programs and so forth. GDB launches
+   the inferior process by lauching ${SHELL} -c <program and args>.
+   Fortunately, we know that it only tries to get the PC so we only
+   have to hack that.. I THINK.
+
+   At this time we are not ready to unify ppc32 and ppc64 as
+   rs/6000-aix is. and there is know easy way to find out if a process
+   is running 32 or 64 bits so we have this little hack.
+
+   EVEN MORE SHAMELESS HACK: rs6000-nat.c solves this problem by
+   expecting the first few ptracex() calls to fail.
+
+*/
+#include <sys/stat.h>
+#include "bfd/elf-bfd.h"
+static int
+ppc_wordsize_pid(pid_t pid)
+{
+  static ino_t fino = 0;
+  static int last = 0;
+  struct stat sb;
+  const char fmt[] = "/proc/%u/exe";
+  FILE *file;
+  char *fname = alloca (sizeof(fmt) + 10); /* 10 digit pid.. why not */
+  Elf_Internal_Ehdr elfh;
+
+  if ((gdbarch_tdep (current_gdbarch))->wordsize == 4)
+    return 4;
+
+  sprintf (fname, fmt, pid);
+
+  if (stat(fname, &sb) == -1)
+    {
+      internal_error (__FILE__, __LINE__,
+		      "could not stat executable from /proc.");
+      return 0;
+    }
+
+  if (fino == sb.st_ino)
+      return last;
+
+  fino = sb.st_ino;
+
+  /* FIXME: could stat the file and check if inode changed. */
+  file = fopen (fname, "rb");
+  if (file == NULL)
+    {
+      internal_error (__FILE__, __LINE__,
+		      "could not open executable from /proc.");
+      return 0;
+    }
+
+  if (fread (elfh.e_ident, EI_NIDENT, 1, file) == 1)
+    {
+      if (elfh.e_ident [EI_CLASS] == ELFCLASS64)
+	last = 8;
+      else
+	last = 4;
+    }
+  else
+    {
+      last = 0;
+      internal_error (__FILE__, __LINE__,
+		      "could not read executable from /proc.");
+    }
+  fclose (file);
+  
+  return last;
+}
+
 /* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a
    configure time check.  Some older glibc's (for instance 2.2.1)
    don't have a specific powerpc version of ptrace.h, and fall back on
@@ -105,7 +202,15 @@ int have_ptrace_getvrregs = 1;
 int
 kernel_u_size (void)
 {
-  return (sizeof (struct user));
+  if ((gdbarch_tdep (current_gdbarch))->wordsize == sizeof (PTRACE_XFER_TYPE))
+    return (sizeof (struct user));
+  else
+    {
+      /* with a 64-bit kernel, all members of struct user go from 32
+         to 64 bit except for the u_comm character array so we can
+         double everything and subtract sizeof u_comm. */
+      return ((sizeof (struct user) * 2) - sizeof (((struct user*)0)->u_comm));
+    }
 }
 
 /* *INDENT-OFF* */
@@ -125,33 +125,34 @@
 ppc_register_u_addr (int regno)
 {
   int u_addr = -1;
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  int wordsize = tdep->wordsize;
 
   /* General purpose registers occupy 1 slot each in the buffer */
   if (regno >= tdep->ppc_gp0_regnum && regno <= tdep->ppc_gplast_regnum )
-    u_addr =  ((PT_R0 + regno) * 4);
+    u_addr =  ((PT_R0 + regno) * wordsize);
 
   /* Floating point regs: 2 slots each */
   if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM)
-    u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4);
+    u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * wordsize);
 
   /* UISA special purpose registers: 1 slot each */
   if (regno == PC_REGNUM)
-    u_addr = PT_NIP * 4;
+    u_addr = PT_NIP * wordsize;
   if (regno == tdep->ppc_lr_regnum)
-    u_addr = PT_LNK * 4;
+    u_addr = PT_LNK * wordsize;
   if (regno == tdep->ppc_cr_regnum)
-    u_addr = PT_CCR * 4;
+    u_addr = PT_CCR * wordsize;
   if (regno == tdep->ppc_xer_regnum)
-    u_addr = PT_XER * 4;
+    u_addr = PT_XER * wordsize;
   if (regno == tdep->ppc_ctr_regnum)
-    u_addr = PT_CTR * 4;
+    u_addr = PT_CTR * wordsize;
   if (regno == tdep->ppc_mq_regnum)
-    u_addr = PT_MQ * 4;
+    u_addr = PT_MQ * wordsize;
   if (regno == tdep->ppc_ps_regnum)
-    u_addr = PT_MSR * 4;
+    u_addr = PT_MSR * wordsize;
   if (regno == tdep->ppc_fpscr_regnum)
-    u_addr = PT_FPSCR * 4;
+    u_addr = PT_FPSCR * wordsize;
 
   return u_addr;
 }
@@ -205,6 +322,16 @@ fetch_register (int tid, int regno)
   unsigned int offset;         /* Offset of registers within the u area. */
   char *buf = alloca (MAX_REGISTER_RAW_SIZE);
   CORE_ADDR regaddr = ppc_register_u_addr (regno);
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
+
+  /* Do the easy thing for now which is to silently succeed if we are
+     attached to a 32-bit process when we are expecting 64-bits */
+  if (wordsize != ppc_wordsize_pid(tid))
+    {
+      /* supplying garbage.. but that's ok */
+      supply_register (regno, buf);
+      return;
+    }
 
   if (altivec_register_p (regno))
     {
@@ -232,8 +359,19 @@ fetch_register (int tid, int regno)
   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
-					       (PTRACE_ARG3_TYPE) regaddr, 0);
+      if (wordsize != sizeof (PTRACE_XFER_TYPE))
+	{
+	  PTRACE_XFER_TYPE reg;
+	  ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
+		  (PTRACE_ARG3_TYPE) regaddr, &reg);
+	  *(PTRACE_XFER_TYPE *) & buf[i] = reg;
+	}
+      else
+      {
+	  *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
+						   (PTRACE_ARG3_TYPE) regaddr, 0);
+      }
+
       regaddr += sizeof (PTRACE_XFER_TYPE);
       if (errno != 0)
 	{
@@ -364,6 +452,7 @@ store_register (int tid, int regno)
   register int i;
   unsigned int offset;         /* Offset of registers within the u area.  */
   char *buf = alloca (MAX_REGISTER_RAW_SIZE);
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
 
   if (altivec_register_p (regno))
     {
@@ -378,8 +517,18 @@ store_register (int tid, int regno)
   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
-	      *(PTRACE_XFER_TYPE *) & buf[i]);
+      if (wordsize != sizeof (PTRACE_XFER_TYPE))
+	{
+	  PTRACE_XFER_TYPE reg;
+	  ptrace (PPC_PTRACE_POKEUSR_3264, tid, (PTRACE_ARG3_TYPE) regaddr,
+		  *(PTRACE_XFER_TYPE *) & buf[i]);
+	}
+      else
+      {
+	  ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+		  *(PTRACE_XFER_TYPE *) & buf[i]);
+      }
+
       regaddr += sizeof (PTRACE_XFER_TYPE);

       if (errno == EIO 
@@ -533,3 +682,243 @@ fill_fpregset (gdb_fpregset_t *fpregsetp
   if ((regno == -1) || regno == tdep->ppc_fpscr_regnum)
     regcache_collect (tdep->ppc_fpscr_regnum, (char *) (*fpregsetp + regi));
 }
+
+
+#ifdef CHILD_XFER_MEMORY
+
+/* this is a complete rip off from infptrace.c */
+
+#ifndef GDB_MAX_ALLOCA
+#define GDB_MAX_ALLOCA 0x1000
+#endif /* GDB_MAX_ALLOCA */
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR to
+   debugger memory starting at MYADDR.  Copy to inferior if WRITE is
+   nonzero.  TARGET is ignored.
+
+   Returns the length copied, which is either the LEN argument or
+   zero.  This xfer function does not do partial moves, since
+   child_ops doesn't allow memory operations to cross below us in the
+   target stack anyway.  */
+
+int
+child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+		   struct mem_attrib *attrib, struct target_ops *target)
+{
+    int i;
+  /* Round starting address down to longword boundary.  */
+    CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
+  /* Round ending address up; get number of longwords that makes.  */
+    int count = ((((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+		 / sizeof (PTRACE_XFER_TYPE));
+    int alloc = count * sizeof (PTRACE_XFER_TYPE);
+    PTRACE_XFER_TYPE *buffer;
+    struct cleanup *old_chain = NULL;
+    int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
+    int arch64 = ARCH64();
+
+  /* Allocate buffer of that many longwords.  */
+    if (len < GDB_MAX_ALLOCA)
+    {
+	buffer = (PTRACE_XFER_TYPE *) alloca (alloc);
+    }
+    else
+    {
+	buffer = (PTRACE_XFER_TYPE *) xmalloc (alloc);
+	old_chain = make_cleanup (xfree, buffer);
+    }
+
+  /* WARNING: from kernel source: "when I and D space are separate,
+     these will need to be fixed." */
+    if (write)
+    {
+      /* Fill start and end extra bytes of buffer with existing memory
+	 data.  */
+	if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE))
+	{
+	  /* Need part of initial word -- fetch it.  */
+	    if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	    {
+		buffer[0] = ptrace (PT_READ_I, PIDGET (inferior_ptid), 
+				    (PTRACE_ARG3_TYPE) addr, 0);
+	    }
+	    else
+	    {
+		if (arch64) {
+		    buffer[0] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid), 
+					(unsigned long) addr, 0);
+		}
+		else 
+		{
+		    ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid), 
+			    (PTRACE_ARG3_TYPE) &addr, buffer);
+		}
+	    }
+	}
+	if (count > 1)		/* FIXME, avoid if even boundary.  */
+	{
+	    CORE_ADDR a64 = (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE));
+	    if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	    {
+		buffer[count - 1] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
+					    (PTRACE_ARG3_TYPE) a64, 0);
+	    }
+	    else
+		if (arch64) {
+		    buffer[count-1] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid),
+					      (PTRACE_ARG3_TYPE) &a64, 0);
+		}
+		else
+		{
+		    ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid),
+			    (PTRACE_ARG3_TYPE) &a64, &buffer[count - 1]);
+		}
+	}
+
+      /* Copy data to be written over corresponding part of buffer.  */
+	memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+		myaddr, len);
+
+      /* Write the entire buffer.  */
+	for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+	{
+	    errno = 0;
+	    if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	    {
+		ptrace (PT_WRITE_D, PIDGET (inferior_ptid), 
+			(PTRACE_ARG3_TYPE) addr, buffer[i]);
+	    }
+	    else
+		if (arch64) {
+		    ptrace (PT_WRITE_D, PIDGET (inferior_ptid), 
+			    (unsigned long) addr, buffer[i]);  
+		}
+		else 
+		{
+		    ptrace (PPC_PTRACE_POKEDATA_3264, PIDGET (inferior_ptid), 
+			    (PTRACE_ARG3_TYPE) &addr, buffer[i]);
+		}
+	    if (errno)
+	    {
+		errno = 0;
+		if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+		{
+		    ptrace (PT_WRITE_I, PIDGET (inferior_ptid), 
+			    (PTRACE_ARG3_TYPE) addr, buffer[i]);
+		}
+		else
+		    if (arch64) {
+			ptrace (PTRACE_POKEDATA, PIDGET (inferior_ptid),  
+				(PTRACE_ARG3_TYPE) addr, buffer[i]); 
+		    }
+		    else 
+		    {
+			ptrace (PPC_PTRACE_POKEDATA_3264, PIDGET (inferior_ptid), 
+				(PTRACE_ARG3_TYPE) &addr, buffer[i]);
+		    }
+	    }
+	    if (errno)
+		return 0;
+	}
+#ifdef CLEAR_INSN_CACHE
+	    CLEAR_INSN_CACHE ();
+#endif
+    }
+  else
+  {
+      /* Read all the longwords.  */
+      for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+      {
+	  errno = 0;
+	  if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	  {
+	      buffer[i] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
+				  (PTRACE_ARG3_TYPE) addr, 0);
+	  }
+	  else
+	  {
+	      if (arch64) {
+		  buffer[i] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid),
+				      (unsigned long) addr, 0);
+	      }
+	      else
+	      {
+		  ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid),
+			  (PTRACE_ARG3_TYPE) &addr, &buffer[i]);
+	      }
+	      if (errno)
+		  return 0;
+	      QUIT;
+	  }
+
+      /* Copy appropriate bytes out of the buffer.  */
+	  memcpy (myaddr,
+		  (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+		  len);
+      }
+  }
+  if (old_chain != NULL)
+    do_cleanups (old_chain);
+  return len;
+    }
+
+\f
+/* Did not want to add this originally since the kernel will give us a
+   lot of gargabe (and would probably fail if it wasn't for the
+   FPU's). But at least you can get the other registers in struct
+   pt_regs.  Perhaps we can get the kernels to co-operate. */
+static void
+udot_info (char *dummy1, int dummy2)
+{
+  int udot_off;			/* Offset into user struct */
+  int udot_val;			/* Value from user struct at udot_off */
+  char mess[128];		/* For messages */
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
+
+  if (!target_has_execution)
+    {
+      error ("The program is not being run.");
+    }
+
+  for (udot_off = 0; udot_off < KERNEL_U_SIZE; udot_off += sizeof (udot_val))
+    {
+      if ((udot_off % 24) == 0)
+	{
+	  if (udot_off > 0)
+	    {
+	      printf_filtered ("\n");
+	    }
+	  printf_filtered ("%04x:", udot_off);
+	}
+      if (wordsize != sizeof (PTRACE_XFER_TYPE))
+	{
+	  PTRACE_XFER_TYPE reg;
+	  /* ptrace will place contents in "data" pointer */
+	  ptrace (PPC_PTRACE_PEEKUSR_3264, PIDGET (inferior_ptid),
+		  (PTRACE_ARG3_TYPE) udot_off, &reg);
+	  udot_val = reg;
+	}
+      else
+	udot_val = ptrace (PT_READ_U, PIDGET (inferior_ptid),
+			   (PTRACE_ARG3_TYPE) udot_off, 0);
+      if (errno != 0)
+	{
+	  sprintf (mess, "\nreading user struct at offset 0x%x", udot_off);
+	  perror_with_name (mess);
+	}
+      /* Avoid using nonportable (?) "*" in print specs */
+      printf_filtered (sizeof (int) == 4 ? " 0x%08x" : " 0x%16x", udot_val);
+    }
+  printf_filtered ("\n");
+}
+#endif /* CHILD_XFER_MEMORY */
+
+#include "command.h"
+void
+_initialize_ppc_linux_nat (void)
+{
+#ifdef CHILD_XFER_MEMORY
+  add_info ("udot", udot_info,
+	    "Print contents of kernel ``struct user'' for current child.");
+#endif
+}
diff -rupPN gdb-5.2.1/gdb/ppc-linux-tdep.c src.ppc64/gdb/ppc-linux-tdep.c
--- gdb-5.2.1/gdb/ppc-linux-tdep.c	2002-02-24 16:31:19.000000000 -0600
+++ src.ppc64/gdb/ppc-linux-tdep.c	2003-01-28 13:28:24.000000000 -0600
@@ -57,6 +57,8 @@
    offsetof(struct sigcontext_struct, handler) == 0x14 */
 #define PPC_LINUX_HANDLER_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x14)
 
+#define TDEP	gdbarch_tdep (current_gdbarch)
+	
 /* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */
 #define PPC_LINUX_PT_R0		0
 #define PPC_LINUX_PT_R1		1
@@ -730,3 +732,64 @@ _initialize_ppc_linux_tdep (void)
 			  ppc_linux_init_abi);
   add_core_fns (&ppc_linux_regset_core_fns);
 }
+
+struct link_map_offsets *
+	ppc64_linux_svr4_fetch_link_map_offsets (void)
+{
+    static struct link_map_offsets lmo;
+    static struct link_map_offsets *lmp = NULL;
+
+    if (lmp == NULL)
+    {
+	lmp = &lmo;
+
+	lmo.r_debug_size = 16;/* The actual size is xx bytes, but
+					   this is all we need.  */
+	lmo.r_map_offset = 8;
+	lmo.r_map_size   = 8; 
+	lmo.link_map_size = 40;  /* The actual size is xxx bytes, but
+					   this is all we need.  */
+	lmo.l_addr_offset = 0;
+	lmo.l_addr_size   = 8;
+	lmo.l_name_offset = 8; 
+	lmo.l_name_size   = 8;
+	lmo.l_next_offset = 24;
+	lmo.l_next_size   = 8;
+	lmo.l_prev_offset = 32;
+	lmo.l_prev_size   = 8;
+    }
+
+    return lmp;
+}
+
+
+/* Support for CONVERT_FROM_FUNC_PTR_ADDR(ADDR).
+	   Duplicate of RS6000 function, except ppc64_linux requires relocated address. */
+static CORE_ADDR
+read_memory_addr (CORE_ADDR memaddr, int len)
+{
+    return read_memory_unsigned_integer (memaddr, len);
+}
+	
+	
+CORE_ADDR
+ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr)
+{
+    long long my_adder;
+    struct obj_section *s;
+    CORE_ADDR retval;
+    extern struct obj_section *find_pc_section(CORE_ADDR);
+
+	/* this should be the base address that the object (containing the func_ptr_addr) is loaded at. */
+    my_adder = 0x7fe0000000; 
+
+    s = find_pc_section (my_adder + addr);
+    if (s && s->the_bfd_section->flags & SEC_CODE)
+	return addr;
+
+	  /* ADDR is in the data space, so it's a special function pointer. */
+    retval = read_memory_addr (my_adder + addr, TDEP->wordsize);
+	/*  printf("reading 0x%lx ",my_adder+addr); */
+	/*  printf("ppc64...convert_func_ptr addr:0x%lx  new:0x%lx\n",addr,retval); */
+    return retval;
+}
diff -rupPN gdb-5.2.1/gdb/ppc64-linux-tdep.c src.ppc64/gdb/ppc64-linux-tdep.c
--- gdb-5.2.1/gdb/ppc64-linux-tdep.c	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/ppc64-linux-tdep.c	2003-01-28 13:28:24.000000000 -0600
@@ -0,0 +1,80 @@
+/* Target-dependent code for GDB, the GNU debugger.
+
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   2000, 2001 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"
+
+
+/* These elfcore fuctions are defined in libbfd.a but only when host
+   == target, once we can convince the bfd to supply it these can go */
+#define _SYSCALL32
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#define ARCH_SIZE 0
+#include "elf-bfd.h"
+#include "libiberty.h"
+#include <sys/procfs.h>
+
+
+/*
+ * Initialization
+ */
+void
+_initialize_ppc64_linux_tdep (void)
+{
+  /* hardware/kernel supports single stepping */
+  set_gdbarch_software_single_step (current_gdbarch, NULL);
+}
+
+/* the start_address stored in the bfd is a function descriptor */
+#include "gdb/target.h"
+CORE_ADDR
+ppc64_bfd_get_start_address (bfd *abfd)
+{
+  extern struct target_ops exec_ops;
+  CORE_ADDR myaddr;
+  xfer_memory(abfd->start_address, (char *)&myaddr, 8, 0, 0, &exec_ops);
+  return myaddr;
+}
+
+/* Fetch (and possibly build) an appropriate link_map_offsets
+   structure for GNU/Linux PPC targets using the struct offsets
+   defined in link.h (but without actual reference to that file).
+
+   This makes it possible to access GNU/Linux PPC shared libraries
+   from a GDB that was not built on an GNU/Linux PPC host (for cross
+   debugging).
+
+*/
+#include "gdbcore.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+#include "ppc-tdep.h"
+#define TDEP	gdbarch_tdep (current_gdbarch)
+
+static CORE_ADDR
+read_memory_addr (CORE_ADDR memaddr, int len)
+{
+  return read_memory_unsigned_integer (memaddr, len);
+}
diff -rupPN gdb-5.2.1/gdb/rs6000-tdep.c src.ppc64/gdb/rs6000-tdep.c
--- gdb-5.2.1/gdb/rs6000-tdep.c	2002-04-01 00:01:46.000000000 -0600
+++ src.ppc64/gdb/rs6000-tdep.c	2003-01-28 13:28:24.000000000 -0600
@@ -513,13 +508,13 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 
       if ((op & 0xfc1fffff) == 0x7c0802a6)
 	{			/* mflr Rx */
-	  lr_reg = (op & 0x03e00000) | 0x90010000;
+	  lr_reg = (op & 0x03e00000);
 	  continue;
 
 	}
       else if ((op & 0xfc1fffff) == 0x7c000026)
 	{			/* mfcr Rx */
-	  cr_reg = (op & 0x03e00000) | 0x90010000;
+	  cr_reg = (op & 0x03e00000);
 	  continue;
 
 	}
@@ -545,7 +540,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 	    {
 	      fdata->saved_gpr = reg;
 	      if ((op & 0xfc1f0003) == 0xf8010000)
-		op = (op >> 1) << 1;
+		op &= ~3UL;
 	      fdata->gpr_offset = SIGNED_SHORT (op) + offset;
 	    }
 	  continue;
@@ -577,19 +572,49 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 	  continue;
 
 	}
-      else if (lr_reg != -1 && (op & 0xffff0000) == lr_reg)
-	{			/* st Rx,NUM(r1) 
-				   where Rx == lr */
-	  fdata->lr_offset = SIGNED_SHORT (op) + offset;
+      else if (lr_reg != -1 &&
+	       /* std Rx || stdu Rx */
+	       (((op & 0xffff0000) == (lr_reg | 0xf8010000)) ||
+		/* stw Rx */
+		((op & 0xffff0000) == (lr_reg | 0x90010000)) ||
+		/* stwu Rx */
+		((op & 0xffff0000) == (lr_reg | 0x94010000))))
+	{	/* where Rx == lr */
+	  fdata->lr_offset = offset;
 	  fdata->nosavedpc = 0;
 	  lr_reg = 0;
+	  if ((op & 0xfc000003) == 0xf8000000 ||	/* std Rx */
+	      (op & 0xfc000000) == 0x90000000)		/* stw Rx */
+	    {
+	      /* does not update r1 add d to lr_offset */
+	      fdata->lr_offset = SIGNED_SHORT (op);
+	    }
 	  continue;
 
 	}
-      else if (cr_reg != -1 && (op & 0xffff0000) == cr_reg)
-	{			/* st Rx,NUM(r1) 
+      else if (cr_reg != -1 &&
+	       /* std Rx || stdu Rx */
+	       (((op & 0xffff0000) == (cr_reg | 0xf8010000)) ||
+		/* stw Rx */
+		((op & 0xffff0000) == (cr_reg | 0x90010000)) ||
+		/* stwu Rx */
+		((op & 0xffff0000) == (cr_reg | 0x94010000))))
+	{	/* where Rx == cr */
+	  fdata->cr_offset = offset;
+	  cr_reg = 0;
+	  if ((op & 0xfc000003) == 0xf8000000 ||
+	      (op & 0xfc000000) == 0x90000000)
+	    {
+	      /* does not update r1 add d to cr_offset */
+	      fdata->cr_offset += SIGNED_SHORT (op);
+	    }
+	  continue;
+
+	}
+      else if (cr_reg != -1 && (op & 0xffff0003) == cr_reg)
+	{			/* std Rx,NUM(r1) || stdu Rx,NUM(r1) 
 				   where Rx == cr */
-	  fdata->cr_offset = SIGNED_SHORT (op) + offset;
+	  fdata->cr_offset = SIGNED_SHORT (op & ~3UL) + offset;
 	  cr_reg = 0;
 	  continue;
 
@@ -634,30 +658,41 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 				   this branch */
 	  continue;
 
-	  /* update stack pointer */
 	}
-      else if ((op & 0xffff0000) == 0x94210000 ||	/* stu r1,NUM(r1) */
-	       (op & 0xffff0003) == 0xf8210001)		/* stdu r1,NUM(r1) */
-	{
+      /* update stack pointer */
+      else if ((op & 0xfc1f0000) == 0x94010000)
+	{		/* stu rX,NUM(r1) ||  stwu rX,NUM(r1) */
 	  fdata->frameless = 0;
-	  if ((op & 0xffff0003) == 0xf8210001)
-	    op = (op >> 1) << 1;
 	  fdata->offset = SIGNED_SHORT (op);
 	  offset = fdata->offset;
 	  continue;
-
 	}
-      else if (op == 0x7c21016e)
-	{			/* stwux 1,1,0 */
+      else if ((op & 0xfc1f016a) == 0x7c01016e)
+	{			/* stwux rX,r1,rY */
+	  /* no way to figure out what r1 is going to be */
+	  fdata->frameless = 0;
+	  offset = fdata->offset;
+	  continue;
+	}
+      else if ((op & 0xfc1f0003) == 0xf8010001)
+	{			/* stdu rX,NUM(r1) */
+	  fdata->frameless = 0;
+	  fdata->offset = SIGNED_SHORT (op & ~3UL);
+	  offset = fdata->offset;
+	  continue;
+	}
+      else if ((op & 0xfc1f016a) == 0x7c01016a)
+	{			/* stdux rX,r1,rY */
+	  /* no way to figure out what r1 is going to be */
 	  fdata->frameless = 0;
 	  offset = fdata->offset;
 	  continue;
-
-	  /* Load up minimal toc pointer */
 	}
-      else if ((op >> 22) == 0x20f
+      /* Load up minimal toc pointer */
+      else if (((op >> 22) == 0x20f	||	/* l r31,... or l r30,... */
+	       (op >> 22) == 0x3af)		/* ld r31,... or ld r30,... */
 	       && !minimal_toc_loaded)
-	{			/* l r31,... or l r30,... */
+	{
 	  minimal_toc_loaded = 1;
 	  continue;
 
@@ -2439,6 +2483,44 @@ static const struct reg registers_7400[]
   /* FIXME? Add more registers? */
 };
 
+
+/* PowerPC UISA - a PPC64 processor as viewed by user-level code. */
+/* Should be able to use the common registers_powerpc[] here, however
+   it does not define an fpscr, though both linux and aix get one from
+   ptrace(). Can only assume that there is a 32-bit core our there
+   that does not have an fpscr.  I think we can assert that all 64-bit
+   cores do. */
+static const struct reg registers_powerpc64[] =
+{
+  COMMON_UISA_REGS,
+  /* SPRs */
+  /*  66 */ R4(cr), R(lr), R(ctr), R4(xer),
+  /*  70 */ R4(fpscr), R0 /* mq? */
+};
+
+static const struct reg registers_a35[] =
+{
+  COMMON_UISA_REGS,
+  /* SPRs */
+  /*  66 */ R4(cr), R(lr), R(ctr), R4(xer),
+  /*  70 */ R4(fpscr), R0 /* mq? */,
+  /*  72 */ R(dabr), R(iabr), R4(dsisr),
+  /*  75 */ R(dar), R4(dec), R(sdr1), R(srr0), R(srr1),
+  /*  80 */ R(sprg0), R(sprg1), R(sprg2), R(sprg3),
+  /*  84 */ R64(asr), R4(ear), R4(tbl), R4(tbu),
+  /*  88 */ R(ibat0u), R(ibat0l), R(ibat1u), R(ibat1l),
+  /*  92 */ R(ibat2u), R(ibat2l), R(ibat3u), R(ibat3l),
+  /*  96 */ R(dbat0u), R(dbat0l), R(dbat1u), R(dbat1l),
+  /* 100 */ R(dbat2u), R(dbat2l), R(dbat3u), R(dbat3l),
+  /* 104 */ R(pir), R4(mmcr0),
+  /* 106..121 segment regs 0..15 */ 
+  /* 106 */ R(sr0), R(sr1), R(sr2), R(sr3),
+  /* 110 */ R(sr4), R(sr5), R(sr6), R(sr7),
+  /* 114 */ R(sr8), R(sr9), R(sr10), R(sr11),
+  /* 118 */ R(sr12), R(sr13), R(sr14), R(sr15),
+  /* 122 */ R4(pvr) /* processor version register */
+};
+
 /* Motorola e500.  */
 static const struct reg registers_e500[] =
 {
@@ -2947,6 +3051,15 @@ rs6000_gdbarch_init (struct gdbarch_info
          descriptors).  */
       set_gdbarch_convert_from_func_ptr_addr (gdbarch,
 	rs6000_convert_from_func_ptr_addr);
+
+      /* wordsize 8, ppc64 linux  functions */
+      if (osabi == ELFOSABI_LINUX)
+      {
+	  set_solib_svr4_fetch_link_map_offsets
+	    (gdbarch, ppc64_linux_svr4_fetch_link_map_offsets);
+	  set_gdbarch_convert_from_func_ptr_addr
+            (gdbarch, ppc64_linux_convert_from_func_ptr_addr);
+      }
     }
   set_gdbarch_frame_args_address (gdbarch, rs6000_frame_args_address);
   set_gdbarch_frame_locals_address (gdbarch, rs6000_frame_args_address);

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

* Re: [PATCH]  new support for PPC64 architecture
  2003-04-17 22:44 [PATCH] new support for PPC64 architecture Will Schmidt
  2003-05-07 20:14 ` Andrew Cagney
@ 2003-05-07 20:37 ` Elena Zannoni
  2003-05-07 20:46   ` Daniel Jacobowitz
  2003-05-09 21:05 ` Jim Blandy
  2003-05-13 22:33 ` Jim Blandy
  3 siblings, 1 reply; 8+ messages in thread
From: Elena Zannoni @ 2003-05-07 20:37 UTC (permalink / raw)
  To: Will Schmidt; +Cc: gdb-patches, will_schmidt, Elena Zannoni

Will Schmidt writes:
 > All,
 > 
 >    This patch contains code that provides support for GDB on the PPC64
 > architecture.     This patch will apply clean on top of the RedHat
 > gdb-5.3post-0.20021129.29.src.rpm.         (A patch against CVS will
 > happen, but not today.. )
 > 
 > 
 > (See attached file: gdb-5.3post-ppc64-support.patch)
 > 
 > 
 > -Will
 > 
 > 
 > Will Schmidt
 > willschm@us.ibm.com     will_schmidt@vnet.ibm.com
 > Linux on PowerPC-64 Development
 > IBM Rochester

A few comments/questions.  You need changelogs, and the proper
copyright verbiage in the new files you are adding. The code needs to
conform to gnu coding standards as fas as spaces, indentation,
etc. You can run the new files through gdb_indent.sh to get the right
format. Comments should start with a capital letter, be full
sentences, and end with a period followed by 2 spaces.

see below.....

diff -rupPN gdb-5.2.1/gdb/config/powerpc/ppc64linux.mh src.ppc64/gdb/config/powerpc/ppc64linux.mh
--- gdb-5.2.1/gdb/config/powerpc/ppc64linux.mh	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/ppc64linux.mh	2003-03-05 13:00:33.000000000 -0600
@@ -0,0 +1,14 @@
+# Host: PowerPC, running Linux
+
+XM_FILE= xm-linux.h
+XM_CLIBS=
+
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o linux-proc.o \
+	core-regset.o ppc-linux-nat.o proc-service.o thread-db.o lin-lwp.o  \
+	gcore.o ppc-sysv-tdep.o
+

this is the host makefile fragment, the *tdep.o files should be
included in the target makefile fragment, the .mt file, not here.
Actually if you exclude the .o's that ashould really be in the mt
file, then this file becomes almost identical to the linux.mh
file. Which makes me wonder if we really need a new file.

+LOADLIBES = -ldl -lthread_db
+

Why include thread_db? I don't see any other config files doing that.

+GDBSERVER_DEPFILES= low-linux.o

it is linux-low.o

+GDBSERVER_LIBS= -lnss_dns  -lnss_files -lresolv





diff -rupPN gdb-5.2.1/gdb/config/powerpc/ppc64linux.mt src.ppc64/gdb/config/powerpc/ppc64linux.mt
--- gdb-5.2.1/gdb/config/powerpc/ppc64linux.mt	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/ppc64linux.mt	2003-03-05 16:32:12.000000000 -0600
@@ -0,0 +1,4 @@
+# Target: PPC running Linux 64bit programs
+TDEPFILES= rs6000-tdep.o ppc-linux-tdep.o ppc64-linux-tdep.o solib.o solib-svr4.o solib-legacy.o 

corelow?

+TM_FILE= tm-ppc64linux.h
+




diff -rupPN gdb-5.2.1/gdb/solib-svr4.c src.ppc64/gdb/solib-svr4.c
--- gdb-5.2.1/gdb/solib-svr4.c	2002-02-05 17:28:13.000000000 -0600
+++ src.ppc64/gdb/solib-svr4.c	2003-01-28 13:28:24.000000000 -0600
@@ -75,6 +75,9 @@ struct lm_info
 
 static char *solib_break_names[] =
 {
+#if defined (SOLIB_BREAK_NAME)
+  SOLIB_BREAK_NAME,
+#endif

Caouldn't the new name just be added to the list w/o this ifdef? All
of these names are looked for into the executable, if one is not
found, it will try the next.

   "r_debug_state",
   "_r_debug_state",
   "_dl_debug_state",
@@ -998,7 +1001,7 @@ enable_break (void)
 	 the current pc (which should point at the entry point for the
 	 dynamic linker) and subtracting the offset of the entry point.  */
       if (!load_addr_found)
-	load_addr = read_pc () - tmp_bfd->start_address;
+	load_addr = read_pc () - CONVERT_FROM_FUNC_PTR_ADDR(tmp_bfd->start_address);
 



       /* Record the relocated start and end address of the dynamic linker
          text and plt section for svr4_in_dynsym_resolve_code.  */




diff -rupPN gdb-5.2.1/gdb/config/powerpc/tm-linux.h src.ppc64/gdb/config/powerpc/tm-linux.h
--- gdb-5.2.1/gdb/config/powerpc/tm-linux.h	2002-02-24 16:56:06.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/tm-linux.h	2003-01-28 13:28:24.000000000 -0600
@@ -67,4 +67,9 @@ extern int ppc_linux_in_sigtramp (CORE_A
    to be relocated. */
 #define SOFUN_ADDRESS_MAYBE_MISSING
 
+/* used for ppc64 only, but added here because code is common between ppc and ppc64 */
+struct link_map_offsets *ppc64_linux_svr4_fetch_link_map_offsets (void);
+extern CORE_ADDR ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr);
+
+
 #endif  /* #ifndef TM_LINUX_H */


diff -rupPN gdb-5.2.1/gdb/config/powerpc/tm-ppc64linux.h src.ppc64/gdb/config/powerpc/tm-ppc64linux.h
--- gdb-5.2.1/gdb/config/powerpc/tm-ppc64linux.h	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/config/powerpc/tm-ppc64linux.h	2003-01-28 13:28:24.000000000 -0600
@@ -0,0 +1,80 @@
+#ifndef TM_PPC64LINUX_H
+#define TM_PPC64LINUX_H
+
+#include "rs6000/tm-rs6000.h"
+
+/* Avoid warning from redefinition in tm-sysv4.h (included from tm-linux.h) */
+#undef SKIP_TRAMPOLINE_CODE
+#include "tm-linux.h"


+
+#include "gdbarch.h"
+/* Reset these back to the default.  Should really fix this for other
+   powerpc tm.h so it can be chosen at runtime  */
+#undef SOFTWARE_SINGLE_STEP_P
+#define SOFTWARE_SINGLE_STEP_P() (gdbarch_software_single_step_p (current_gdbarch))
+#undef SOFTWARE_SINGLE_STEP
+#define SOFTWARE_SINGLE_STEP(sig, insert_breakpoints_p) (gdbarch_software_single_step (current_gdbarch, sig, insert_breakpoints_p))
+

why this? In the current tm-linux.h it is defined to generate an
internal_error.

+#ifdef DEAD_CODE
+/* FIXME: tm-linux defines this which a dead interface, as far as I
+   can tell. The macro is unused and there is no definition for the
+   function the macro calls. It is here so we know to get rid of it
+   there. */
+/* Make sure nexti gets the help it needs for debugging assembly code
+   without symbols */
+
+#define AT_SUBROUTINE_CALL_INSTRUCTION_TARGET(prevpc,stoppc) \
+   at_subroutine_call_instruction_target(prevpc,stoppc)
+extern int at_subroutine_call_instruction_target();
+#endif /* DEAD_CODE */

delete this dead code.

+
+/* We _want_ the SVR4 section offset calculations (see syms_from_objfile()
+   in symfile.c) */
+#undef IBM6000_TARGET
+
+/* Default offset from SP where the LR is stored */
+#undef DEFAULT_LR_SAVE
+#define	DEFAULT_LR_SAVE 16
+
+/* Say that we're using ELF, not XCOFF.  */
+#define ELF_OBJECT_FORMAT 1
+
+/* Say that we're using ELF64 since ABI is closer to XCOFF64. */
+#define ELF64_OBJECT_FORMAT 1
+
+#undef PROCESS_LINENUMBER_HOOK
+
+#undef TEXT_SEGMENT_BASE
+#define TEXT_SEGMENT_BASE 1
+

hmm do we need this?


+/* don't think it is but it can't hurt (can it?) */
+#define TARGET_BYTE_ORDER_SELECTABLE_P 1
+

the above macro is gone from the gdb sources since Jan 2002.


+/* The value of symbols of type N_SO and N_FUN maybe null when 
+   it shouldn't be. */
+#define SOFUN_ADDRESS_MAYBE_MISSING
+
+#undef CHILD_SPECIAL_WAITSTATUS
+

Do we need to worry at all about CHILD_SPECIAL_WAITSTATUS?


+/* Use generic shared library machinery.  */
+#include "solib.h"
+
+/* function entrypoints have a '.' prepended to them (elfread.c) */
+#define DROP_TEXT_NAME_PREFIX_CHAR '.'
+/* skip data symbols if they are from the .opd section (elfread.c) */
+#define SKIP_DATA_IN_OPD
+

please explain the need for the above 2 macros. 

+/* define our own child_xfer_memory() ppc-linux-nat.c */
+#define CHILD_XFER_MEMORY
+



+#undef bfd_get_start_address
+#define bfd_get_start_address(abfd) ppc64_bfd_get_start_address (abfd)
+extern  CORE_ADDR ppc64_bfd_get_start_address (bfd *);
+struct link_map_offsets *ppc64_linux_svr4_fetch_link_map_offsets (void);
+extern CORE_ADDR ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr);
+
+/* define additional name for solib functions (solib-svr4.c) to hinge on. */
+#define SOLIB_BREAK_NAME "._dl_debug_state"
+
+
+#endif  /* #ifndef TM_PPC64LINUX_H */


diff -rupPN gdb-5.2.1/gdb/configure.host src.ppc64/gdb/configure.host
--- gdb-5.2.1/gdb/configure.host	2002-03-01 12:35:23.000000000 -0600
+++ src.ppc64/gdb/configure.host	2003-01-28 13:28:24.000000000 -0600
@@ -136,6 +136,8 @@ powerpc-*-aix*)		gdb_host=aix ;;
 powerpc-*-linux*)	gdb_host=linux ;;
 powerpc-*-netbsd*)	gdb_host=nbsd ;;
 
+powerpc64-*-linux*)	gdb_host=ppc64linux ;;
+
 rs6000-*-lynxos*)	gdb_host=rs6000lynx ;;
 rs6000-*-aix4*)		gdb_host=aix4 ;;
 rs6000-*-*)		gdb_host=rs6000 ;;
diff -rupPN gdb-5.2.1/gdb/configure.tgt src.ppc64/gdb/configure.tgt
--- gdb-5.2.1/gdb/configure.tgt	2002-05-28 21:36:55.000000000 -0500
+++ src.ppc64/gdb/configure.tgt	2003-01-28 13:28:24.000000000 -0600
@@ -222,6 +222,15 @@ powerpcle-*-eabi* | powerpcle-*-sysv* | 
 powerpc-*-linux*)	gdb_target=linux
 			build_gdbserver=yes
 			;;
+powerpc64-*-linux*)	gdb_target=ppc64linux
+			###HACK -JX
+			case "${host}" in
+			powerpc-*-linux*)
+			  ## This host can treat target as native
+			  nativefile=nm-linux.h
+			  ;;
+			esac
+			;;
 powerpc-*-vxworks*)	gdb_target=vxworks ;;
 powerpc*-*-*)		if test -f ../sim/ppc/Makefile; then
 			  gdb_target=ppc-sim

diff -rupPN gdb-5.2.1/gdb/elfread.c src.ppc64/gdb/elfread.c
--- gdb-5.2.1/gdb/elfread.c	2002-03-25 10:50:20.000000000 -0600
+++ src.ppc64/gdb/elfread.c	2003-01-28 13:28:24.000000000 -0600
@@ -154,6 +154,12 @@ record_minimal_symbol_and_info (char *na
   if (ms_type == mst_text || ms_type == mst_file_text)
     address = SMASH_TEXT_ADDRESS (address);
 
+#ifdef DROP_TEXT_NAME_PREFIX_CHAR
+  if ((ms_type == mst_text || ms_type == mst_file_text)
+      && name[0] == DROP_TEXT_NAME_PREFIX_CHAR)
+    ++name;
+#endif /* DROP_TEXT_NAME_PREFIX_CHAR */
+


can you explain why this is needed? Do we really have names starting
with '.', using gcc?


   return prim_record_minimal_symbol_and_info
     (name, address, ms_type, info, bfd_section->index, bfd_section, objfile);
 }
@@ -376,6 +382,10 @@ elf_symtab_read (struct objfile *objfile
 		    {
 		      if (sym->section->flags & SEC_LOAD)
 			{
+#ifdef SKIP_DATA_IN_OPD
+			  if (strcmp(sym->section->name, ".opd") == 0)
+			    continue;
+#endif /* SKIP_DATA_IN_OPD */
 			  ms_type = mst_data;
 			}
 		      else
@@ -455,6 +465,10 @@ elf_symtab_read (struct objfile *objfile
 		         symbol processing. */
 		      if (sym->section->flags & SEC_LOAD)
 			{
+#ifdef SKIP_DATA_IN_OPD
+			  if (strcmp(sym->section->name, ".opd") == 0)
+			    continue;
+#endif /* SKIP_DATA_IN_OPD */
 			  ms_type = mst_file_data;
 			}
 		      else


diff -rupPN gdb-5.2.1/gdb/ppc-linux-nat.c src.ppc64/gdb/ppc-linux-nat.c
--- gdb-5.2.1/gdb/ppc-linux-nat.c	2002-02-21 16:04:46.000000000 -0600
+++ src.ppc64/gdb/ppc-linux-nat.c	2003-01-28 13:28:24.000000000 -0600
@@ -47,11 +47,108 @@
 #define PT_WRITE_U PTRACE_POKEUSR
 #endif
 
-/* Default the type of the ptrace transfer to int.  */
+/* Default the type of the ptrace transfer to long.  */
 #ifndef PTRACE_XFER_TYPE
-#define PTRACE_XFER_TYPE int
+#define PTRACE_XFER_TYPE long
 #endif
 
+/* Write DATA into location ADDR within the "user area" on a 64-bit
+   process from a 32-bit process. */
+#ifndef PPC_PTRACE_POKEUSR_3264
+#define PPC_PTRACE_POKEUSR_3264   0x90 
+#endif
+
+/* Read a register (specified by ADDR) out of the "user area" on a
+   64-bit process from a 32-bit process. */
+#ifndef PPC_PTRACE_PEEKUSR_3264
+#define PPC_PTRACE_PEEKUSR_3264   0x91
+#endif
+
+/* Write word at location ADDR on a 64-bit process from a 32-bit process. */
+#ifndef PPC_PTRACE_POKEDATA_3264
+#define PPC_PTRACE_POKEDATA_3264   0x92
+#endif
+
+/* Read word at location ADDR on a 64-bit process from a 32-bit
+   process. */
+#ifndef PPC_PTRACE_PEEKDATA_3264
+#define PPC_PTRACE_PEEKDATA_3264   0x94
+#endif
+

shouldn't these come from some include file? Should there be a
configure time check to see if the glibc include fles have such ptrace
flag? 

+#define ARCH64() (REGISTER_RAW_SIZE (0) == 8)
+

ulgh, can't you use tdep->wordsize instead?

+/* REALLY SHAMELESS HACK:
+
+   32 bit programs can exec 64 bit programs and so forth. GDB launches
+   the inferior process by lauching ${SHELL} -c <program and args>.
+   Fortunately, we know that it only tries to get the PC so we only
+   have to hack that.. I THINK.
+
+   At this time we are not ready to unify ppc32 and ppc64 as
+   rs/6000-aix is. and there is know easy way to find out if a process
+   is running 32 or 64 bits so we have this little hack.
+
+   EVEN MORE SHAMELESS HACK: rs6000-nat.c solves this problem by
+   expecting the first few ptracex() calls to fail.
+
+*/
+#include <sys/stat.h>
+#include "bfd/elf-bfd.h"
+static int
+ppc_wordsize_pid(pid_t pid)
+{
+  static ino_t fino = 0;
+  static int last = 0;
+  struct stat sb;
+  const char fmt[] = "/proc/%u/exe";
+  FILE *file;
+  char *fname = alloca (sizeof(fmt) + 10); /* 10 digit pid.. why not */
+  Elf_Internal_Ehdr elfh;
+
+  if ((gdbarch_tdep (current_gdbarch))->wordsize == 4)
+    return 4;
+
+  sprintf (fname, fmt, pid);
+
+  if (stat(fname, &sb) == -1)
+    {
+      internal_error (__FILE__, __LINE__,
+		      "could not stat executable from /proc.");
+      return 0;
+    }
+
+  if (fino == sb.st_ino)
+      return last;
+
+  fino = sb.st_ino;
+
+  /* FIXME: could stat the file and check if inode changed. */
+  file = fopen (fname, "rb");
+  if (file == NULL)
+    {
+      internal_error (__FILE__, __LINE__,
+		      "could not open executable from /proc.");
+      return 0;
+    }
+
+  if (fread (elfh.e_ident, EI_NIDENT, 1, file) == 1)
+    {
+      if (elfh.e_ident [EI_CLASS] == ELFCLASS64)
+	last = 8;
+      else
+	last = 4;
+    }


maybe I am missing something here, but there is already an identical test in
rs6000 tdep.c (around line 2074):
  else if (from_elf_exec)
    {
      if (elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64)
	wordsize = 8;
      else
	wordsize = 4;
    }


+  else
+    {
+      last = 0;
+      internal_error (__FILE__, __LINE__,
+		      "could not read executable from /proc.");
+    }
+  fclose (file);
+  
+  return last;
+}
+
 /* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a
    configure time check.  Some older glibc's (for instance 2.2.1)
    don't have a specific powerpc version of ptrace.h, and fall back on
@@ -105,7 +202,15 @@ int have_ptrace_getvrregs = 1;
 int
 kernel_u_size (void)
 {
-  return (sizeof (struct user));
+  if ((gdbarch_tdep (current_gdbarch))->wordsize == sizeof (PTRACE_XFER_TYPE))
+    return (sizeof (struct user));
+  else
+    {
+      /* with a 64-bit kernel, all members of struct user go from 32
+         to 64 bit except for the u_comm character array so we can
+         double everything and subtract sizeof u_comm. */
+      return ((sizeof (struct user) * 2) - sizeof (((struct user*)0)->u_comm));
+    }
 }
 
 /* *INDENT-OFF* */
@@ -125,33 +125,34 @@
 ppc_register_u_addr (int regno)
 {
   int u_addr = -1;
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  int wordsize = tdep->wordsize;
 
   /* General purpose registers occupy 1 slot each in the buffer */
   if (regno >= tdep->ppc_gp0_regnum && regno <= tdep->ppc_gplast_regnum )
-    u_addr =  ((PT_R0 + regno) * 4);
+    u_addr =  ((PT_R0 + regno) * wordsize);
 
   /* Floating point regs: 2 slots each */
   if (regno >= FP0_REGNUM && regno <= FPLAST_REGNUM)
-    u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * 4);
+    u_addr = ((PT_FPR0 + (regno - FP0_REGNUM) * 2) * wordsize);
 
   /* UISA special purpose registers: 1 slot each */
   if (regno == PC_REGNUM)
-    u_addr = PT_NIP * 4;
+    u_addr = PT_NIP * wordsize;
   if (regno == tdep->ppc_lr_regnum)
-    u_addr = PT_LNK * 4;
+    u_addr = PT_LNK * wordsize;
   if (regno == tdep->ppc_cr_regnum)
-    u_addr = PT_CCR * 4;
+    u_addr = PT_CCR * wordsize;
   if (regno == tdep->ppc_xer_regnum)
-    u_addr = PT_XER * 4;
+    u_addr = PT_XER * wordsize;
   if (regno == tdep->ppc_ctr_regnum)
-    u_addr = PT_CTR * 4;
+    u_addr = PT_CTR * wordsize;
   if (regno == tdep->ppc_mq_regnum)
-    u_addr = PT_MQ * 4;
+    u_addr = PT_MQ * wordsize;
   if (regno == tdep->ppc_ps_regnum)
-    u_addr = PT_MSR * 4;
+    u_addr = PT_MSR * wordsize;
   if (regno == tdep->ppc_fpscr_regnum)
-    u_addr = PT_FPSCR * 4;
+    u_addr = PT_FPSCR * wordsize;
 
   return u_addr;
 }
@@ -205,6 +322,16 @@ fetch_register (int tid, int regno)
   unsigned int offset;         /* Offset of registers within the u area. */
   char *buf = alloca (MAX_REGISTER_RAW_SIZE);
   CORE_ADDR regaddr = ppc_register_u_addr (regno);
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
+
+  /* Do the easy thing for now which is to silently succeed if we are
+     attached to a 32-bit process when we are expecting 64-bits */
+  if (wordsize != ppc_wordsize_pid(tid))
+    {
+      /* supplying garbage.. but that's ok */
+      supply_register (regno, buf);
+      return;
+    }
 

   if (altivec_register_p (regno))
     {
@@ -232,8 +359,19 @@ fetch_register (int tid, int regno)
   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
-					       (PTRACE_ARG3_TYPE) regaddr, 0);
+      if (wordsize != sizeof (PTRACE_XFER_TYPE))
+	{
+	  PTRACE_XFER_TYPE reg;
+	  ptrace (PPC_PTRACE_PEEKUSR_3264, tid,
+		  (PTRACE_ARG3_TYPE) regaddr, &reg);
+	  *(PTRACE_XFER_TYPE *) & buf[i] = reg;
+	}
+      else
+      {
+	  *(PTRACE_XFER_TYPE *) & buf[i] = ptrace (PT_READ_U, tid,
+						   (PTRACE_ARG3_TYPE) regaddr, 0);
+      }
+
       regaddr += sizeof (PTRACE_XFER_TYPE);
       if (errno != 0)
 	{
@@ -364,6 +452,7 @@ store_register (int tid, int regno)
   register int i;
   unsigned int offset;         /* Offset of registers within the u area.  */
   char *buf = alloca (MAX_REGISTER_RAW_SIZE);
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
 
   if (altivec_register_p (regno))
     {
@@ -378,8 +517,18 @@ store_register (int tid, int regno)
   for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
-	      *(PTRACE_XFER_TYPE *) & buf[i]);
+      if (wordsize != sizeof (PTRACE_XFER_TYPE))
+	{
+	  PTRACE_XFER_TYPE reg;
+	  ptrace (PPC_PTRACE_POKEUSR_3264, tid, (PTRACE_ARG3_TYPE) regaddr,
+		  *(PTRACE_XFER_TYPE *) & buf[i]);
+	}
+      else
+      {
+	  ptrace (PT_WRITE_U, tid, (PTRACE_ARG3_TYPE) regaddr,
+		  *(PTRACE_XFER_TYPE *) & buf[i]);
+      }
+
       regaddr += sizeof (PTRACE_XFER_TYPE);

       if (errno == EIO 
@@ -533,3 +682,243 @@ fill_fpregset (gdb_fpregset_t *fpregsetp
   if ((regno == -1) || regno == tdep->ppc_fpscr_regnum)
     regcache_collect (tdep->ppc_fpscr_regnum, (char *) (*fpregsetp + regi));
 }
+
+
+#ifdef CHILD_XFER_MEMORY
+
+/* this is a complete rip off from infptrace.c */
+
+#ifndef GDB_MAX_ALLOCA
+#define GDB_MAX_ALLOCA 0x1000
+#endif /* GDB_MAX_ALLOCA */
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR to
+   debugger memory starting at MYADDR.  Copy to inferior if WRITE is
+   nonzero.  TARGET is ignored.
+
+   Returns the length copied, which is either the LEN argument or
+   zero.  This xfer function does not do partial moves, since
+   child_ops doesn't allow memory operations to cross below us in the
+   target stack anyway.  */
+
+int
+child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
+		   struct mem_attrib *attrib, struct target_ops *target)
+{
+    int i;
+  /* Round starting address down to longword boundary.  */
+    CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
+  /* Round ending address up; get number of longwords that makes.  */
+    int count = ((((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+		 / sizeof (PTRACE_XFER_TYPE));
+    int alloc = count * sizeof (PTRACE_XFER_TYPE);
+    PTRACE_XFER_TYPE *buffer;
+    struct cleanup *old_chain = NULL;
+    int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
+    int arch64 = ARCH64();
+
+  /* Allocate buffer of that many longwords.  */
+    if (len < GDB_MAX_ALLOCA)
+    {
+	buffer = (PTRACE_XFER_TYPE *) alloca (alloc);
+    }
+    else
+    {
+	buffer = (PTRACE_XFER_TYPE *) xmalloc (alloc);
+	old_chain = make_cleanup (xfree, buffer);
+    }
+
+  /* WARNING: from kernel source: "when I and D space are separate,
+     these will need to be fixed." */
+    if (write)
+    {
+      /* Fill start and end extra bytes of buffer with existing memory
+	 data.  */
+	if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE))
+	{
+	  /* Need part of initial word -- fetch it.  */
+	    if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	    {
+		buffer[0] = ptrace (PT_READ_I, PIDGET (inferior_ptid), 
+				    (PTRACE_ARG3_TYPE) addr, 0);
+	    }
+	    else
+	    {
+		if (arch64) {
+		    buffer[0] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid), 
+					(unsigned long) addr, 0);
+		}
+		else 
+		{
+		    ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid), 
+			    (PTRACE_ARG3_TYPE) &addr, buffer);
+		}
+	    }
+	}
+	if (count > 1)		/* FIXME, avoid if even boundary.  */
+	{
+	    CORE_ADDR a64 = (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE));
+	    if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	    {
+		buffer[count - 1] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
+					    (PTRACE_ARG3_TYPE) a64, 0);
+	    }
+	    else
+		if (arch64) {
+		    buffer[count-1] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid),
+					      (PTRACE_ARG3_TYPE) &a64, 0);
+		}
+		else
+		{
+		    ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid),
+			    (PTRACE_ARG3_TYPE) &a64, &buffer[count - 1]);
+		}
+	}
+
+      /* Copy data to be written over corresponding part of buffer.  */
+	memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+		myaddr, len);
+
+      /* Write the entire buffer.  */
+	for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+	{
+	    errno = 0;
+	    if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	    {
+		ptrace (PT_WRITE_D, PIDGET (inferior_ptid), 
+			(PTRACE_ARG3_TYPE) addr, buffer[i]);
+	    }
+	    else
+		if (arch64) {
+		    ptrace (PT_WRITE_D, PIDGET (inferior_ptid), 
+			    (unsigned long) addr, buffer[i]);  
+		}
+		else 
+		{
+		    ptrace (PPC_PTRACE_POKEDATA_3264, PIDGET (inferior_ptid), 
+			    (PTRACE_ARG3_TYPE) &addr, buffer[i]);
+		}
+	    if (errno)
+	    {
+		errno = 0;
+		if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+		{
+		    ptrace (PT_WRITE_I, PIDGET (inferior_ptid), 
+			    (PTRACE_ARG3_TYPE) addr, buffer[i]);
+		}
+		else
+		    if (arch64) {
+			ptrace (PTRACE_POKEDATA, PIDGET (inferior_ptid),  
+				(PTRACE_ARG3_TYPE) addr, buffer[i]); 
+		    }
+		    else 
+		    {
+			ptrace (PPC_PTRACE_POKEDATA_3264, PIDGET (inferior_ptid), 
+				(PTRACE_ARG3_TYPE) &addr, buffer[i]);
+		    }
+	    }
+	    if (errno)
+		return 0;
+	}
+#ifdef CLEAR_INSN_CACHE
+	    CLEAR_INSN_CACHE ();
+#endif
+    }
+  else
+  {
+      /* Read all the longwords.  */
+      for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+      {
+	  errno = 0;
+	  if (wordsize == sizeof (PTRACE_XFER_TYPE) && (!arch64))
+	  {
+	      buffer[i] = ptrace (PT_READ_I, PIDGET (inferior_ptid),
+				  (PTRACE_ARG3_TYPE) addr, 0);
+	  }
+	  else
+	  {
+	      if (arch64) {
+		  buffer[i] = ptrace (PTRACE_PEEKDATA, PIDGET (inferior_ptid),
+				      (unsigned long) addr, 0);
+	      }
+	      else
+	      {
+		  ptrace (PPC_PTRACE_PEEKDATA_3264, PIDGET (inferior_ptid),
+			  (PTRACE_ARG3_TYPE) &addr, &buffer[i]);
+	      }
+	      if (errno)
+		  return 0;
+	      QUIT;
+	  }
+
+      /* Copy appropriate bytes out of the buffer.  */
+	  memcpy (myaddr,
+		  (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+		  len);
+      }
+  }
+  if (old_chain != NULL)
+    do_cleanups (old_chain);
+  return len;
+    }
+
+\f
+/* Did not want to add this originally since the kernel will give us a
+   lot of gargabe (and would probably fail if it wasn't for the
+   FPU's). But at least you can get the other registers in struct
+   pt_regs.  Perhaps we can get the kernels to co-operate. */
+static void
+udot_info (char *dummy1, int dummy2)
+{
+  int udot_off;			/* Offset into user struct */
+  int udot_val;			/* Value from user struct at udot_off */
+  char mess[128];		/* For messages */
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
+
+  if (!target_has_execution)
+    {
+      error ("The program is not being run.");
+    }
+
+  for (udot_off = 0; udot_off < KERNEL_U_SIZE; udot_off += sizeof (udot_val))
+    {
+      if ((udot_off % 24) == 0)
+	{
+	  if (udot_off > 0)
+	    {
+	      printf_filtered ("\n");
+	    }
+	  printf_filtered ("%04x:", udot_off);
+	}
+      if (wordsize != sizeof (PTRACE_XFER_TYPE))
+	{
+	  PTRACE_XFER_TYPE reg;
+	  /* ptrace will place contents in "data" pointer */
+	  ptrace (PPC_PTRACE_PEEKUSR_3264, PIDGET (inferior_ptid),
+		  (PTRACE_ARG3_TYPE) udot_off, &reg);
+	  udot_val = reg;
+	}
+      else
+	udot_val = ptrace (PT_READ_U, PIDGET (inferior_ptid),
+			   (PTRACE_ARG3_TYPE) udot_off, 0);
+      if (errno != 0)
+	{
+	  sprintf (mess, "\nreading user struct at offset 0x%x", udot_off);
+	  perror_with_name (mess);
+	}
+      /* Avoid using nonportable (?) "*" in print specs */
+      printf_filtered (sizeof (int) == 4 ? " 0x%08x" : " 0x%16x", udot_val);
+    }
+  printf_filtered ("\n");
+}
+#endif /* CHILD_XFER_MEMORY */
+
+#include "command.h"
+void
+_initialize_ppc_linux_nat (void)
+{
+#ifdef CHILD_XFER_MEMORY
+  add_info ("udot", udot_info,
+	    "Print contents of kernel ``struct user'' for current child.");
+#endif
+}



diff -rupPN gdb-5.2.1/gdb/ppc-linux-tdep.c src.ppc64/gdb/ppc-linux-tdep.c
--- gdb-5.2.1/gdb/ppc-linux-tdep.c	2002-02-24 16:31:19.000000000 -0600
+++ src.ppc64/gdb/ppc-linux-tdep.c	2003-01-28 13:28:24.000000000 -0600
@@ -57,6 +57,8 @@
    offsetof(struct sigcontext_struct, handler) == 0x14 */
 #define PPC_LINUX_HANDLER_PTR_OFFSET (PPC_LINUX_SIGNAL_FRAMESIZE + 0x14)
 
+#define TDEP	gdbarch_tdep (current_gdbarch)
+	


No, please! :-) I went through this file to get rid of the TDEP's not
too long ago.



 /* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */
 #define PPC_LINUX_PT_R0		0
 #define PPC_LINUX_PT_R1		1
@@ -730,3 +732,64 @@ _initialize_ppc_linux_tdep (void)
 			  ppc_linux_init_abi);
   add_core_fns (&ppc_linux_regset_core_fns);
 }
+
+struct link_map_offsets *
+	ppc64_linux_svr4_fetch_link_map_offsets (void)
+{

Don't add this at the end of the file. Probably right after the 32 bit
version of the function is better.

+    static struct link_map_offsets lmo;
+    static struct link_map_offsets *lmp = NULL;
+
+    if (lmp == NULL)
+    {
+	lmp = &lmo;
+
+	lmo.r_debug_size = 16;/* The actual size is xx bytes, but
+					   this is all we need.  */
+	lmo.r_map_offset = 8;
+	lmo.r_map_size   = 8; 
+	lmo.link_map_size = 40;  /* The actual size is xxx bytes, but
+					   this is all we need.  */
+	lmo.l_addr_offset = 0;
+	lmo.l_addr_size   = 8;
+	lmo.l_name_offset = 8; 
+	lmo.l_name_size   = 8;
+	lmo.l_next_offset = 24;
+	lmo.l_next_size   = 8;
+	lmo.l_prev_offset = 32;
+	lmo.l_prev_size   = 8;
+    }
+
+    return lmp;
+}
+
+
+/* Support for CONVERT_FROM_FUNC_PTR_ADDR(ADDR).
+	   Duplicate of RS6000 function, except ppc64_linux requires relocated address. */
+static CORE_ADDR
+read_memory_addr (CORE_ADDR memaddr, int len)
+{
+    return read_memory_unsigned_integer (memaddr, len);
+}
+	
+	
+CORE_ADDR
+ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr)
+{
+    long long my_adder;
+    struct obj_section *s;
+    CORE_ADDR retval;
+    extern struct obj_section *find_pc_section(CORE_ADDR);

no 'extern's in .c files. Include the .h instead.

+
+	/* this should be the base address that the object (containing the func_ptr_addr) is loaded at. */
+    my_adder = 0x7fe0000000; 
+
+    s = find_pc_section (my_adder + addr);
+    if (s && s->the_bfd_section->flags & SEC_CODE)
+	return addr;
+
+	  /* ADDR is in the data space, so it's a special function pointer. */
+    retval = read_memory_addr (my_adder + addr, TDEP->wordsize);
+	/*  printf("reading 0x%lx ",my_adder+addr); */
+	/*  printf("ppc64...convert_func_ptr addr:0x%lx  new:0x%lx\n",addr,retval); */
+    return retval;
+}

can you expand a bit on why the above is needed?



diff -rupPN gdb-5.2.1/gdb/ppc64-linux-tdep.c src.ppc64/gdb/ppc64-linux-tdep.c
--- gdb-5.2.1/gdb/ppc64-linux-tdep.c	1969-12-31 18:00:00.000000000 -0600
+++ src.ppc64/gdb/ppc64-linux-tdep.c	2003-01-28 13:28:24.000000000 -0600
@@ -0,0 +1,80 @@
+/* Target-dependent code for GDB, the GNU debugger.
+
+   Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   2000, 2001 Free Software Foundation, Inc.
+

Copyright 2003 only, is enough, since this is a new file.

+   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"
+
+
+/* These elfcore fuctions are defined in libbfd.a but only when host
+   == target, once we can convince the bfd to supply it these can go */

can you explain what's going on here? I don't understand the comment.

+#define _SYSCALL32
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#define ARCH_SIZE 0
+#include "elf-bfd.h"
+#include "libiberty.h"
+#include <sys/procfs.h>
+
+
+/*
+ * Initialization
+ */
+void
+_initialize_ppc64_linux_tdep (void)
+{
+  /* hardware/kernel supports single stepping */
+  set_gdbarch_software_single_step (current_gdbarch, NULL);
+}
+

the _initialize functions should be at the bottom of the file.

+/* the start_address stored in the bfd is a function descriptor */
+#include "gdb/target.h"
+CORE_ADDR
+ppc64_bfd_get_start_address (bfd *abfd)
+{
+  extern struct target_ops exec_ops;
+  CORE_ADDR myaddr;
+  xfer_memory(abfd->start_address, (char *)&myaddr, 8, 0, 0, &exec_ops);
+  return myaddr;
+}
+
+/* Fetch (and possibly build) an appropriate link_map_offsets
+   structure for GNU/Linux PPC targets using the struct offsets
+   defined in link.h (but without actual reference to that file).
+
+   This makes it possible to access GNU/Linux PPC shared libraries
+   from a GDB that was not built on an GNU/Linux PPC host (for cross
+   debugging).
+
+*/


????

+#include "gdbcore.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+#include "ppc-tdep.h"
+#define TDEP	gdbarch_tdep (current_gdbarch)
+

No. All includes go at the beginning of the file. No TDEP.

+static CORE_ADDR
+read_memory_addr (CORE_ADDR memaddr, int len)
+{
+  return read_memory_unsigned_integer (memaddr, len);
+}

????? what's this for???


this whole file is questionable.



diff -rupPN gdb-5.2.1/gdb/rs6000-tdep.c src.ppc64/gdb/rs6000-tdep.c
--- gdb-5.2.1/gdb/rs6000-tdep.c	2002-04-01 00:01:46.000000000 -0600
+++ src.ppc64/gdb/rs6000-tdep.c	2003-01-28 13:28:24.000000000 -0600
@@ -513,13 +508,13 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 
       if ((op & 0xfc1fffff) == 0x7c0802a6)
 	{			/* mflr Rx */
-	  lr_reg = (op & 0x03e00000) | 0x90010000;
+	  lr_reg = (op & 0x03e00000);
 	  continue;
 
 	}
       else if ((op & 0xfc1fffff) == 0x7c000026)
 	{			/* mfcr Rx */
-	  cr_reg = (op & 0x03e00000) | 0x90010000;
+	  cr_reg = (op & 0x03e00000);
 	  continue;
 
 	}
@@ -545,7 +540,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 	    {
 	      fdata->saved_gpr = reg;
 	      if ((op & 0xfc1f0003) == 0xf8010000)
-		op = (op >> 1) << 1;
+		op &= ~3UL;
 	      fdata->gpr_offset = SIGNED_SHORT (op) + offset;
 	    }
 	  continue;
@@ -577,19 +572,49 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 	  continue;
 
 	}
-      else if (lr_reg != -1 && (op & 0xffff0000) == lr_reg)
-	{			/* st Rx,NUM(r1) 
-				   where Rx == lr */
-	  fdata->lr_offset = SIGNED_SHORT (op) + offset;
+      else if (lr_reg != -1 &&
+	       /* std Rx || stdu Rx */
+	       (((op & 0xffff0000) == (lr_reg | 0xf8010000)) ||
+		/* stw Rx */
+		((op & 0xffff0000) == (lr_reg | 0x90010000)) ||
+		/* stwu Rx */
+		((op & 0xffff0000) == (lr_reg | 0x94010000))))
+	{	/* where Rx == lr */
+	  fdata->lr_offset = offset;
 	  fdata->nosavedpc = 0;
 	  lr_reg = 0;
+	  if ((op & 0xfc000003) == 0xf8000000 ||	/* std Rx */
+	      (op & 0xfc000000) == 0x90000000)		/* stw Rx */
+	    {
+	      /* does not update r1 add d to lr_offset */
+	      fdata->lr_offset = SIGNED_SHORT (op);
+	    }
 	  continue;
 
 	}
-      else if (cr_reg != -1 && (op & 0xffff0000) == cr_reg)
-	{			/* st Rx,NUM(r1) 
+      else if (cr_reg != -1 &&
+	       /* std Rx || stdu Rx */
+	       (((op & 0xffff0000) == (cr_reg | 0xf8010000)) ||
+		/* stw Rx */
+		((op & 0xffff0000) == (cr_reg | 0x90010000)) ||
+		/* stwu Rx */
+		((op & 0xffff0000) == (cr_reg | 0x94010000))))
+	{	/* where Rx == cr */
+	  fdata->cr_offset = offset;
+	  cr_reg = 0;
+	  if ((op & 0xfc000003) == 0xf8000000 ||
+	      (op & 0xfc000000) == 0x90000000)
+	    {
+	      /* does not update r1 add d to cr_offset */
+	      fdata->cr_offset += SIGNED_SHORT (op);
+	    }
+	  continue;
+
+	}
+      else if (cr_reg != -1 && (op & 0xffff0003) == cr_reg)
+	{			/* std Rx,NUM(r1) || stdu Rx,NUM(r1) 
 				   where Rx == cr */
-	  fdata->cr_offset = SIGNED_SHORT (op) + offset;
+	  fdata->cr_offset = SIGNED_SHORT (op & ~3UL) + offset;
 	  cr_reg = 0;
 	  continue;
 
@@ -634,30 +658,41 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR l
 				   this branch */
 	  continue;
 
-	  /* update stack pointer */
 	}
-      else if ((op & 0xffff0000) == 0x94210000 ||	/* stu r1,NUM(r1) */
-	       (op & 0xffff0003) == 0xf8210001)		/* stdu r1,NUM(r1) */
-	{
+      /* update stack pointer */
+      else if ((op & 0xfc1f0000) == 0x94010000)
+	{		/* stu rX,NUM(r1) ||  stwu rX,NUM(r1) */
 	  fdata->frameless = 0;
-	  if ((op & 0xffff0003) == 0xf8210001)
-	    op = (op >> 1) << 1;
 	  fdata->offset = SIGNED_SHORT (op);
 	  offset = fdata->offset;
 	  continue;
-
 	}
-      else if (op == 0x7c21016e)
-	{			/* stwux 1,1,0 */
+      else if ((op & 0xfc1f016a) == 0x7c01016e)
+	{			/* stwux rX,r1,rY */
+	  /* no way to figure out what r1 is going to be */
+	  fdata->frameless = 0;
+	  offset = fdata->offset;
+	  continue;
+	}
+      else if ((op & 0xfc1f0003) == 0xf8010001)
+	{			/* stdu rX,NUM(r1) */
+	  fdata->frameless = 0;
+	  fdata->offset = SIGNED_SHORT (op & ~3UL);
+	  offset = fdata->offset;
+	  continue;
+	}
+      else if ((op & 0xfc1f016a) == 0x7c01016a)
+	{			/* stdux rX,r1,rY */
+	  /* no way to figure out what r1 is going to be */
 	  fdata->frameless = 0;
 	  offset = fdata->offset;
 	  continue;
-
-	  /* Load up minimal toc pointer */
 	}
-      else if ((op >> 22) == 0x20f
+      /* Load up minimal toc pointer */
+      else if (((op >> 22) == 0x20f	||	/* l r31,... or l r30,... */
+	       (op >> 22) == 0x3af)		/* ld r31,... or ld r30,... */
 	       && !minimal_toc_loaded)
-	{			/* l r31,... or l r30,... */
+	{
 	  minimal_toc_loaded = 1;
 	  continue;
 

All these changes to skip_prologue worry me. Are you sure you are not
breaking other ppc variants? Did you test altivec? e500? eabi, etc etc?

@@ -2439,6 +2483,44 @@ static const struct reg registers_7400[]
   /* FIXME? Add more registers? */
 };
 
+
+/* PowerPC UISA - a PPC64 processor as viewed by user-level code. */
+/* Should be able to use the common registers_powerpc[] here, however
+   it does not define an fpscr, though both linux and aix get one from
+   ptrace(). Can only assume that there is a 32-bit core our there
+   that does not have an fpscr.  I think we can assert that all 64-bit
+   cores do. */

how about using PPC_UISA_SPRS ?

+static const struct reg registers_powerpc64[] =
+{
+  COMMON_UISA_REGS,
+  /* SPRs */
+  /*  66 */ R4(cr), R(lr), R(ctr), R4(xer),
+  /*  70 */ R4(fpscr), R0 /* mq? */
+};
+



+static const struct reg registers_a35[] =
+{
+  COMMON_UISA_REGS,
+  /* SPRs */
+  /*  66 */ R4(cr), R(lr), R(ctr), R4(xer),
+  /*  70 */ R4(fpscr), R0 /* mq? */,
+  /*  72 */ R(dabr), R(iabr), R4(dsisr),
+  /*  75 */ R(dar), R4(dec), R(sdr1), R(srr0), R(srr1),
+  /*  80 */ R(sprg0), R(sprg1), R(sprg2), R(sprg3),
+  /*  84 */ R64(asr), R4(ear), R4(tbl), R4(tbu),
+  /*  88 */ R(ibat0u), R(ibat0l), R(ibat1u), R(ibat1l),
+  /*  92 */ R(ibat2u), R(ibat2l), R(ibat3u), R(ibat3l),
+  /*  96 */ R(dbat0u), R(dbat0l), R(dbat1u), R(dbat1l),
+  /* 100 */ R(dbat2u), R(dbat2l), R(dbat3u), R(dbat3l),
+  /* 104 */ R(pir), R4(mmcr0),
+  /* 106..121 segment regs 0..15 */ 
+  /* 106 */ R(sr0), R(sr1), R(sr2), R(sr3),
+  /* 110 */ R(sr4), R(sr5), R(sr6), R(sr7),
+  /* 114 */ R(sr8), R(sr9), R(sr10), R(sr11),
+  /* 118 */ R(sr12), R(sr13), R(sr14), R(sr15),
+  /* 122 */ R4(pvr) /* processor version register */
+};
+

what's the a35 stuff for?

 /* Motorola e500.  */
 static const struct reg registers_e500[] =
 {
@@ -2947,6 +3051,15 @@ rs6000_gdbarch_init (struct gdbarch_info
          descriptors).  */
       set_gdbarch_convert_from_func_ptr_addr (gdbarch,
 	rs6000_convert_from_func_ptr_addr);
+
+      /* wordsize 8, ppc64 linux  functions */
+      if (osabi == ELFOSABI_LINUX)
+      {
+	  set_solib_svr4_fetch_link_map_offsets
+	    (gdbarch, ppc64_linux_svr4_fetch_link_map_offsets);
+	  set_gdbarch_convert_from_func_ptr_addr
+            (gdbarch, ppc64_linux_convert_from_func_ptr_addr);
+      }
     }

why here? shouldn't this bit go in ppc_linux_init_abi()?


   set_gdbarch_frame_args_address (gdbarch, rs6000_frame_args_address);
   set_gdbarch_frame_locals_address (gdbarch, rs6000_frame_args_address);




Well, I think there are still a lot of things that need to be looked
at.  Expecially the new PTRACE related changes. Maybe Kevin has some
more ideas on this.


elena


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

* Re: [PATCH]  new support for PPC64 architecture
  2003-05-07 20:37 ` Elena Zannoni
@ 2003-05-07 20:46   ` Daniel Jacobowitz
  0 siblings, 0 replies; 8+ messages in thread
From: Daniel Jacobowitz @ 2003-05-07 20:46 UTC (permalink / raw)
  To: Elena Zannoni; +Cc: Will Schmidt, gdb-patches, will_schmidt

On Wed, May 07, 2003 at 04:42:27PM -0400, Elena Zannoni wrote:
> Will Schmidt writes:
>  > All,
>  > 
>  >    This patch contains code that provides support for GDB on the PPC64
>  > architecture.     This patch will apply clean on top of the RedHat
>  > gdb-5.3post-0.20021129.29.src.rpm.         (A patch against CVS will
>  > happen, but not today.. )
>  > 
>  > 
>  > (See attached file: gdb-5.3post-ppc64-support.patch)
>  > 
>  > 
>  > -Will
>  > 
>  > 
>  > Will Schmidt
>  > willschm@us.ibm.com     will_schmidt@vnet.ibm.com
>  > Linux on PowerPC-64 Development
>  > IBM Rochester
> 
> A few comments/questions.  You need changelogs, and the proper
> copyright verbiage in the new files you are adding. The code needs to
> conform to gnu coding standards as fas as spaces, indentation,
> etc. You can run the new files through gdb_indent.sh to get the right
> format. Comments should start with a capital letter, be full
> sentences, and end with a period followed by 2 spaces.
> 
> see below.....
> 
> diff -rupPN gdb-5.2.1/gdb/config/powerpc/ppc64linux.mh src.ppc64/gdb/config/powerpc/ppc64linux.mh
> --- gdb-5.2.1/gdb/config/powerpc/ppc64linux.mh	1969-12-31 18:00:00.000000000 -0600
> +++ src.ppc64/gdb/config/powerpc/ppc64linux.mh	2003-03-05 13:00:33.000000000 -0600
> @@ -0,0 +1,14 @@
> +# Host: PowerPC, running Linux
> +
> +XM_FILE= xm-linux.h
> +XM_CLIBS=
> +
> +NAT_FILE= nm-linux.h
> +NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o linux-proc.o \
> +	core-regset.o ppc-linux-nat.o proc-service.o thread-db.o lin-lwp.o  \
> +	gcore.o ppc-sysv-tdep.o
> +
> 
> this is the host makefile fragment, the *tdep.o files should be
> included in the target makefile fragment, the .mt file, not here.
> Actually if you exclude the .o's that ashould really be in the mt
> file, then this file becomes almost identical to the linux.mh
> file. Which makes me wonder if we really need a new file.
> 
> +LOADLIBES = -ldl -lthread_db
> +
> 
> Why include thread_db? I don't see any other config files doing that.
> 
> +GDBSERVER_DEPFILES= low-linux.o
> 
> it is linux-low.o
> 
> +GDBSERVER_LIBS= -lnss_dns  -lnss_files -lresolv

Actually, those lines are obsolete.  It's on my list to go through and
remove them all so people don't keep copying them.

> diff -rupPN gdb-5.2.1/gdb/elfread.c src.ppc64/gdb/elfread.c
> --- gdb-5.2.1/gdb/elfread.c	2002-03-25 10:50:20.000000000 -0600
> +++ src.ppc64/gdb/elfread.c	2003-01-28 13:28:24.000000000 -0600
> @@ -154,6 +154,12 @@ record_minimal_symbol_and_info (char *na
>    if (ms_type == mst_text || ms_type == mst_file_text)
>      address = SMASH_TEXT_ADDRESS (address);
>  
> +#ifdef DROP_TEXT_NAME_PREFIX_CHAR
> +  if ((ms_type == mst_text || ms_type == mst_file_text)
> +      && name[0] == DROP_TEXT_NAME_PREFIX_CHAR)
> +    ++name;
> +#endif /* DROP_TEXT_NAME_PREFIX_CHAR */
> +
> 
> 
> can you explain why this is needed? Do we really have names starting
> with '.', using gcc?


This is a peculiarity of the PPC64 ABI, also related to the OPD macros. 
Global functions have two symbols: 'foo' and '.foo'.  One of them is
an address and the other is a descriptor with the function's gp value,
IIRC.


-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


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

* Re: [PATCH]  new support for PPC64 architecture
  2003-04-17 22:44 [PATCH] new support for PPC64 architecture Will Schmidt
  2003-05-07 20:14 ` Andrew Cagney
  2003-05-07 20:37 ` Elena Zannoni
@ 2003-05-09 21:05 ` Jim Blandy
  2003-05-13 22:33 ` Jim Blandy
  3 siblings, 0 replies; 8+ messages in thread
From: Jim Blandy @ 2003-05-09 21:05 UTC (permalink / raw)
  To: Will Schmidt; +Cc: gdb-patches, will_schmidt, Elena Zannoni


"Will Schmidt" <willschm@us.ibm.com> writes:
>    This patch contains code that provides support for GDB on the PPC64
> architecture.     This patch will apply clean on top of the RedHat
> gdb-5.3post-0.20021129.29.src.rpm.         (A patch against CVS will
> happen, but not today.. )

To make it easier to look through the patch and put together the
necessary changes, I've gone ahead and created
jimb-ppc64-linux-20030509-branch, based on today's sources, and
committed your patch as-is to there.

Will, whose Linux distribution have you been building and testing in?
What release?


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

* Re: [PATCH]  new support for PPC64 architecture
  2003-04-17 22:44 [PATCH] new support for PPC64 architecture Will Schmidt
                   ` (2 preceding siblings ...)
  2003-05-09 21:05 ` Jim Blandy
@ 2003-05-13 22:33 ` Jim Blandy
  3 siblings, 0 replies; 8+ messages in thread
From: Jim Blandy @ 2003-05-13 22:33 UTC (permalink / raw)
  To: Will Schmidt; +Cc: gdb-patches, will_schmidt, Elena Zannoni


"Will Schmidt" <willschm@us.ibm.com> writes:
>    This patch contains code that provides support for GDB on the PPC64
> architecture.     This patch will apply clean on top of the RedHat
> gdb-5.3post-0.20021129.29.src.rpm.         (A patch against CVS will
> happen, but not today.. )

Okay --- here are the next steps, as I see them:

- As you say, get the patch to apply and run against current sources.
  This can happen without worrying about bringing the patch in line
  with current requirements for contributions: multi-arch, using new
  interfaces, etc.

- Get a test suite run with those sources that we can use as a
  baseline for evaluating subsequent work.

- Worry about multi-arch, new interfaces, etc.  This should be pretty
  easy going, since both tasks break down into (possibly large) sets
  of small, mostly independent changes.  It'll be easy to work
  incrementally, and share the job.


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

* Re: [PATCH]  new support for PPC64 architecture
@ 2003-05-13 22:59 Will Schmidt
  0 siblings, 0 replies; 8+ messages in thread
From: Will Schmidt @ 2003-05-13 22:59 UTC (permalink / raw)
  To: Jim Blandy; +Cc: Elena Zannoni, gdb-patches, will_schmidt


Those steps sound good to me. :-)

Elena, were you able to get your build to complete?


willschm@us.ibm.com
Linux on PowerPC-64 Development
IBM Rochester


                                                                                                                                                     
                      Jim Blandy                                                                                                                     
                      <jimb@redhat.com>        To:       Will Schmidt/Rochester/IBM@IBMUS                                                            
                                               cc:       gdb-patches@sources.redhat.com, will_schmidt@vnet.ibm.com, Elena Zannoni                    
                      05/13/2003 05:38          <ezannoni@redhat.com>                                                                                
                      PM                       Subject:  Re: [PATCH]  new support for PPC64 architecture                                             
                                                                                                                                                     
                                                                                                                                                     





"Will Schmidt" <willschm@us.ibm.com> writes:
>    This patch contains code that provides support for GDB on the PPC64
> architecture.     This patch will apply clean on top of the RedHat
> gdb-5.3post-0.20021129.29.src.rpm.         (A patch against CVS will
> happen, but not today.. )

Okay --- here are the next steps, as I see them:

- As you say, get the patch to apply and run against current sources.
  This can happen without worrying about bringing the patch in line
  with current requirements for contributions: multi-arch, using new
  interfaces, etc.

- Get a test suite run with those sources that we can use as a
  baseline for evaluating subsequent work.

- Worry about multi-arch, new interfaces, etc.  This should be pretty
  easy going, since both tasks break down into (possibly large) sets
  of small, mostly independent changes.  It'll be easy to work
  incrementally, and share the job.





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

* Re: [PATCH]  new support for PPC64 architecture
@ 2003-05-12 14:34 Will Schmidt
  0 siblings, 0 replies; 8+ messages in thread
From: Will Schmidt @ 2003-05-12 14:34 UTC (permalink / raw)
  To: Jim Blandy; +Cc: Elena Zannoni, gdb-patches, will_schmidt


To date this work has been done on SuSE Sles 7 and Sles 8 (for ppc64)
releases.

willschm@us.ibm.com
Linux on PowerPC-64 Development
IBM Rochester


                                                                                                                                                     
                      Jim Blandy                                                                                                                     
                      <jimb@redhat.com>        To:       Will Schmidt/Rochester/IBM@IBMUS                                                            
                                               cc:       gdb-patches@sources.redhat.com, will_schmidt@vnet.ibm.com, Elena Zannoni                    
                      05/09/2003 04:10          <ezannoni@redhat.com>                                                                                
                      PM                       Subject:  Re: [PATCH]  new support for PPC64 architecture                                             
                                                                                                                                                     
                                                                                                                                                     





"Will Schmidt" <willschm@us.ibm.com> writes:
>    This patch contains code that provides support for GDB on the PPC64
> architecture.     This patch will apply clean on top of the RedHat
> gdb-5.3post-0.20021129.29.src.rpm.         (A patch against CVS will
> happen, but not today.. )

To make it easier to look through the patch and put together the
necessary changes, I've gone ahead and created
jimb-ppc64-linux-20030509-branch, based on today's sources, and
committed your patch as-is to there.

Will, whose Linux distribution have you been building and testing in?
What release?





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

end of thread, other threads:[~2003-05-13 22:59 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-17 22:44 [PATCH] new support for PPC64 architecture Will Schmidt
2003-05-07 20:14 ` Andrew Cagney
2003-05-07 20:37 ` Elena Zannoni
2003-05-07 20:46   ` Daniel Jacobowitz
2003-05-09 21:05 ` Jim Blandy
2003-05-13 22:33 ` Jim Blandy
2003-05-12 14:34 Will Schmidt
2003-05-13 22:59 Will Schmidt

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