Remove cli_ui_out::out_field_fmt
[deliverable/binutils-gdb.git] / gdb / solib-spu.c
index 19e3212a2009edf293f37c212e2a88390e16a3af..cb735fd451c38e85bbaf5e8b95a6ee69e966cf7c 100644 (file)
@@ -1,5 +1,5 @@
 /* Cell SPU GNU/Linux support -- shared library handling.
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009-2018 Free Software Foundation, Inc.
 
    Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
 
@@ -7,7 +7,7 @@
 
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    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.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "solib-spu.h"
 #include "gdbcore.h"
-#include "gdb_string.h"
-#include "gdb_assert.h"
-#include "gdb_stat.h"
+#include <sys/stat.h>
 #include "arch-utils.h"
 #include "bfd.h"
 #include "symtab.h"
 #include "solist.h"
 #include "inferior.h"
 #include "objfiles.h"
-#include "observer.h"
+#include "observable.h"
 #include "breakpoint.h"
 #include "gdbthread.h"
+#include "gdb_bfd.h"
 
 #include "spu-tdep.h"
 
 static void
 spu_relocate_main_executable (int spufs_fd)
 {
-  struct objfile *objfile;
-  struct cleanup *old_chain;
   struct section_offsets *new_offsets;
   int i;
 
-  for (objfile = symfile_objfile;
-       objfile;
-       objfile = objfile->separate_debug_objfile)
-    {
-      new_offsets = xcalloc (objfile->num_sections,
-                            sizeof (struct section_offsets));
-      old_chain = make_cleanup (xfree, new_offsets);
+  if (symfile_objfile == NULL)
+    return;
 
-      for (i = 0; i < objfile->num_sections; i++)
-        new_offsets->offsets[i] = SPUADDR (spufs_fd, 0);
+  new_offsets = XALLOCAVEC (struct section_offsets,
+                           symfile_objfile->num_sections);
 
-      objfile_relocate (objfile, new_offsets);
-      do_cleanups (old_chain);
-    }
+  for (i = 0; i < symfile_objfile->num_sections; i++)
+    new_offsets->offsets[i] = SPUADDR (spufs_fd, 0);
+
+  objfile_relocate (symfile_objfile, new_offsets);
 }
 
 /* When running a stand-alone SPE executable, we may need to skip one more
@@ -92,13 +84,70 @@ spu_skip_standalone_loader (void)
         this will step past the first instruction of the stand-alone SPE
         executable loader, but we don't care about that.  */
 
-      inferior_thread ()->in_infcall = 1;   /* Suppress MI messages.  */
+      inferior_thread ()->control.in_infcall = 1; /* Suppress MI messages.  */
 
-      target_resume (inferior_ptid, 1, TARGET_SIGNAL_0);
+      target_resume (inferior_ptid, 1, GDB_SIGNAL_0);
       target_wait (minus_one_ptid, &ws, 0);
       set_executing (minus_one_ptid, 0);
 
-      inferior_thread ()->in_infcall = 0;
+      inferior_thread ()->control.in_infcall = 0;
+    }
+}
+
+static const struct objfile_data *ocl_program_data_key;
+
+/* Appends OpenCL programs to the list of `struct so_list' objects.  */
+static void
+append_ocl_sos (struct so_list **link_ptr)
+{
+  CORE_ADDR *ocl_program_addr_base;
+  struct objfile *objfile;
+
+  ALL_OBJFILES (objfile)
+    {
+      ocl_program_addr_base
+       = (CORE_ADDR *) objfile_data (objfile, ocl_program_data_key);
+      if (ocl_program_addr_base != NULL)
+        {
+         enum bfd_endian byte_order = bfd_big_endian (objfile->obfd)?
+                                        BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
+         TRY
+           {
+             CORE_ADDR data =
+               read_memory_unsigned_integer (*ocl_program_addr_base,
+                                             sizeof (CORE_ADDR),
+                                             byte_order);
+             if (data != 0x0)
+               {
+                 struct so_list *newobj;
+
+                 /* Allocate so_list structure.  */
+                 newobj = XCNEW (struct so_list);
+
+                 /* Encode FD and object ID in path name.  */
+                 xsnprintf (newobj->so_name, sizeof newobj->so_name, "@%s <%d>",
+                            hex_string (data),
+                            SPUADDR_SPU (*ocl_program_addr_base));
+                 strcpy (newobj->so_original_name, newobj->so_name);
+
+                 *link_ptr = newobj;
+                 link_ptr = &newobj->next;
+               }
+           }
+         CATCH (ex, RETURN_MASK_ALL)
+           {
+             /* Ignore memory errors.  */
+             switch (ex.error)
+               {
+               case MEMORY_ERROR:
+                 break;
+               default:
+                 throw_exception (ex);
+                 break;
+               }
+           }
+         END_CATCH
+       }
     }
 }
 
@@ -107,11 +156,11 @@ spu_skip_standalone_loader (void)
 static struct so_list *
 spu_current_sos (void)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
   struct so_list *head;
   struct so_list **link_ptr;
 
-  char buf[MAX_SPE_FD * 4];
+  gdb_byte buf[MAX_SPE_FD * 4];
   int i, size;
 
   /* First, retrieve the SVR4 shared library list.  */
@@ -132,6 +181,7 @@ spu_current_sos (void)
       if (size == 4)
        {
          int fd = extract_unsigned_integer (buf, 4, byte_order);
+
          spu_relocate_main_executable (fd);
 
          /* Re-enable breakpoints after main SPU context was established;
@@ -146,7 +196,7 @@ spu_current_sos (void)
   for (i = 0; i < size; i += 4)
     {
       int fd = extract_unsigned_integer (buf + i, 4, byte_order);
-      struct so_list *new;
+      struct so_list *newobj;
 
       unsigned long long addr;
       char annex[32], id[100];
@@ -157,7 +207,7 @@ spu_current_sos (void)
         yet.  Skip such entries; we'll be back for them later.  */
       xsnprintf (annex, sizeof annex, "%d/object-id", fd);
       len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
-                        id, 0, sizeof id);
+                        (gdb_byte *) id, 0, sizeof id);
       if (len <= 0 || len >= sizeof id)
        continue;
       id[len] = 0;
@@ -165,17 +215,21 @@ spu_current_sos (void)
        continue;
 
       /* Allocate so_list structure.  */
-      new = XZALLOC (struct so_list);
+      newobj = XCNEW (struct so_list);
 
       /* Encode FD and object ID in path name.  Choose the name so as not
         to conflict with any (normal) SVR4 library path name.  */
-      xsnprintf (new->so_name, sizeof new->so_name, "@0x%llx <%d>", addr, fd);
-      strcpy (new->so_original_name, new->so_name);
+      xsnprintf (newobj->so_name, sizeof newobj->so_name, "@%s <%d>",
+                hex_string (addr), fd);
+      strcpy (newobj->so_original_name, newobj->so_name);
 
-      *link_ptr = new;
-      link_ptr = &new->next;
+      *link_ptr = newobj;
+      link_ptr = &newobj->next;
     }
 
+  /* Append OpenCL sos.  */
+  append_ocl_sos (link_ptr);
+
   return head;
 }
 
@@ -230,7 +284,9 @@ static int
 spu_bfd_iovec_close (bfd *nbfd, void *stream)
 {
   xfree (stream);
-  return 1;
+
+  /* Zero means success.  */
+  return 0;
 }
 
 static file_ptr
@@ -240,7 +296,7 @@ spu_bfd_iovec_pread (bfd *abfd, void *stream, void *buf,
   CORE_ADDR addr = *(CORE_ADDR *)stream;
   int ret;
 
-  ret = target_read_memory (addr + offset, buf, nbytes);
+  ret = target_read_memory (addr + offset, (gdb_byte *) buf, nbytes);
   if (ret != 0)
     {
       bfd_set_error (bfd_error_invalid_operation);
@@ -258,40 +314,37 @@ spu_bfd_iovec_stat (bfd *abfd, void *stream, struct stat *sb)
      table to find the extent of the last section but that seems
      pointless when the size is needed only for checks of other
      parsed values in dbxread.c.  */
+  memset (sb, 0, sizeof (struct stat));
   sb->st_size = INT_MAX;
   return 0;
 }
 
-static bfd *
-spu_bfd_fopen (char *name, CORE_ADDR addr)
+static gdb_bfd_ref_ptr
+spu_bfd_fopen (const char *name, CORE_ADDR addr)
 {
-  bfd *nbfd;
+  CORE_ADDR *open_closure = XNEW (CORE_ADDR);
 
-  CORE_ADDR *open_closure = xmalloc (sizeof (CORE_ADDR));
   *open_closure = addr;
 
-  nbfd = bfd_openr_iovec (xstrdup (name), "elf32-spu",
-                          spu_bfd_iovec_open, open_closure,
-                          spu_bfd_iovec_pread, spu_bfd_iovec_close,
-                         spu_bfd_iovec_stat);
-  if (!nbfd)
+  gdb_bfd_ref_ptr nbfd (gdb_bfd_openr_iovec (name, "elf32-spu",
+                                            spu_bfd_iovec_open, open_closure,
+                                            spu_bfd_iovec_pread,
+                                            spu_bfd_iovec_close,
+                                            spu_bfd_iovec_stat));
+  if (nbfd == NULL)
     return NULL;
 
-  if (!bfd_check_format (nbfd, bfd_object))
-    {
-      bfd_close (nbfd);
-      return NULL;
-    }
+  if (!bfd_check_format (nbfd.get (), bfd_object))
+    return NULL;
 
   return nbfd;
 }
 
 /* Open shared library BFD.  */
-static bfd *
-spu_bfd_open (char *pathname)
+static gdb_bfd_ref_ptr
+spu_bfd_open (const char *pathname)
 {
-  char *original_name = strrchr (pathname, '@');
-  bfd *abfd;
+  const char *original_name = strrchr (pathname, '@');
   asection *spu_name;
   unsigned long long addr;
   int fd;
@@ -305,19 +358,23 @@ spu_bfd_open (char *pathname)
     internal_error (__FILE__, __LINE__, "bad object ID");
 
   /* Open BFD representing SPE executable.  */
-  abfd = spu_bfd_fopen (original_name, (CORE_ADDR) addr);
-  if (!abfd)
+  gdb_bfd_ref_ptr abfd (spu_bfd_fopen (original_name, (CORE_ADDR) addr));
+  if (abfd == NULL)
     error (_("Cannot read SPE executable at %s"), original_name);
 
   /* Retrieve SPU name note.  */
-  spu_name = bfd_get_section_by_name (abfd, ".note.spu_name");
+  spu_name = bfd_get_section_by_name (abfd.get (), ".note.spu_name");
   if (spu_name)
     {
-      int sect_size = bfd_section_size (abfd, spu_name);
+      int sect_size = bfd_section_size (abfd.get (), spu_name);
+
       if (sect_size > 20)
        {
-         char *buf = alloca (sect_size - 20 + strlen (original_name) + 1);
-         bfd_get_section_contents (abfd, spu_name, buf, 20, sect_size - 20);
+         char *buf
+           = (char *) alloca (sect_size - 20 + strlen (original_name) + 1);
+
+         bfd_get_section_contents (abfd.get (), spu_name, buf, 20,
+                                   sect_size - 20);
          buf[sect_size - 20] = '\0';
 
          strcat (buf, original_name);
@@ -331,27 +388,24 @@ spu_bfd_open (char *pathname)
 }
 
 /* Lookup global symbol in a SPE executable.  */
-static struct symbol *
-spu_lookup_lib_symbol (const struct objfile *objfile,
+static struct block_symbol
+spu_lookup_lib_symbol (struct objfile *objfile,
                       const char *name,
-                      const char *linkage_name,
                       const domain_enum domain)
 {
   if (bfd_get_arch (objfile->obfd) == bfd_arch_spu)
-    return lookup_global_symbol_from_objfile (objfile, name, linkage_name,
-                                             domain);
+    return lookup_global_symbol_from_objfile (objfile, name, domain);
 
   if (svr4_so_ops.lookup_lib_global_symbol != NULL)
-    return svr4_so_ops.lookup_lib_global_symbol (objfile, name, linkage_name,
-                                                domain);
-  return NULL;
+    return svr4_so_ops.lookup_lib_global_symbol (objfile, name, domain);
+  return (struct block_symbol) {NULL, NULL};
 }
 
 /* Enable shared library breakpoint.  */
 static int
 spu_enable_break (struct objfile *objfile)
 {
-  struct minimal_symbol *spe_event_sym = NULL;
+  struct bound_minimal_symbol spe_event_sym;
 
   /* The libspe library will call __spe_context_update_event whenever any
      SPE context is allocated or destroyed.  */
@@ -359,26 +413,60 @@ spu_enable_break (struct objfile *objfile)
                                         NULL, objfile);
 
   /* Place a solib_event breakpoint on the symbol.  */
-  if (spe_event_sym)
+  if (spe_event_sym.minsym)
     {
-      CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (spe_event_sym);
-      addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, addr,
+      CORE_ADDR addr = BMSYMBOL_VALUE_ADDRESS (spe_event_sym);
+
+      addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (), addr,
                                                  &current_target);
-      create_solib_event_breakpoint (target_gdbarch, addr);
+      create_solib_event_breakpoint (target_gdbarch (), addr);
       return 1;
     }
 
   return 0;
 }
 
-/* Create inferior hook.  */
+/* Enable shared library breakpoint for the
+   OpenCL runtime running on the SPU.  */
 static void
-spu_solib_create_inferior_hook (void)
+ocl_enable_break (struct objfile *objfile)
 {
-  /* Remove all previously installed solib breakpoints.  Both the SVR4
-     code and us will re-install all required breakpoints.  */
-  remove_solib_event_breakpoints ();
+  struct bound_minimal_symbol event_sym;
+  struct bound_minimal_symbol addr_sym;
+
+  /* The OpenCL runtime on the SPU will call __opencl_program_update_event
+     whenever an OpenCL program is loaded.  */
+  event_sym = lookup_minimal_symbol ("__opencl_program_update_event", NULL,
+                                    objfile);
+  /* The PPU address of the OpenCL program can be found
+     at opencl_elf_image_address.  */
+  addr_sym = lookup_minimal_symbol ("opencl_elf_image_address", NULL, objfile);
+
+  if (event_sym.minsym && addr_sym.minsym)
+    {
+      /* Place a solib_event breakpoint on the symbol.  */
+      CORE_ADDR event_addr = BMSYMBOL_VALUE_ADDRESS (event_sym);
+      create_solib_event_breakpoint (get_objfile_arch (objfile), event_addr);
+
+      /* Store the address of the symbol that will point to OpenCL program
+         using the per-objfile private data mechanism.  */
+      if (objfile_data (objfile, ocl_program_data_key) == NULL)
+        {
+          CORE_ADDR *ocl_program_addr_base = OBSTACK_CALLOC (
+                 &objfile->objfile_obstack,
+                 objfile->sections_end - objfile->sections,
+                 CORE_ADDR);
+         *ocl_program_addr_base = BMSYMBOL_VALUE_ADDRESS (addr_sym);
+         set_objfile_data (objfile, ocl_program_data_key,
+                           ocl_program_addr_base);
+        }
+    }
+}
 
+/* Create inferior hook.  */
+static void
+spu_solib_create_inferior_hook (int from_tty)
+{
   /* Handle SPE stand-alone executables.  */
   if (spu_standalone_p ())
     {
@@ -404,7 +492,7 @@ spu_solib_create_inferior_hook (void)
     }
 
   /* Call SVR4 hook -- this will re-insert the SVR4 solib breakpoints.  */
-  svr4_so_ops.solib_create_inferior_hook ();
+  svr4_so_ops.solib_create_inferior_hook (from_tty);
 
   /* If the inferior is statically linked against libspe, we need to install
      our own solib breakpoint right now.  Otherwise, it will be installed by
@@ -442,14 +530,22 @@ spu_solib_loaded (struct so_list *so)
 {
   if (strstr (so->so_original_name, "/libspe") != NULL)
     {
-      solib_read_symbols (so, so->from_tty ? SYMFILE_VERBOSE : 0);
+      solib_read_symbols (so, 0);
       spu_enable_break (so->objfile);
     }
+  /* In case the OpenCL runtime is loaded we install a breakpoint
+     to get notified whenever an OpenCL program gets loaded.  */
+  if (strstr (so->so_name, "CLRuntimeAccelCellSPU@") != NULL)
+    {
+      solib_read_symbols (so, 0);
+      ocl_enable_break (so->objfile);
+    }
 }
 
 void
 _initialize_spu_solib (void)
 {
-  observer_attach_solib_loaded (spu_solib_loaded);
+  gdb::observers::solib_loaded.attach (spu_solib_loaded);
+  ocl_program_data_key = register_objfile_data ();
 }
 
This page took 0.030455 seconds and 4 git commands to generate.