#include "defs.h" #include "top.h" #include "command.h" #include "gdbcmd.h" #include "completer.h" #include #include #include #include struct plugin_state { char **names; size_t num; void **plugin_data; }; void *_plugin_global_data; static struct plugin_state pstate; static int debug_plugins_flag = 0; void load_plugin (char *arg, int from_tty) { void (*fptr) () = NULL; char *init_func_name = "_init_from_gdb"; char *p, path[PATH_MAX+1]; if (arg == NULL) { error ("Usage: load-plugin "); return; } strcpy ( path, p = tilde_expand (arg)); xfree (p); if (debug_plugins_flag) { printf_unfiltered ("Loading GDB module from \"%s\"\n", arg); } { NSObjectFileImage image; NSObjectFileImageReturnCode nsret; NSSymbol sym; NSModule module; nsret = NSCreateObjectFileImageFromFile (path, &image); if (nsret != NSObjectFileImageSuccess) { error ("NSCreateObjectFileImageFromFile failed for \"%s\" (error %d).", path, nsret); } if (debug_plugins_flag) { printf_unfiltered ("Linking GDB module from \"%s\"\n", path); } module = NSLinkModule (image, path, NSLINKMODULE_OPTION_PRIVATE); /*module = NSLinkModule (image, path, NSLINKMODULE_OPTION_NONE);*/ if (module == NULL) { error ("NSLinkModule failed for \"%s\" (error %d).", path, nsret); } sym = NSLookupSymbolInModule (module, init_func_name); if (sym == NULL) { error("Unable to locate symbol '%s' in module.", init_func_name); } fptr = NSAddressOfSymbol (sym); if (fptr == NULL) { error ("Unable to locate address for symbol '%s' in module.", init_func_name); } } if (debug_plugins_flag) { printf_unfiltered ("Calling '%s' in \"%s\"\n", init_func_name, path); } CHECK_FATAL (fptr != NULL); /* Make sure the names and data arrays are updated BEFORE calling init_func_name() so that the plugin can use _plugin_private_data() */ pstate.plugin_data = xrealloc (pstate.plugin_data, (pstate.num + 1) * sizeof (void *)); pstate.plugin_data[pstate.num] = NULL; pstate.names = xrealloc (pstate.names, (pstate.num + 1) * sizeof (char *)); pstate.names[pstate.num] = xstrdup (path); pstate.num++; (* fptr) (); } void info_plugins_command (char *arg, int from_tty) { size_t i; for (i = 0; i < pstate.num; i++) { printf_unfiltered ("%s\n", pstate.names[i]); } } void _initialize_load_plugin () { struct cmd_list_element *cmd; pstate.names = NULL; pstate.num = 0; pstate.plugin_data = NULL; cmd = add_cmd ("load-plugin", class_obscure, load_plugin, "Usage: load-plugin \n" "Load a plugin from the specified path.", &cmdlist); cmd->completer = filename_completer; cmd->completer_word_break_characters = gdb_completer_filename_word_break_characters; cmd = add_set_cmd ("debug-plugins", class_obscure, var_boolean, (char *) &debug_plugins_flag, "Set if tracing of plugin loading is enabled", &setlist); add_show_from_set (cmd, &showlist); add_info ("plugins", info_plugins_command, "Show current plug-ins state."); } /* Search for a loaded plugin by name and return a pointer to it's private data slot allocated for plugin use. Return NULL if plugin is not loaded. If NULL is passed for a plugin name then a pointer to a global data pointer is returned. */ void **_plugin_private_data (char *plugin_name) { size_t i; char *p; if (plugin_name == NULL) return &_plugin_global_data; for (i = 0; i < pstate.num; i++) { p = strrchr (pstate.names[i], '/'); if (p) { if (strcmp (plugin_name, p+1) != 0) continue; } else if (strcmp (plugin_name, pstate.names[i]) != 0) continue; return &pstate.plugin_data[i]; } return NULL; }