]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Patch from Will Schmidt <willschm@us.ibm.com>: jimb-ppc64-linux-20030509-branch
authorJim Blandy <jimb@codesourcery.com>
Tue, 13 May 2003 00:08:58 +0000 (00:08 +0000)
committerJim Blandy <jimb@codesourcery.com>
Tue, 13 May 2003 00:08:58 +0000 (00:08 +0000)
These changes enable support of PPC64 architecture.
* config/powerpc/ppc64linux.mh: New file.
* config/powerpc/ppc64linux.mt: New file.
* config/powerpc/tm-ppc64linux.h: New file.
* ppc64-linux-tdep.c: New file.
* configure.host: Add clause for powerpc64-*-linux*
* configure.tgt: Add clause for powerpc64-*-linux*
* elfread.c (record_minimal_symbol_and_info): If
DROP_TEXT_NAME_PREFIX_CHAR is #defined, then drop a leading
instance of that char from the names of text symbols.
(elf_symtab_read): If SKIP_DATA_IN_OPD is #defined, ignore data
symbols in the .opd section.
* ppc-linux-nat.c (PTRACE_XFER_TYPE): Change the default for this
to 'long'.
(PPC_PTRACE_POKEUSR_3264, PPC_PTRACE_PEEKUSR_3264,
PPC_PTRACE_POKEDATA_3264, PPC_PTRACE_PEEKDATA_3264): Provide
default definitions for these.
(ARCH64): New macro.
(ppc_wordsize_pid): New function.
(kernel_u_size): Handle 64-bit case.
(ppc_register_u_addr): Same.
(fetch_register): Use the *_3264 requests when
debugging a 64-bit process from a 32-bit GDB.
(store_register): Same.
(GDB_MAX_ALLOCA, child_xfer_memory, udot_info): Copied from
infptrace.c.
(_initialize_ppc_linux_nat): New function, to register our copy of
the udot_info command.
* ppc-linux-tdep.c (TDEP): New macro.
(ppc64_linux_svr4_fetch_link_map_offsets): New function.
(read_memory_addr): Copied from rs6000-tdep.c.
(ppc64_linux_convert_from_func_ptr_addr): New function.
* rs6000-tdep.c (skip_prologue): Recognize more instructions for
saving the 'lr' and 'cr' registers; don't just pre-emptively mask
in the 'st' opcode as soon as we see an 'mflr' or 'mfcr' opcode.
Recognize more instructions for updating the stack pointer, and
loading the TOC pointer.
(registers_powerpc64, registers_a35): New register tables.
(rs6000_gdbarch_init): Register the 64-bit solib functions.
* solib-svr4.c (solib_break_names): If SOLIB_BREAK_NAME is
#defined, include an entry for it.
(enable_break): Call CONVERT_FROM_FUNC_PTR_ADDR when trying to
guess the linker's base address.
* config/powerpc/tm-linux.h
(ppc64_linux_svr4_fetch_link_map_offsets,
ppc64_linux_convert_from_func_ptr_addr): New declarations.

13 files changed:
gdb/ChangeLog
gdb/config/powerpc/ppc64linux.mh [new file with mode: 0644]
gdb/config/powerpc/ppc64linux.mt [new file with mode: 0644]
gdb/config/powerpc/tm-linux.h
gdb/config/powerpc/tm-ppc64linux.h [new file with mode: 0644]
gdb/configure.host
gdb/configure.tgt
gdb/elfread.c
gdb/ppc-linux-nat.c
gdb/ppc-linux-tdep.c
gdb/ppc64-linux-tdep.c [new file with mode: 0644]
gdb/rs6000-tdep.c
gdb/solib-svr4.c

index 9c58b41c498cf2c429fba9589478dcf5fe804c16..9bd5f9dc2fff39acd97c75aa6b78d95fa7b2b11b 100644 (file)
@@ -1,3 +1,52 @@
+2003-05-12  Will Schmidt <willschm@us.ibm.com>
+
+        These changes enable support of PPC64 architecture.
+       * config/powerpc/ppc64linux.mh: New file.
+       * config/powerpc/ppc64linux.mt: New file.
+       * config/powerpc/tm-ppc64linux.h: New file.
+       * ppc64-linux-tdep.c: New file.
+       * configure.host: Add clause for powerpc64-*-linux*
+       * configure.tgt: Add clause for powerpc64-*-linux*
+       * elfread.c (record_minimal_symbol_and_info): If
+       DROP_TEXT_NAME_PREFIX_CHAR is #defined, then drop a leading
+       instance of that char from the names of text symbols.
+       (elf_symtab_read): If SKIP_DATA_IN_OPD is #defined, ignore data
+       symbols in the .opd section.
+       * ppc-linux-nat.c (PTRACE_XFER_TYPE): Change the default for this
+       to 'long'.
+       (PPC_PTRACE_POKEUSR_3264, PPC_PTRACE_PEEKUSR_3264,
+       PPC_PTRACE_POKEDATA_3264, PPC_PTRACE_PEEKDATA_3264): Provide
+       default definitions for these.
+       (ARCH64): New macro.
+       (ppc_wordsize_pid): New function.
+       (kernel_u_size): Handle 64-bit case.
+       (ppc_register_u_addr): Same.
+       (fetch_register): Use the *_3264 requests when
+       debugging a 64-bit process from a 32-bit GDB.
+       (store_register): Same.
+       (GDB_MAX_ALLOCA, child_xfer_memory, udot_info): Copied from
+       infptrace.c.
+       (_initialize_ppc_linux_nat): New function, to register our copy of
+       the udot_info command.
+       * ppc-linux-tdep.c (TDEP): New macro.
+       (ppc64_linux_svr4_fetch_link_map_offsets): New function.
+       (read_memory_addr): Copied from rs6000-tdep.c.
+       (ppc64_linux_convert_from_func_ptr_addr): New function.
+       * rs6000-tdep.c (skip_prologue): Recognize more instructions for
+       saving the 'lr' and 'cr' registers; don't just pre-emptively mask
+       in the 'st' opcode as soon as we see an 'mflr' or 'mfcr' opcode.
+       Recognize more instructions for updating the stack pointer, and
+       loading the TOC pointer.
+       (registers_powerpc64, registers_a35): New register tables.
+       (rs6000_gdbarch_init): Register the 64-bit solib functions.
+       * solib-svr4.c (solib_break_names): If SOLIB_BREAK_NAME is
+       #defined, include an entry for it.
+       (enable_break): Call CONVERT_FROM_FUNC_PTR_ADDR when trying to
+       guess the linker's base address.
+       * config/powerpc/tm-linux.h
+       (ppc64_linux_svr4_fetch_link_map_offsets,
+       ppc64_linux_convert_from_func_ptr_addr): New declarations.
+
 2003-05-08  Andrew Cagney  <cagney@redhat.com>
 
        * regcache.h (max_register_size): Delete declaration.
diff --git a/gdb/config/powerpc/ppc64linux.mh b/gdb/config/powerpc/ppc64linux.mh
new file mode 100644 (file)
index 0000000..e18a188
--- /dev/null
@@ -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 --git a/gdb/config/powerpc/ppc64linux.mt b/gdb/config/powerpc/ppc64linux.mt
new file mode 100644 (file)
index 0000000..878eb15
--- /dev/null
@@ -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
+
index d69dfc1f5bfd4abf52b8665ac9085250f9fcf056..9d72374a5be876c1a3340fc3e370c9ac1a91a24d 100644 (file)
@@ -67,4 +67,9 @@ extern int ppc_linux_in_sigtramp (CORE_ADDR pc, char *func_name);
    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 --git a/gdb/config/powerpc/tm-ppc64linux.h b/gdb/config/powerpc/tm-ppc64linux.h
new file mode 100644 (file)
index 0000000..4b30c18
--- /dev/null
@@ -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 */
index 8f96b0a842ce97253aa55d53d4da73d6297f6d13..ab5c2b7d14bac0d302fe4ebe5f4a2bee0eeb57fe 100644 (file)
@@ -120,6 +120,8 @@ powerpc-*-aix*)             gdb_host=aix432 ;;
 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 ;;
index fe4cc5d485677c10e817cd180f3e9d55de1a0b2f..2f5c909795a4979176d2bfdbdadbfcb2f5dea2db 100644 (file)
@@ -193,6 +193,15 @@ powerpc-*-aix*)            gdb_target=aix ;;
 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
index 7aee37cc5db37685ce7c0f5e5607d8d692a3976b..fd4c9566dbfa459aecd764dfb2dd814efd3b34c4 100644 (file)
@@ -141,6 +141,12 @@ record_minimal_symbol_and_info (char *name, CORE_ADDR address,
   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);
 }
@@ -363,6 +369,10 @@ elf_symtab_read (struct objfile *objfile, int dynamic)
                    {
                      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
@@ -444,6 +454,10 @@ elf_symtab_read (struct objfile *objfile, int dynamic)
                         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
index 20c8adda44a31d9ba0c5585d514eff49b1e974c7..aff1f7385bdd3547b8970424590a76a175ab559d 100644 (file)
 #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
@@ -106,7 +203,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* */
@@ -127,32 +232,33 @@ 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;
 }
@@ -206,6 +312,16 @@ fetch_register (int tid, int regno)
   unsigned int offset;         /* Offset of registers within the u area. */
   char buf[MAX_REGISTER_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))
     {
@@ -233,8 +349,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)
        {
@@ -365,6 +492,7 @@ store_register (int tid, int regno)
   register int i;
   unsigned int offset;         /* Offset of registers within the u area.  */
   char buf[MAX_REGISTER_SIZE];
+  int wordsize = (gdbarch_tdep (current_gdbarch))->wordsize;
 
   if (altivec_register_p (regno))
     {
@@ -379,8 +507,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 
@@ -534,3 +672,243 @@ fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
   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
+}
index 9284751fd0ccac23f2b4bbccfed381fcb666733e..59930396c0bb6afc72049a1be09a709796eeb53c 100644 (file)
@@ -63,6 +63,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
@@ -755,3 +757,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 --git a/gdb/ppc64-linux-tdep.c b/gdb/ppc64-linux-tdep.c
new file mode 100644 (file)
index 0000000..f7e0a2a
--- /dev/null
@@ -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);
+}
index 0b239bd418002555945423205e4c6e1b15456793..cd59cd43bd42be327bea7b31010d9137082ffda4 100644 (file)
@@ -529,13 +529,13 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
 
       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;
 
        }
@@ -561,7 +561,7 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
            {
              fdata->saved_gpr = reg;
              if ((op & 0xfc1f0003) == 0xf8010000)
-               op = (op >> 1) << 1;
+               op &= ~3UL;
              fdata->gpr_offset = SIGNED_SHORT (op) + offset;
            }
          continue;
@@ -593,19 +593,49 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
          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 &&
+              /* 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 & 0xffff0000) == cr_reg)
-       {                       /* st Rx,NUM(r1) 
+      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;
 
@@ -650,30 +680,41 @@ skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
                                   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;
 
@@ -2456,6 +2497,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[] =
 {
@@ -2956,6 +3035,15 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          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);
index 6c4c10ae0139d8fc4c8d8419f7e92ae195c977fc..2b453c9ba6be2c2fefccb56caa1ba8d4ac051705 100644 (file)
@@ -76,6 +76,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",
@@ -1015,7 +1018,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.  */