This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch, spu] Detect OpenCL program executables


Hi,

OpenCL kernels are compiled and loaded at runtime but there is no way for GDB 
to detect that. The problem is similar to the handling of dynamic shared 
libraries. Unfortunately no such mechanism exists for OpenCL programs on the 
SPU. This patch extends the SPU solib code to append OpenCL programs to the 
list of `struct so_list' objects. As OpenCL programs are loaded dynamically, 
the OpenCL run-time cooperates with GDB and calls 
__opencl_program_update_event whenever a kernel is loaded and notifies the 
debugger on where the code resides in memory. This approach is very similar on 
how GDB communicates with libspe to handle SPU programs.

Regards,
-ken
2010-06-25  Ken Werner  <ken.werner@de.ibm.com>

	* solib-spu.c: Include "exception.h".
	(ocl_program_data_key): New variable.
        (append_ocl_sos): New function.
        (ocl_enable_break): Likewise.
	(spu_current_sos): Call append_ocl_sos.
	(spu_solib_loaded): Call ocl_enable_break.
	(_initialize_spu_solib): Register ocl_program_data_key.


Index: gdb/solib-spu.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-spu.c,v
retrieving revision 1.10
diff -u -p -r1.10 solib-spu.c
--- gdb/solib-spu.c	16 May 2010 23:49:58 -0000	1.10
+++ gdb/solib-spu.c	25 Jun 2010 11:53:56 -0000
@@ -34,6 +34,7 @@
 #include "observer.h"
 #include "breakpoint.h"
 #include "gdbthread.h"
+#include "exceptions.h"
 
 #include "spu-tdep.h"
 
@@ -94,6 +95,61 @@ spu_skip_standalone_loader (void)
     }
 }
 
+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 = 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;
+	  volatile struct gdb_exception ex;
+	  TRY_CATCH (ex, RETURN_MASK_ALL)
+	    {
+	      CORE_ADDR data =
+		read_memory_unsigned_integer (*ocl_program_addr_base,
+					      sizeof (CORE_ADDR),
+					      byte_order);
+	      if (data != 0x0)
+		{
+		  struct so_list *new;
+
+		  /* Allocate so_list structure.  */
+		  new = XZALLOC (struct so_list);
+
+		  /* Encode FD and object ID in path name.  */
+		  xsnprintf (new->so_name, sizeof new->so_name, "@0x%lx <%d>",
+			     data, SPUADDR_SPU (*ocl_program_addr_base));
+		  strcpy (new->so_original_name, new->so_name);
+
+		  *link_ptr = new;
+		  link_ptr = &new->next;
+		}
+	    }
+	  if (ex.reason < 0)
+	    {
+	      /* Ignore memory errors.  */
+	      switch (ex.error)
+		{
+		case MEMORY_ERROR:
+		  break;
+		default:
+		  throw_exception (ex);
+		  break;
+		}
+	    }
+	}
+    }
+}
+
 /* Build a list of `struct so_list' objects describing the shared
    objects currently loaded in the inferior.  */
 static struct so_list *
@@ -170,6 +226,9 @@ spu_current_sos (void)
       link_ptr = &new->next;
     }
 
+  /* Append OpenCL sos. */
+  append_ocl_sos (link_ptr);
+
   return head;
 }
 
@@ -365,6 +424,43 @@ spu_enable_break (struct objfile *objfil
   return 0;
 }
 
+/* Enable shared library breakpoint for the
+   OpenCL runtime running on the SPU.  */
+static void
+ocl_enable_break (struct objfile *objfile)
+{
+  struct minimal_symbol *event_sym = NULL;
+  struct minimal_symbol *addr_sym = NULL;
+
+  /* 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 && addr_sym)
+    {
+      /* Place a solib_event breakpoint on the symbol.  */
+      CORE_ADDR event_addr = SYMBOL_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 = SYMBOL_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)
@@ -435,11 +531,19 @@ spu_solib_loaded (struct so_list *so)
       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);
+  ocl_program_data_key = register_objfile_data ();
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]