This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch, spu] Detect OpenCL program executables
- From: Ken Werner <ken at linux dot vnet dot ibm dot com>
- To: gdb-patches at sourceware dot org
- Date: Fri, 25 Jun 2010 15:56:32 +0200
- Subject: [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 ();
}