* GDB C plugin system, and STL container viewer as an example
@ 2008-05-23 18:34 Vincent Benony
2008-05-23 19:30 ` Vladimir Prus
0 siblings, 1 reply; 9+ messages in thread
From: Vincent Benony @ 2008-05-23 18:34 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2010 bytes --]
Hello,
some days ago, I send here a (crap and buggy) patch that allows GDB to
display STL containers. I know that this patch was too intrusive and
dependent of the STL version.
Today, I wrote another patch that allows me to load plugin into GDB
that are called in particular situations, like displaying the content of
a variable of a particular type, or creating varobjects in MI
interpreter. It is used to format any kind of datas as I want it to be
displayed.
I submit a new version of my STL container viewer, but this time as a
plugin. It handles STL container access as it was a classic C array, and
answers queries like 'sizeof'... It also support MI interpreter, so that
GDB could be used with frontend, still displaying data correctly. I
tried it with Eclipse/CDT, KDevelop, KDBG, Nemiver and Insight/GDB. All
works well !
In order to compile the plugin, you'll have to modify the Makefile and
set the correct value for GDB_SOURCES variable.
After that, launch a GDB session, and execute the command
(gdb) loadplugin /path/to/plugin/stl.so
A typical session could look like that
(gdb) b 122
Breakpoint 1 at 0x8049602: file main.cpp, line 122.
(gdb) r
Starting program: /home/bsr/sources/stl/a.out
Breakpoint 1, main () at main.cpp:122
122 return 0;
(gdb) whatis m
type = std::map<const char*,int,std::less<const
char*>,std::allocator<std::pair<const char* const, int> > >
(gdb) p m
$1 = {
{
0x8051ec6 "un",
1
},
{
0x8051ec9 "deux",
2
},
{
0x8051ece "trois",
3
}
}
(gdb) p m[2]
$2 = {
first = 0x8051ece "trois",
second = 3
}
(gdb) p sizeof(m)
$3 = 12
(gdb) stlsizeof 1
sizeof operator on STL containers will print the number of elements.
(gdb) p sizeof(m)
$4 = 3
(gdb) ...
You could simply put the command into your ".gdbinit" to allow
frontends to use STL data formatter.
PS: I know that there is a Python scripting patch in progress. Mine is
only a small patch to allows people to use this feature today, waiting a
cleaner engine !
[-- Attachment #2: gdb-6.8-plugin.patch --]
[-- Type: text/x-patch, Size: 27559 bytes --]
diff -BNurw gdb-6.8/gdb/cli/cli-cmds.c gdb-6.8-patched/gdb/cli/cli-cmds.c
--- gdb-6.8/gdb/cli/cli-cmds.c 2008-01-01 23:53:14.000000000 +0100
+++ gdb-6.8-patched/gdb/cli/cli-cmds.c 2008-05-23 09:16:11.000000000 +0200
@@ -45,6 +45,8 @@
#include "cli/cli-setshow.h"
#include "cli/cli-cmds.h"
+#include "plugin.h"
+
#ifdef TUI
#include "tui/tui.h" /* For tui_active et.al. */
#endif
@@ -1159,6 +1161,16 @@
value);
}
+static void
+loadplugin_command (char *args, int from_tty)
+{
+ printf_unfiltered(_("Loading plugin \"%s\n"), args);
+ if (!load_plugin(args))
+ {
+ error (_("cannot load plugin."));
+ }
+}
+
\f
void
init_cli_cmds (void)
@@ -1423,4 +1435,10 @@
NULL,
NULL,
&setlist, &showlist);
+
+ source_help_text = xstrprintf (_("\
+Load a GDB plugin."));
+ c = add_cmd ("loadplugin", class_support, loadplugin_command,
+ source_help_text, &cmdlist);
+ set_cmd_completer (c, filename_completer);
}
diff -BNurw gdb-6.8/gdb/cp-valprint.c gdb-6.8-patched/gdb/cp-valprint.c
--- gdb-6.8/gdb/cp-valprint.c 2008-01-01 23:53:09.000000000 +0100
+++ gdb-6.8-patched/gdb/cp-valprint.c 2008-05-23 09:16:11.000000000 +0200
@@ -36,6 +36,7 @@
#include "valprint.h"
#include "cp-support.h"
#include "language.h"
+#include "plugin.h"
/* Controls printing of vtbl's */
int vtblprint;
@@ -161,6 +162,11 @@
CHECK_TYPEDEF (type);
+ if (plugins_try_print(type, address, stream, format, recurse, pretty))
+ {
+ return;
+ }
+
fprintf_filtered (stream, "{");
len = TYPE_NFIELDS (type);
n_baseclasses = TYPE_N_BASECLASSES (type);
diff -BNurw gdb-6.8/gdb/Makefile.in gdb-6.8-patched/gdb/Makefile.in
--- gdb-6.8/gdb/Makefile.in 2008-03-17 13:15:08.000000000 +0100
+++ gdb-6.8-patched/gdb/Makefile.in 2008-05-23 10:26:48.000000000 +0200
@@ -622,7 +622,7 @@
sentinel-frame.c \
serial.c ser-base.c ser-unix.c \
solib.c solib-null.c source.c \
- stabsread.c stack.c std-regs.c symfile.c symfile-mem.c symmisc.c \
+ stabsread.c stack.c std-regs.c plugin.c symfile.c symfile-mem.c symmisc.c \
symtab.c \
target.c target-descriptions.c target-memory.c \
thread.c top.c tracepoint.c \
@@ -885,6 +885,7 @@
srec_h = srec.h
stabsread_h = stabsread.h
stack_h = stack.h
+plugin_h = plugin.h
symfile_h = symfile.h $(symtab_h)
symtab_h = symtab.h
target_h = target.h $(bfd_h) $(symtab_h) $(dcache_h) $(memattr_h) $(vec_h)
@@ -1072,7 +1073,7 @@
tramp-frame.o \
solib.o solib-null.o \
prologue-value.o memory-map.o xml-support.o \
- target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
+ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o plugin.o
TSOBS = inflow.o
@@ -2012,7 +2013,9 @@
cp-valprint.o: cp-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \
$(gdbtypes_h) $(expression_h) $(value_h) $(command_h) $(gdbcmd_h) \
$(demangle_h) $(annotate_h) $(gdb_string_h) $(c_lang_h) $(target_h) \
- $(cp_abi_h) $(valprint_h) $(cp_support_h) $(language_h)
+ $(cp_abi_h) $(valprint_h) $(cp_support_h) $(language_h) $(plugin_h)
+plugin.o: $(defs_h) $(gdbtypes_h) $(block_h) $(gdbcore_h) \
+ $(value_h) $(expression_h) $(c_lang_h) $(varobj_h)
cris-tdep.o: cris-tdep.c $(defs_h) $(frame_h) $(frame_unwind_h) \
$(frame_base_h) $(trad_frame_h) $(dwarf2_frame_h) $(symtab_h) \
$(inferior_h) $(gdbtypes_h) $(gdbcore_h) $(gdbcmd_h) $(target_h) \
@@ -2078,7 +2081,7 @@
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
$(f_lang_h) $(cp_abi_h) $(infcall_h) $(objc_lang_h) $(block_h) \
$(parser_defs_h) $(cp_support_h) $(gdb_assert_h) $(exceptions_h) \
- $(uiout_h) $(regcache_h)
+ $(uiout_h) $(regcache_h) $(plugin_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h) $(exceptions_h) $(gdb_assert_h) $(gdb_select_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
@@ -2921,7 +2924,7 @@
$(regcache_h) $(dis_asm_h) $(osabi_h)
valarith.o: valarith.c $(defs_h) $(value_h) $(symtab_h) $(gdbtypes_h) \
$(expression_h) $(target_h) $(language_h) $(gdb_string_h) \
- $(doublest_h) $(dfp_h) $(infcall_h)
+ $(doublest_h) $(dfp_h) $(infcall_h) $(plugin_h)
valops.o: valops.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(value_h) $(frame_h) \
$(inferior_h) $(gdbcore_h) $(target_h) $(demangle_h) $(language_h) \
$(gdbcmd_h) $(regcache_h) $(cp_abi_h) $(block_h) $(infcall_h) \
@@ -2937,7 +2940,7 @@
$(gdb_assert_h) $(regcache_h) $(block_h) $(dfp_h)
varobj.o: varobj.c $(defs_h) $(exceptions_h) $(value_h) $(expression_h) \
$(frame_h) $(language_h) $(wrapper_h) $(gdbcmd_h) $(block_h) \
- $(gdb_assert_h) $(gdb_string_h) $(varobj_h) $(vec_h)
+ $(gdb_assert_h) $(gdb_string_h) $(varobj_h) $(vec_h) $(plugin_h)
vaxbsd-nat.o: vaxbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) $(target_h) \
$(vax_tdep_h) $(inf_ptrace_h) $(bsd_kvm_h)
vax-nat.o: vax-nat.c $(defs_h) $(inferior_h) $(gdb_assert_h) $(vax_tdep_h) \
diff -BNurw gdb-6.8/gdb/plugin.c gdb-6.8-patched/gdb/plugin.c
--- gdb-6.8/gdb/plugin.c 1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.8-patched/gdb/plugin.c 2008-05-23 10:22:20.000000000 +0200
@@ -0,0 +1,422 @@
+#include "defs.h"
+#include "c-lang.h"
+#include "plugin.h"
+#include "gdbtypes.h"
+#include "block.h"
+#include "gdbcore.h"
+#include "value.h"
+#include "varobj.h"
+#include "expression.h"
+#include "command.h"
+#include "completer.h"
+
+#include <dlfcn.h>
+#include <string.h>
+
+typedef int (*init_plugin_fct)(struct plugin_functions);
+typedef void (*uninit_plugin_fct)();
+typedef int (*type_handled_fct)(const char * type_name, int type_name_len);
+typedef int (*get_num_children_fct)(struct varobj * varobj);
+typedef int (*print_fct)(const char * type_name, int type_name_len, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty);
+typedef int (*operator_handled_fct)(const char *type_name, int type_name_len, enum exp_opcode op);
+typedef struct value * (*unary_operation_fct)(const char *type_name, int type_name_len, CORE_ADDR address, enum exp_opcode op);
+typedef struct value * (*binary_operation_fct)(const char *type_name, int type_name_len, CORE_ADDR address, struct value * other, enum exp_opcode op);
+typedef struct type * (*get_child_item_type_at_fct)(struct varobj *, int index);
+typedef struct value * (*get_child_item_value_at_fct)(struct varobj *, int index);
+
+struct loaded_plugin
+{
+ struct loaded_plugin * next;
+ int id;
+
+ void * module;
+
+ init_plugin_fct init;
+ uninit_plugin_fct uninit;
+ type_handled_fct type_handled;
+ get_num_children_fct get_num_children;
+ print_fct print;
+
+ operator_handled_fct operator_handled;
+ unary_operation_fct unary_operation;
+ binary_operation_fct binary_operation;
+
+ get_child_item_type_at_fct get_child_item_type_at;
+ get_child_item_value_at_fct get_child_item_value_at;
+};
+
+static int plugin_id = 1;
+static struct loaded_plugin * plugins = NULL;
+
+struct block * get_current_block()
+{
+ struct frame_info * current_frame = get_current_frame();
+ CORE_ADDR pc = get_frame_address_in_block(current_frame);
+ return block_for_pc(pc);
+}
+
+struct type * get_type(const char * name, struct block * block)
+{
+ struct type *type;
+ struct type *ptr_type;
+ char *rname = (char *)malloc(strlen(name) + 1);
+ char *old = rname;
+ int nbPtrs = 0;
+
+ strcpy(rname, name);
+ if (!strncmp(rname, "const ", 6)) rname += 6;
+ while (rname[strlen(rname) - 1] == '*')
+ {
+ nbPtrs++;
+ rname[strlen(rname) - 1] = 0;
+ }
+
+ while (rname[strlen(rname) - 1] == ' ')
+ {
+ rname[strlen(rname) - 1] = 0;
+ }
+
+ type = lookup_typename(rname, block, 1);
+ while (nbPtrs--)
+ {
+ ptr_type = NULL;
+ make_pointer_type(type, &ptr_type);
+ type = ptr_type;
+ }
+
+ free(old);
+ return type;
+}
+
+const char * get_type_name(struct type * type)
+{
+ if (type == NULL) return NULL;
+ return type->main_type->name;
+}
+
+int get_type_length(struct type * type)
+{
+ return TYPE_LENGTH(type);
+}
+
+void print(struct type * type, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty)
+{
+ gdb_byte * b = (gdb_byte *)malloc(TYPE_LENGTH(type));
+ read_memory(address, b, TYPE_LENGTH(type));
+ c_val_print(type, b, 0, address, stream, format, 0, recurse, pretty);
+ free(b);
+}
+
+CORE_ADDR get_value_address(struct value * value)
+{
+ return VALUE_ADDRESS(value) + value_offset(value);
+}
+
+void add_command(char *name, char *help, void (*handler)(char *, int), enum completer_type comp)
+{
+ extern struct cmd_list_element *cmdlist;
+ struct cmd_list_element *c;
+ c = add_cmd (name, class_support, handler, help, &cmdlist);
+ switch(comp)
+ {
+ case COMPLETE_FILENAME:
+ set_cmd_completer (c, filename_completer);
+ break;
+ case COMPLETE_LOCATION:
+ set_cmd_completer (c, location_completer);
+ break;
+ default:
+ break;
+ }
+}
+
+static struct plugin_functions all_functions =
+ {
+ add_command,
+ print_spaces_filtered,
+ printf_unfiltered,
+ printf_filtered,
+ fprintf_unfiltered,
+ fprintf_filtered,
+ get_current_block,
+ get_type,
+ get_type_name,
+ get_type_length,
+ read_memory_integer,
+ read_memory,
+ print,
+ value_at,
+ value_as_long,
+ value_from_longest,
+ get_value_address,
+ varobj_get_gdb_type,
+ varobj_get_gdb_value,
+ varobj_get_block
+ };
+
+int load_plugin(const char * filename)
+{
+ struct loaded_plugin * plugin;
+
+ void * module = dlopen(filename, RTLD_NOW | RTLD_DEEPBIND);
+ if (module == 0)
+ {
+ fprintf(stderr, "Cannot load plugin %s : cannot open file\n", filename);
+ fprintf(stderr, "%s\n", dlerror());
+ return 0;
+ }
+
+ plugin = (struct loaded_plugin *)malloc(sizeof(struct loaded_plugin));
+ plugin->module = module;
+ plugin->init = (init_plugin_fct) dlsym(module, "init_plugin");
+ plugin->uninit = (uninit_plugin_fct) dlsym(module, "uninit_plugin");
+ plugin->type_handled = (type_handled_fct) dlsym(module, "type_handled");
+ plugin->get_num_children = (get_num_children_fct) dlsym(module, "get_num_children");
+ plugin->print = (print_fct) dlsym(module, "print");
+ plugin->operator_handled = (operator_handled_fct) dlsym(module, "operator_handled");
+ plugin->unary_operation = (unary_operation_fct) dlsym(module, "unary_operation");
+ plugin->binary_operation = (binary_operation_fct) dlsym(module, "binary_operation");
+ plugin->get_child_item_type_at = (get_child_item_type_at_fct) dlsym(module, "get_child_item_type_at");
+ plugin->get_child_item_value_at = (get_child_item_value_at_fct)dlsym(module, "get_child_item_value_at");
+
+ if (plugin->init == 0
+ || plugin->uninit == 0
+ || plugin->type_handled == 0
+ || plugin->get_num_children == 0
+ || plugin->print == 0
+ || plugin->operator_handled == 0
+ || plugin->unary_operation == 0
+ || plugin->binary_operation == 0
+ || plugin->get_child_item_type_at == 0
+ || plugin->get_child_item_value_at == 0)
+ {
+ dlclose(module);
+ free(plugin);
+ fprintf(stderr, "Cannot load plugin %s : missing symbol\n", filename);
+ return 0;
+ }
+
+ if (!plugin->init(all_functions))
+ {
+ dlclose(plugin->module);
+ free(plugin);
+ fprintf(stderr, "Cannot load plugin %s : init_plugin return false\n", filename);
+ return 0;
+ }
+
+ plugin->next = plugins;
+ plugin->id = plugin_id++;
+ plugins = plugin;
+ return plugin->id;
+}
+
+void unload_plugin(int id)
+{
+ struct loaded_plugin * current = plugins;
+ struct loaded_plugin * previous = NULL;
+ while (current)
+ {
+ if (current->id == id)
+ {
+ dlclose(current->module);
+ if (previous)
+ {
+ previous->next = current->next;
+ }
+ else
+ {
+ plugins = current->next;
+ }
+ free(current);
+ return;
+ }
+ previous = current;
+ current = current->next;
+ }
+}
+
+int plugins_type_handled(struct type * type)
+{
+ const char * type_name;
+ int type_name_len;
+ struct loaded_plugin * plugin = plugins;
+
+ if (!type || !type->main_type || !type->main_type->name) return 0;
+ type_name = type->main_type->name;
+ type_name_len = strlen(type_name);
+
+ while (plugin)
+ {
+ if (plugin->type_handled(type_name, type_name_len))
+ {
+ return 1;
+ }
+ plugin = plugin->next;
+ }
+
+ return 0;
+}
+
+int plugins_try_print(struct type * type, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty)
+{
+ const char * type_name;
+ int type_name_len;
+ struct loaded_plugin * plugin = plugins;
+
+ if (!type || !type->main_type || !type->main_type->name) return 0;
+ type_name = type->main_type->name;
+ type_name_len = strlen(type_name);
+
+ while (plugin)
+ {
+ if (plugin->type_handled(type_name, type_name_len))
+ {
+ return plugin->print(type_name, type_name_len, address, stream, format, recurse, pretty);
+ }
+ plugin = plugin->next;
+ }
+
+ return 0;
+}
+
+int plugins_get_num_children(struct varobj * varobj)
+{
+ const char * type_name;
+ int type_name_len;
+ struct loaded_plugin * plugin = plugins;
+ struct type * type = varobj_get_gdb_type(varobj);
+
+ if (!type || !type->main_type || !type->main_type->name) return 0;
+ type_name = type->main_type->name;
+ type_name_len = strlen(type_name);
+
+ while (plugin)
+ {
+ if (plugin->type_handled(type_name, type_name_len))
+ {
+ return plugin->get_num_children(varobj);
+ }
+ plugin = plugin->next;
+ }
+
+ return 0;
+}
+
+int plugins_operator_handled(struct type * type, enum exp_opcode op)
+{
+ const char * type_name;
+ int type_name_len;
+ struct loaded_plugin * plugin = plugins;
+
+ if (!type || !type->main_type || !type->main_type->name) return 0;
+ type_name = type->main_type->name;
+ type_name_len = strlen(type_name);
+
+ while (plugin)
+ {
+ if (plugin->operator_handled(type_name, type_name_len, op))
+ {
+ return 1;
+ }
+ plugin = plugin->next;
+ }
+
+ return 0;
+}
+
+struct value * plugins_try_unary(struct value * arg, enum exp_opcode op)
+{
+ const char * type_name;
+ int type_name_len;
+ struct loaded_plugin * plugin = plugins;
+
+ struct type * type = check_typedef(value_type(arg));
+ CORE_ADDR addr_arg = VALUE_ADDRESS(arg) + value_offset(arg);
+
+ if (!type || !type->main_type || !type->main_type->name) return 0;
+ type_name = type->main_type->name;
+ type_name_len = strlen(type_name);
+
+ while (plugin)
+ {
+ if (plugin->operator_handled(type_name, type_name_len, op))
+ {
+ return plugin->unary_operation(type_name, type_name_len, addr_arg, op);
+ }
+ plugin = plugin->next;
+ }
+
+ return 0;
+}
+
+struct value * plugins_try_binary(struct value * arg1, struct value * arg2, enum exp_opcode op)
+{
+ const char * type_name;
+ int type_name_len;
+ struct loaded_plugin * plugin = plugins;
+
+ struct type * type = check_typedef(value_type(arg1));
+ CORE_ADDR addr_arg1 = VALUE_ADDRESS(arg1) + value_offset(arg1);
+
+ if (!type || !type->main_type || !type->main_type->name) return 0;
+ type_name = type->main_type->name;
+ type_name_len = strlen(type_name);
+
+ while (plugin)
+ {
+ if (plugin->operator_handled(type_name, type_name_len, op))
+ {
+ return plugin->binary_operation(type_name, type_name_len, addr_arg1, arg2, op);
+ }
+ plugin = plugin->next;
+ }
+
+ return 0;
+}
+
+struct type * plugins_get_child_item_type_at(struct varobj * varobj, int index)
+{
+ const char * type_name;
+ int type_name_len;
+ struct loaded_plugin * plugin = plugins;
+ struct type * type = varobj_get_gdb_type(varobj);
+
+ if (!type || !type->main_type || !type->main_type->name) return 0;
+ type_name = type->main_type->name;
+ type_name_len = strlen(type_name);
+
+ while (plugin)
+ {
+ if (plugin->type_handled(type_name, type_name_len))
+ {
+ return plugin->get_child_item_type_at(varobj, index);
+ }
+ plugin = plugin->next;
+ }
+
+ return 0;
+}
+
+struct value * plugins_get_child_item_value_at(struct varobj * varobj, int index)
+{
+ const char * type_name;
+ int type_name_len;
+ struct loaded_plugin * plugin = plugins;
+ struct type * type = varobj_get_gdb_type(varobj);
+
+ if (!type || !type->main_type || !type->main_type->name) return 0;
+ type_name = type->main_type->name;
+ type_name_len = strlen(type_name);
+
+ while (plugin)
+ {
+ if (plugin->type_handled(type_name, type_name_len))
+ {
+ return plugin->get_child_item_value_at(varobj, index);
+ }
+ plugin = plugin->next;
+ }
+
+ return 0;
+}
+
diff -BNurw gdb-6.8/gdb/plugin.h gdb-6.8-patched/gdb/plugin.h
--- gdb-6.8/gdb/plugin.h 1970-01-01 01:00:00.000000000 +0100
+++ gdb-6.8-patched/gdb/plugin.h 2008-05-23 10:21:59.000000000 +0200
@@ -0,0 +1,87 @@
+#ifndef PLUGIN_H__
+#define PLUGIN_H__
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "expression.h"
+
+struct type;
+struct block;
+struct ui_file;
+struct value;
+struct varobj;
+
+/*
+ * A plugin should implement those functions:
+ *
+ * int init_plugin(struct plugin_functions);
+ * void uninit_plugin();
+ *
+ * int type_handled(const char * type_name, int type_name_len);
+ * int get_num_children(struct varobj *varobj);
+ * int print(const char * type_name, int type_name_len, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty);
+ *
+ * int operator_handled(const char * type_name, int type_name_len, enum exp_opcode op);
+ * struct value * unary_operation(const char * type_name, int type_name_len, CORE_ADDR address, enum exp_opcode op);
+ * struct value * binary_operation(const char * type_name, int type_name_len, CORE_ADDR address, struct value * other, enum exp_opcode op);
+ *
+ * struct type * get_child_item_type_at(struct varobj *, int index);
+ * struct value * get_child_item_value_at(struct varobj *, int index);
+ */
+
+enum completer_type
+{
+ COMPLETE_FILENAME,
+ COMPLETE_LOCATION,
+ COMPLETE_NONE
+};
+
+/*
+ * Available function for plugins
+ */
+struct plugin_functions
+{
+ void (*add_cli_command)(char * name, char * help, void (*handler)(char *,int), enum completer_type comp);
+
+ void (*print_spaces_filtered)(int count, struct ui_file * stream);
+ void (*printf_unfiltered)(const char * format, ...);
+ void (*printf_filtered)(const char * format, ...);
+ void (*fprintf_unfiltered)(struct ui_file * stream, const char * format, ...);
+ void (*fprintf_filtered)(struct ui_file * stream, const char * format, ...);
+ struct block * (*get_current_block)();
+
+ struct type * (*get_type)(const char * name, struct block * block);
+ const char * (*get_type_name)(struct type * type);
+ int (*get_type_length)(struct type * type);
+
+ LONGEST (*read_memory_integer)(CORE_ADDR address, int size);
+ void (*read_memory)(CORE_ADDR address, gdb_byte * destination, int size);
+
+ void (*print)(struct type * type, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty);
+
+ struct value * (*value_at)(struct type * type, CORE_ADDR address);
+ LONGEST (*value_as_long)(struct value *);
+ struct value * (*value_from_longest)(struct type * type, LONGEST num);
+ CORE_ADDR (*get_value_address)(struct value *);
+
+ struct type * (*get_varobj_type)(struct varobj *);
+ struct value * (*get_varobj_value)(struct varobj *);
+ struct block * (*get_varobj_block)(struct varobj *);
+};
+
+int load_plugin(const char * filename);
+void unload_plugin(int id);
+
+int plugins_type_handled(struct type * type);
+int plugins_try_print(struct type * type, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty);
+int plugins_get_num_children(struct varobj * varobj);
+
+int plugins_operator_handled(struct type * type, enum exp_opcode op);
+struct value * plugins_try_unary(struct value * arg, enum exp_opcode op);
+struct value * plugins_try_binary(struct value * arg1, struct value * arg2, enum exp_opcode op);
+
+struct type * plugins_get_child_item_type_at(struct varobj * varobj, int index);
+struct value * plugins_get_child_item_value_at(struct varobj * varobj, int index);
+
+#endif
+
diff -BNurw gdb-6.8/gdb/valarith.c gdb-6.8-patched/gdb/valarith.c
--- gdb-6.8/gdb/valarith.c 2008-02-04 01:23:04.000000000 +0100
+++ gdb-6.8-patched/gdb/valarith.c 2008-05-23 10:21:35.000000000 +0200
@@ -31,6 +31,9 @@
#include "dfp.h"
#include <math.h>
#include "infcall.h"
+#include "block.h"
+#include "gdbcore.h"
+#include "plugin.h"
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C). */
@@ -309,6 +313,9 @@
if (TYPE_CODE (type2) == TYPE_CODE_REF)
type2 = check_typedef (TYPE_TARGET_TYPE (type2));
+ if (plugins_operator_handled(type1, op))
+ return 1;
+
return (TYPE_CODE (type1) == TYPE_CODE_STRUCT
|| TYPE_CODE (type2) == TYPE_CODE_STRUCT);
}
@@ -326,6 +334,10 @@
if (op == UNOP_ADDR)
return 0;
type1 = check_typedef (value_type (arg1));
+
+ if (plugins_operator_handled(type1, op))
+ return 1;
+
for (;;)
{
if (TYPE_CODE (type1) == TYPE_CODE_STRUCT)
@@ -354,12 +366,19 @@
char *ptr;
char tstr[13];
int static_memfuncp;
+ struct value * plugin_res;
arg1 = coerce_ref (arg1);
arg2 = coerce_ref (arg2);
arg1 = coerce_enum (arg1);
arg2 = coerce_enum (arg2);
+ plugin_res = plugins_try_binary(arg1, arg2, op);
+ if (plugin_res)
+ {
+ return plugin_res;
+ }
+
/* now we know that what we have to do is construct our
arg vector and find the right function to call it with. */
@@ -516,10 +535,17 @@
char *ptr, *mangle_ptr;
char tstr[13], mangle_tstr[13];
int static_memfuncp, nargs;
+ struct value * plugin_res;
arg1 = coerce_ref (arg1);
arg1 = coerce_enum (arg1);
+ plugin_res = plugins_try_unary(arg1, op);
+ if (plugin_res)
+ {
+ return plugin_res;
+ }
+
/* now we know that what we have to do is construct our
arg vector and find the right function to call it with. */
diff -BNurw gdb-6.8/gdb/varobj.c gdb-6.8-patched/gdb/varobj.c
--- gdb-6.8/gdb/varobj.c 2008-02-04 08:49:04.000000000 +0100
+++ gdb-6.8-patched/gdb/varobj.c 2008-05-23 09:16:11.000000000 +0200
@@ -24,6 +24,7 @@
#include "language.h"
#include "wrapper.h"
#include "gdbcmd.h"
+#include "gdbcore.h"
#include "block.h"
#include "gdb_assert.h"
@@ -32,6 +33,8 @@
#include "varobj.h"
#include "vec.h"
+#include "plugin.h"
+
/* Non-zero if we want to see trace of varobj level stuff. */
int varobjdebug = 0;
@@ -1151,6 +1154,17 @@
if (type_changed)
VEC_safe_push (varobj_p, result, *varp);
+ if (plugins_type_handled(varobj_get_gdb_type(*varp)))
+ {
+ int new_childs = plugins_get_num_children(*varp);
+ if (new_childs != (*varp)->num_children)
+ {
+ (*varp)->num_children = new_childs;
+ (*varp)->children = varobj_list_children (*varp);
+ VEC_safe_push (varobj_p, result, *varp);
+ }
+ }
+
if (install_new_value ((*varp), new, type_changed))
{
/* If type_changed is 1, install_new_value will never return
@@ -2222,6 +2236,7 @@
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
+ if (!plugins_type_handled(varobj_get_gdb_type(var)))
return xstrdup ("{...}");
/* break; */
@@ -2267,6 +2282,11 @@
struct type *type;
int children, dont_know;
+ if (plugins_type_handled(varobj_get_gdb_type(var)))
+ {
+ return plugins_get_num_children(var);
+ }
+
dont_know = 1;
children = 0;
@@ -2410,7 +2430,19 @@
|| TYPE_CODE (type) == TYPE_CODE_UNION)
{
char *join = was_ptr ? "->" : ".";
- if (CPLUS_FAKE_CHILD (parent))
+
+ if (plugins_type_handled(varobj_get_gdb_type(parent)))
+ {
+ if (cname)
+ *cname = xstrprintf("%d", index);
+ if (ctype)
+ *ctype = plugins_get_child_item_type_at(parent, index);
+ if (cvalue)
+ *cvalue = plugins_get_child_item_value_at(parent, index);
+ if (cfull_expression)
+ *cfull_expression = xstrprintf("(%s)[%d]", parent_expression, index);
+ }
+ else if (CPLUS_FAKE_CHILD (parent))
{
/* The fields of the class type are ordered as they
appear in the class. We are given an index for a
@@ -2725,3 +2757,15 @@
}
return;
}
+
+struct block *
+varobj_get_block (struct varobj *var)
+{
+ return var->root->valid_block;
+}
+
+struct value *
+varobj_get_gdb_value (struct varobj *var)
+{
+ return var->value;
+}
diff -BNurw gdb-6.8/gdb/varobj.h gdb-6.8-patched/gdb/varobj.h
--- gdb-6.8/gdb/varobj.h 2008-01-30 08:17:31.000000000 +0100
+++ gdb-6.8-patched/gdb/varobj.h 2008-05-23 09:16:11.000000000 +0200
@@ -61,6 +61,7 @@
/* Struct thar describes a variable object instance */
struct varobj;
+struct block;
typedef struct varobj *varobj_p;
DEF_VEC_P (varobj_p);
@@ -122,4 +123,8 @@
extern int varobj_editable_p (struct varobj *var);
+extern struct block * varobj_get_block (struct varobj *var);
+
+extern struct value * varobj_get_gdb_value (struct varobj *var);
+
#endif /* VAROBJ_H */
diff -BNurw gdb-6.8/gdb/eval.c gdb-6.8-patched/gdb/eval.c
--- gdb-6.8/gdb/eval.c 2008-02-04 01:23:04.000000000 +0100
+++ gdb-6.8-patched/gdb/eval.c 2008-05-23 10:47:30.000000000 +0200
@@ -41,6 +41,8 @@
#include "gdb_assert.h"
+#include "plugin.h"
+
/* This is defined in valops.c */
extern int overload_resolution;
@@ -2305,6 +2307,11 @@
case OP_VAR_VALUE:
(*pos) += 4;
type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
+ if (plugins_operator_handled(type, UNOP_SIZEOF))
+ {
+ val = value_of_variable(exp->elts[pc + 2].symbol, exp->elts[pc + 1].block);
+ return plugins_try_unary(val, UNOP_SIZEOF);
+ }
return
value_from_longest (builtin_type_int, (LONGEST) TYPE_LENGTH (type));
[-- Attachment #3: main.c --]
[-- Type: text/x-csrc, Size: 49323 bytes --]
#include "stdio.h"
#include "plugin.h"
#include <string.h>
static int stllimit = 0;
static int stlsizeof = 0;
static int stlprintcompatible = 1;
#define TREE_PARENT(A) ((CORE_ADDR)read_memory_integer ((A) + 1 * ptr_size, ptr_size))
#define TREE_LEFT(A) ((CORE_ADDR)read_memory_integer ((A) + 2 * ptr_size, ptr_size))
#define TREE_RIGHT(A) ((CORE_ADDR)read_memory_integer ((A) + 3 * ptr_size, ptr_size))
static struct plugin_functions ext_fcts;
void handle_stllimit(char * args, int from_tty)
{
if (args && strlen(args))
{
stllimit = atoi(args);
}
if (stllimit == 0)
{
ext_fcts.printf_unfiltered("STL limit set to UNLIMITED\n");
}
else
{
ext_fcts.printf_unfiltered("STL limit set to %d\n", stllimit);
}
}
void handle_stlstyle(char * args, int from_tty)
{
if (args && strlen(args))
{
stlprintcompatible = atoi(args);
}
ext_fcts.printf_unfiltered("STL container style %d\n", stlprintcompatible);
}
void handle_stlsizeof(char *args, int from_tty)
{
if (args && strlen(args))
{
stlsizeof = atoi(args);
}
if (stlsizeof)
{
ext_fcts.printf_unfiltered("sizeof operator on STL containers will print the number of elements.\n");
}
else
{
ext_fcts.printf_unfiltered("sizeof operator on STL containers will print the total size in bytes.\n");
}
}
int init_plugin(struct plugin_functions fcts)
{
ext_fcts = fcts;
ext_fcts.add_cli_command("stllimit", "Set the maximum number of element display for STL containers", handle_stllimit, COMPLETE_NONE);
ext_fcts.add_cli_command("stlstyle", "Set the display style of STL containers", handle_stlstyle, COMPLETE_NONE);
ext_fcts.add_cli_command("stlsizeof", "Set if sizeof(X) on an STL container should return the number of elements (argument != 0) or the total number of bytes (argument = 0).\n", handle_stlsizeof, COMPLETE_NONE);
ext_fcts.printf_unfiltered("GDB STL plugin loaded\n");
return 1;
}
void uninit_plugin()
{
}
/*
* helpers
*/
int get_stl_inner_type(const char * type_name, char *inner_type_name)
{
int level = 1;
char *pname = (char *)type_name;
while (*pname && *pname != '<') pname++;
if (*pname == 0)
{
// This is not a template !
*inner_type_name = 0;
return 0;
}
pname++;
while (!(level == 1 && *pname == ','))
{
if (*pname == '<') level++;
else if (*pname == '>') level--;
if (!(level == 1 && *pname == ',')) *inner_type_name++ = *pname++;
}
*inner_type_name = 0;
return 1;
}
int get_stl_inner_type_pair(const char * type_name, char *inner_type_key, char *inner_type_value, char *pair_name)
{
int level = 1;
char *pname = (char *)type_name;
while (*pname && *pname != '<') pname++;
if (*pname == 0)
{
// This is not a template !
*inner_type_key = 0;
*inner_type_value = 0;
return 0;
}
pname++;
while (!(level == 1 && *pname == ','))
{
if (*pname == '<') level++;
else if (*pname == '>') level--;
if (!(level == 1 && *pname == ',')) *inner_type_key++ = *pname++;
}
*inner_type_key = 0;
if (*pname == ',')
{
pname++;
while (!(level == 1 && *pname == ','))
{
if (*pname == '<') level++;
else if (*pname == '>') level--;
if (!(level == 1 && *pname == ',')) *inner_type_value++ = *pname++;
}
*inner_type_value = 0;
}
if (pair_name == NULL) return 1;
level = 0;
pname++;
while (!(level == 0 && *pname == ','))
{
if (*pname == '<') level++;
else if (*pname == '>') level--;
pname++;
}
pname++;
if (strncmp(pname, "std::allocator<std::pair<", 25))
{
puts(pname);
return 0;
}
pname += 15;
level = 0;
while (!(level == 0 && *pname == '>'))
{
if (*pname == '<') level++;
else if (*pname == '>') level--;
*pair_name++ = *pname++;
}
*pair_name++ = 0;
return 1;
}
struct type * get_stl_container_inner_type(struct varobj * var)
{
char * inner_name;
struct type * type = ext_fcts.get_varobj_type(var);
struct type * inner;
struct block * block = ext_fcts.get_varobj_block(var);
const char * type_name = ext_fcts.get_type_name(type);
inner_name = (char *)malloc(strlen(type_name) + 1);
if (!get_stl_inner_type(type_name, inner_name))
return NULL;
inner = ext_fcts.get_type(inner_name, block);
free(inner_name);
return inner;
}
/*
* printers
*/
void print_stl_vector(const char * type_name, int type_name_len,
CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
char *inner_name;
struct type *void_type;
struct type *inner_type;
struct block *block;
int ptr_size;
unsigned int idx;
CORE_ADDR begin;
CORE_ADDR end;
inner_name = (char *)malloc(type_name_len + 1);
if (get_stl_inner_type (type_name, inner_name))
{
if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "vector<%s>", inner_name);
ext_fcts.fprintf_filtered (stream, "{");
if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
block = ext_fcts.get_current_block();
inner_type = ext_fcts.get_type(inner_name, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (inner_type == NULL)
{
if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
ext_fcts.fprintf_filtered (stream, " // no information for type %s\n", inner_name);
}
else
{
idx = 0;
begin = (CORE_ADDR)ext_fcts.read_memory_integer(address, ptr_size);
end = (CORE_ADDR)ext_fcts.read_memory_integer(address + ptr_size, ptr_size);
while (begin != end)
{
if (stllimit && idx >= stllimit)
{
fprintf_filtered (stream, "...");
break;
}
if (pretty) ext_fcts.print_spaces_filtered(2 + 2 * recurse, stream);
if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
idx++;
ext_fcts.print(inner_type, begin, stream, format, recurse + 1, pretty);
begin += ext_fcts.get_type_length(inner_type);
if (begin != end) ext_fcts.fprintf_filtered(stream, ", ");
if (pretty)
{
ext_fcts.fprintf_filtered(stream, "\n");
}
}
}
if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
ext_fcts.fprintf_filtered (stream, "}");
if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
}
free(inner_name);
}
void print_stl_list(const char * type_name, int type_name_len,
CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
char *inner_name;
CORE_ADDR node;
CORE_ADDR data_ptr;
struct type *inner_type;
struct type *void_type;
struct block *block;
int ptr_size;
unsigned int idx;
inner_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type(type_name, inner_name))
{
if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "list<%s>", inner_name);
ext_fcts.fprintf_filtered (stream, "{");
if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
block = ext_fcts.get_current_block();
inner_type = ext_fcts.get_type(inner_name, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (inner_type == NULL)
{
if (pretty) ext_fcts.print_spaces_filtered(2 + 2 * recurse, stream);
ext_fcts.fprintf_filtered(stream, " // no information for type %s\n", inner_name);
}
else
{
idx = 0;
node = (CORE_ADDR)read_memory_integer (address, ptr_size);
while (node != address)
{
if (stllimit && idx >= stllimit)
{
ext_fcts.fprintf_filtered (stream, "...");
break;
}
data_ptr = (CORE_ADDR)(node + ptr_size * 2);
if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
idx++;
ext_fcts.print(inner_type, data_ptr, stream, format, recurse + 1, pretty);
node = (CORE_ADDR)ext_fcts.read_memory_integer (node, ptr_size);
if (node != address) ext_fcts.fprintf_filtered(stream, ", ");
if (pretty)
{
ext_fcts.fprintf_filtered(stream, "\n");
}
}
}
if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
ext_fcts.fprintf_filtered (stream, "}");
if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
}
free(inner_name);
}
void print_stl_set(const char * type_name, int type_name_len,
CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
char *inner_name;
CORE_ADDR node;
CORE_ADDR left;
CORE_ADDR tmp_node;
CORE_ADDR data_ptr;
struct type *inner_type;
struct type *void_type;
struct block *block;
int ptr_size;
unsigned int idx;
int count;
inner_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type(type_name, inner_name))
{
if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "set<%s>", inner_name);
ext_fcts.fprintf_filtered (stream, "{");
if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
block = ext_fcts.get_current_block();
inner_type = ext_fcts.get_type(inner_name, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (inner_type == NULL)
{
if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
ext_fcts.fprintf_filtered (stream, " // no information for type %s\n", inner_name);
}
else
{
node = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size);
count = (int)read_memory_integer(address + 5 * ptr_size, ptr_size);
for (idx=0; idx<count; idx++)
{
if (stllimit && idx >= stllimit)
{
ext_fcts.fprintf_filtered (stream, "...");
break;
}
data_ptr = (CORE_ADDR)(node + ptr_size * 4);
if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
ext_fcts.print(inner_type, data_ptr, stream, format, recurse + 1, pretty);
if (TREE_RIGHT(node) != 0)
{
node = TREE_RIGHT(node);
while ((left = TREE_LEFT(node)))
{
node = left;
}
}
else
{
tmp_node = TREE_PARENT(node);
while (node == TREE_RIGHT(node))
{
node = tmp_node;
tmp_node = TREE_PARENT(node);
}
if (TREE_RIGHT(node) != tmp_node)
{
node = tmp_node;
}
}
if (idx != count - 1) ext_fcts.fprintf_filtered(stream, ", ");
if (pretty)
{
ext_fcts.fprintf_filtered(stream, "\n");
}
}
}
if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
ext_fcts.fprintf_filtered (stream, "}");
if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
}
free(inner_name);
}
void print_stl_map(const char * type_name, int type_name_len,
CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
char *inner_key;
char *inner_value;
CORE_ADDR node;
CORE_ADDR left;
CORE_ADDR tmp_node;
CORE_ADDR data_ptr;
struct type *inner_type_key;
struct type *inner_type_value;
struct type *void_type;
struct block *block;
int ptr_size;
unsigned int idx;
int count;
inner_key = (char *)malloc(strlen(type_name) + 1);
inner_value = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type_pair(type_name, inner_key, inner_value, NULL))
{
if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "map<%s, %s>", inner_key, inner_value);
ext_fcts.fprintf_filtered (stream, "{");
if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
block = ext_fcts.get_current_block();
inner_type_key = ext_fcts.get_type(inner_key, block);
inner_type_value = ext_fcts.get_type(inner_value, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (inner_type_key == NULL || inner_type_value == NULL)
{
if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
ext_fcts.fprintf_filtered (stream, " // no information for type std::pair<%s, %s>\n", inner_key, inner_value);
}
else
{
node = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size);
count = (int)read_memory_integer(address + 5 * ptr_size, ptr_size);
for (idx=0; idx<count; idx++)
{
if (stllimit && idx >= stllimit)
{
ext_fcts.fprintf_filtered (stream, "...");
break;
}
data_ptr = (CORE_ADDR)(node + ptr_size * 4);
if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
ext_fcts.fprintf_filtered (stream, "{");
if (pretty) ext_fcts.fprintf_filtered(stream, "\n");
if (pretty) ext_fcts.print_spaces_filtered (4 + 2 * recurse, stream);
if (!stlprintcompatible)
{
ext_fcts.fprintf_filtered(stream, "key ");
if (pretty) ext_fcts.fprintf_filtered(stream, " ");
ext_fcts.fprintf_filtered(stream, "= ");
}
ext_fcts.print(inner_type_key, data_ptr, stream, format, recurse + 3, pretty);
if (pretty) ext_fcts.fprintf_filtered(stream, ",\n"); else ext_fcts.fprintf_filtered(stream, ", ");
if (pretty) ext_fcts.print_spaces_filtered (4 + 2 * recurse, stream);
if (!stlprintcompatible)
{
ext_fcts.fprintf_filtered(stream, "value = ");
}
ext_fcts.print(inner_type_value, data_ptr + ptr_size, stream, format, recurse + 3, pretty);
if (pretty) ext_fcts.fprintf_filtered(stream, "\n");
if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
ext_fcts.fprintf_filtered(stream, "}");
if (TREE_RIGHT(node) != 0)
{
node = TREE_RIGHT(node);
while ((left = TREE_LEFT(node)))
{
node = left;
}
}
else
{
tmp_node = TREE_PARENT(node);
while (node == TREE_RIGHT(node))
{
node = tmp_node;
tmp_node = TREE_PARENT(node);
}
if (TREE_RIGHT(node) != tmp_node)
{
node = tmp_node;
}
}
if (idx != count - 1) ext_fcts.fprintf_filtered(stream, ", ");
if (pretty)
{
ext_fcts.fprintf_filtered(stream, "\n");
}
}
}
if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
ext_fcts.fprintf_filtered (stream, "}");
if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
}
free(inner_key);
free(inner_value);
}
void print_stl_deque(const char * type_name, int type_name_len,
CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
char *inner_name;
CORE_ADDR node;
CORE_ADDR data_ptr;
CORE_ADDR map;
CORE_ADDR cur_node;
int iter_beg_cur;
int iter_beg_first;
int iter_beg_last;
int iter_beg_node;
int iter_end_cur;
int iter_end_first;
int iter_end_last;
int iter_end_node;
int elems_per_nodes;
int size;
struct type *inner_type;
struct type *void_type;
struct block *block;
int ptr_size;
unsigned int idx;
int nodes_rem;
inner_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type(type_name, inner_name))
{
if (!stlprintcompatible) ext_fcts.fprintf_filtered (stream, "deque<%s>", inner_name);
ext_fcts.fprintf_filtered (stream, "{");
if (pretty) ext_fcts.fprintf_filtered (stream, "\n");
block = ext_fcts.get_current_block();
inner_type = ext_fcts.get_type(inner_name, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (inner_type == NULL)
{
if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
ext_fcts.fprintf_filtered (stream, " // no information for type %s\n", inner_name);
}
else
{
map = read_memory_integer (address, ptr_size);
iter_beg_cur = read_memory_integer (address + ptr_size * 2, ptr_size);
iter_beg_first = read_memory_integer (address + ptr_size * 3, ptr_size);
iter_beg_last = read_memory_integer (address + ptr_size * 4, ptr_size);
iter_beg_node = read_memory_integer (address + ptr_size * 5, ptr_size);
iter_end_cur = read_memory_integer (address + ptr_size * 6, ptr_size);
iter_end_first = read_memory_integer (address + ptr_size * 7, ptr_size);
iter_end_last = read_memory_integer (address + ptr_size * 8, ptr_size);
iter_end_node = read_memory_integer (address + ptr_size * 9, ptr_size);
elems_per_nodes = TYPE_LENGTH(inner_type) < 512 ? 512 / TYPE_LENGTH(inner_type) : 1;
size = ( elems_per_nodes * (iter_end_node - iter_beg_node - ptr_size) + (iter_end_cur - iter_end_first) + (iter_beg_last - iter_beg_cur) ) / ptr_size;
idx = 0;
nodes_rem = elems_per_nodes;
data_ptr = iter_beg_cur;
cur_node = iter_beg_node;
while (idx < size)
{
if (stllimit && idx >= stllimit)
{
ext_fcts.fprintf_filtered (stream, "...");
break;
}
if (nodes_rem)
{
if (pretty) ext_fcts.print_spaces_filtered (2 + 2 * recurse, stream);
if (!stlprintcompatible) ext_fcts.fprintf_filtered(stream, "[%d] = ", idx);
ext_fcts.print(inner_type, data_ptr, stream, format, recurse + 1, pretty);
if (idx != size - 1) ext_fcts.fprintf_filtered(stream, ", ");
if (pretty) ext_fcts.fprintf_filtered(stream, "\n");
data_ptr += TYPE_LENGTH(inner_type);
nodes_rem--;
idx++;
}
else
{
nodes_rem = elems_per_nodes;
cur_node += ptr_size;
data_ptr = read_memory_integer (cur_node, ptr_size);
}
}
if (pretty) ext_fcts.print_spaces_filtered (2 * recurse, stream);
ext_fcts.fprintf_filtered (stream, "}");
if (recurse == 0) ext_fcts.fprintf_filtered (stream, "\n");
}
}
free(inner_name);
}
void print_stl_string(const char * type_name, int type_name_len,
CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
struct type *char_type;
struct block *block;
int ptr_size;
CORE_ADDR string_ptr;
block = ext_fcts.get_current_block();
char_type = ext_fcts.get_type("char *", block);
ptr_size = ext_fcts.get_type_length(char_type);
string_ptr = ext_fcts.read_memory_integer(address, ptr_size);
val_print_string(string_ptr, -1, 1, stream);
}
/*
* getters
*/
struct value * get_stl_list_item_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
char *inner_name;
CORE_ADDR node;
CORE_ADDR data_ptr;
struct type *inner_type;
struct type *void_type;
struct block *block;
int ptr_size;
unsigned int idx;
if (index < 0) return NULL;
inner_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type(type_name, inner_name))
{
block = ext_fcts.get_current_block();
inner_type = ext_fcts.get_type(inner_name, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (inner_type == NULL)
{
free(inner_name);
return NULL;
}
else
{
idx = 0;
node = (CORE_ADDR)ext_fcts.read_memory_integer(address, ptr_size);
while (node != address && idx <= index)
{
if (idx == index)
{
free(inner_name);
return ext_fcts.value_at(inner_type, (CORE_ADDR)(node + ptr_size * 2));
}
node = (CORE_ADDR)ext_fcts.read_memory_integer (node, ptr_size);
idx++;
}
}
}
free(inner_name);
return NULL;
}
struct value * get_stl_vector_item_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
char *inner_name;
struct type *void_type;
struct type *inner_type;
struct block *block;
int ptr_size;
CORE_ADDR begin;
CORE_ADDR end;
if (index < 0) return NULL;
inner_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type(type_name, inner_name))
{
block = ext_fcts.get_current_block();
inner_type = ext_fcts.get_type(inner_name, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (inner_type == NULL)
{
free(inner_name);
return NULL;
}
else
{
begin = (CORE_ADDR)read_memory_integer (address, ptr_size);
end = (CORE_ADDR)read_memory_integer (address + ptr_size, ptr_size);
begin += index * TYPE_LENGTH (inner_type);
if (begin >= end)
{
free(inner_name);
return NULL;
}
return ext_fcts.value_at(inner_type, begin);
}
}
free(inner_name);
return NULL;
}
struct value * get_stl_set_item_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
char *inner_name;
CORE_ADDR node;
CORE_ADDR left;
CORE_ADDR tmp_node;
CORE_ADDR data_ptr;
struct type *inner_type;
struct type *void_type;
struct block *block;
int ptr_size;
unsigned int idx;
int count;
if (index < 0) return NULL;
inner_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type(type_name, inner_name))
{
block = ext_fcts.get_current_block();
inner_type = ext_fcts.get_type(inner_name, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (inner_type == NULL)
{
free(inner_name);
return NULL;
}
else
{
node = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size);
count = (int)read_memory_integer(address + 5 * ptr_size, ptr_size);
if (index >= count)
{
free(inner_name);
return NULL;
}
for (idx=0; idx<index; idx++)
{
if (TREE_RIGHT(node) != 0)
{
node = TREE_RIGHT(node);
while ((left = TREE_LEFT(node)))
{
node = left;
}
}
else
{
tmp_node = TREE_PARENT(node);
while (node == TREE_RIGHT(node))
{
node = tmp_node;
tmp_node = TREE_PARENT(node);
}
if (TREE_RIGHT(node) != tmp_node)
{
node = tmp_node;
}
}
}
free(inner_name);
return ext_fcts.value_at(inner_type, (CORE_ADDR)(node + ptr_size * 4));
}
}
free(inner_name);
return NULL;
}
struct value * get_stl_map_pair_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
char *inner_key;
char *inner_value;
char *pair_name;
CORE_ADDR node;
CORE_ADDR left;
CORE_ADDR tmp_node;
CORE_ADDR data_ptr;
struct type *void_type;
struct type *pair_type;
struct block *block;
int ptr_size;
unsigned int idx;
int count;
if (index < 0) return NULL;
inner_key = (char *)malloc(strlen(type_name) + 1);
inner_value = (char *)malloc(strlen(type_name) + 1);
pair_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type_pair(type_name, inner_key, inner_value, pair_name))
{
block = ext_fcts.get_current_block();
pair_type = ext_fcts.get_type(pair_name, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (pair_type == NULL)
{
free (inner_key);
free (inner_value);
free (pair_name);
return NULL;
}
else
{
node = (CORE_ADDR)read_memory_integer (address + 3 * ptr_size, ptr_size);
count = (int)read_memory_integer(address + 5 * ptr_size, ptr_size);
if (index >= count)
{
free (inner_key);
free (inner_value);
free (pair_name);
return NULL;
}
for (idx=0; idx<index; idx++)
{
if (TREE_RIGHT(node) != 0)
{
node = TREE_RIGHT(node);
while ((left = TREE_LEFT(node)))
{
node = left;
}
}
else
{
tmp_node = TREE_PARENT(node);
while (node == TREE_RIGHT(node))
{
node = tmp_node;
tmp_node = TREE_PARENT(node);
}
if (TREE_RIGHT(node) != tmp_node)
{
node = tmp_node;
}
}
}
free (inner_key);
free (inner_value);
free (pair_name);
return ext_fcts.value_at(pair_type, (CORE_ADDR)(node + ptr_size * 4));
}
}
free(inner_key);
free(inner_value);
free (pair_name);
return NULL;
}
struct value * get_stl_deque_item_at(const char * type_name, int type_name_len, CORE_ADDR address, int index)
{
char *inner_name;
CORE_ADDR node;
CORE_ADDR data_ptr;
CORE_ADDR map;
CORE_ADDR cur_node;
int iter_beg_cur;
int iter_beg_first;
int iter_beg_last;
int iter_beg_node;
int iter_end_cur;
int iter_end_first;
int iter_end_last;
int iter_end_node;
int elems_per_nodes;
int size;
struct type *inner_type;
struct type *void_type;
struct block *block;
int ptr_size;
unsigned int idx;
int nodes_rem;
if (index < 0) return NULL;
inner_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type(type_name, inner_name))
{
block = ext_fcts.get_current_block();
inner_type = ext_fcts.get_type(inner_name, block);
void_type = ext_fcts.get_type("void *", block);
ptr_size = ext_fcts.get_type_length(void_type);
if (inner_type == NULL)
{
free(inner_name);
return NULL;
}
else
{
map = read_memory_integer (address, ptr_size);
iter_beg_cur = read_memory_integer (address + ptr_size * 2, ptr_size);
iter_beg_first = read_memory_integer (address + ptr_size * 3, ptr_size);
iter_beg_last = read_memory_integer (address + ptr_size * 4, ptr_size);
iter_beg_node = read_memory_integer (address + ptr_size * 5, ptr_size);
iter_end_cur = read_memory_integer (address + ptr_size * 6, ptr_size);
iter_end_first = read_memory_integer (address + ptr_size * 7, ptr_size);
iter_end_last = read_memory_integer (address + ptr_size * 8, ptr_size);
iter_end_node = read_memory_integer (address + ptr_size * 9, ptr_size);
elems_per_nodes = TYPE_LENGTH(inner_type) < 512 ? 512 / TYPE_LENGTH(inner_type) : 1;
size = ( elems_per_nodes * (iter_end_node - iter_beg_node - ptr_size) + (iter_end_cur - iter_end_first) + (iter_beg_last - iter_beg_cur) ) / ptr_size;
idx = 0;
nodes_rem = elems_per_nodes;
data_ptr = iter_beg_cur;
cur_node = iter_beg_node;
if (index >= size)
{
free(inner_name);
return NULL;
}
while (idx < size)
{
if (index == idx)
{
free(inner_name);
return ext_fcts.value_at(inner_type, data_ptr);
}
if (nodes_rem)
{
nodes_rem--;
data_ptr += TYPE_LENGTH(inner_type);
idx++;
}
else
{
nodes_rem = elems_per_nodes;
cur_node += ptr_size;
data_ptr = read_memory_integer (cur_node, ptr_size);
}
}
}
}
free(inner_name);
return NULL;
}
int get_stl_list_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
int children = 0;
char * inner_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type(type_name, inner_name))
{
struct type * void_type = ext_fcts.get_type("void *", block);
struct type * inner_type = ext_fcts.get_type(inner_name, block);
int ptr_size = ext_fcts.get_type_length(void_type);
CORE_ADDR node = (CORE_ADDR)read_memory_integer (varadr, ptr_size);
while (node != varadr)
{
node = (CORE_ADDR)ext_fcts.read_memory_integer (node, ptr_size);
children++;
}
}
free (inner_name);
return children;
}
int get_stl_list_size_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (!type) return 0;
return get_stl_list_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}
int get_stl_vector_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
int children = 0;
char * inner_name = (char *)malloc(strlen(type_name) + 1);
if (get_stl_inner_type(type_name, inner_name))
{
struct type * void_type = ext_fcts.get_type("void *", block);
struct type * inner_type = ext_fcts.get_type(inner_name, block);
int ptr_size = ext_fcts.get_type_length(void_type);
CORE_ADDR begin = (CORE_ADDR)read_memory_integer (varadr, ptr_size);
CORE_ADDR end = (CORE_ADDR)read_memory_integer (varadr + ptr_size, ptr_size);
children = (end - begin) / TYPE_LENGTH (inner_type);
}
free (inner_name);
return children;
}
int get_stl_vector_size_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (!type) return 0;
return get_stl_vector_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}
int get_stl_set_or_multiset_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
struct type * void_type = ext_fcts.get_type("void *", block);
int ptr_size = ext_fcts.get_type_length(void_type);
return (int)read_memory_integer(varadr + 5 * ptr_size, ptr_size);
}
int get_stl_set_or_multiset_size_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (!type) return 0;
return get_stl_set_or_multiset_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}
int get_stl_map_or_multimap_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
struct type * void_type = ext_fcts.get_type("void *", block);
int ptr_size = ext_fcts.get_type_length(void_type);
return (int)read_memory_integer(varadr + 5 * ptr_size, ptr_size);
}
int get_stl_map_or_multimap_size_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (!type) return 0;
return get_stl_map_or_multimap_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}
int get_stl_deque_size(const char * type_name, struct block * block, CORE_ADDR varadr)
{
char * inner_name = (char *)malloc(strlen(type_name) + 1);
struct type * void_type = ext_fcts.get_type("void *", block);
int ptr_size = ext_fcts.get_type_length(void_type);
if (get_stl_inner_type(type_name, inner_name))
{
struct type * inner_type = ext_fcts.get_type(inner_name, block);
int iter_beg_cur = read_memory_integer (varadr + ptr_size * 2, ptr_size);
int iter_beg_first = read_memory_integer (varadr + ptr_size * 3, ptr_size);
int iter_beg_last = read_memory_integer (varadr + ptr_size * 4, ptr_size);
int iter_beg_node = read_memory_integer (varadr + ptr_size * 5, ptr_size);
int iter_end_cur = read_memory_integer (varadr + ptr_size * 6, ptr_size);
int iter_end_first = read_memory_integer (varadr + ptr_size * 7, ptr_size);
int iter_end_last = read_memory_integer (varadr + ptr_size * 8, ptr_size);
int iter_end_node = read_memory_integer (varadr + ptr_size * 9, ptr_size);
int elems_per_nodes = ext_fcts.get_type_length(inner_type) < 512 ? 512 / ext_fcts.get_type_length(inner_type) : 1;
return ( elems_per_nodes * (iter_end_node - iter_beg_node - ptr_size) + (iter_end_cur - iter_end_first) + (iter_beg_last - iter_beg_cur) ) / ptr_size;
}
return 0;
}
int get_stl_deque_size_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (!type) return 0;
return get_stl_deque_size(ext_fcts.get_type_name(type), ext_fcts.get_varobj_block(var), ext_fcts.get_value_address(ext_fcts.get_varobj_value(var)));
}
/*
* predicates
*/
int is_stl_vector_from_name(const char * name, int len)
{
if (len > 2 && name[len - 1] == '>')
{
if (!strncmp(name, "std::vector<", 12))
return 1;
if (!strncmp(name, "std::_Vector_base<", 18))
return 1;
}
return 0;
}
int is_stl_list_from_name(const char * name, int len)
{
if (len > 2 && name[len - 1] == '>')
{
if (!strncmp(name, "std::list<", 10))
return 1;
if (!strncmp(name, "std::_List_base<", 16))
return 1;
}
return 0;
}
int is_stl_set_or_multiset_from_name(const char * name, int len)
{
if (len > 2 && name[len - 1] == '>')
{
if (!strncmp(name, "std::set<", 9))
return 1;
if (!strncmp(name, "std::multiset<", 14))
return 1;
if (!strncmp(name, "std::_Rb_tree<", 14))
return 1;
}
return 0;
}
int is_stl_map_or_multimap_from_name(const char * name, int len)
{
if (len > 2 && name[len - 1] == '>')
{
if (!strncmp(name, "std::map<", 9))
return 1;
if (!strncmp(name, "std::multimap<", 14))
return 1;
}
return 0;
}
int is_stl_deque_from_name(const char * name, int len)
{
if (len > 2 && name[len - 1] == '>')
{
if (!strncmp(name, "std::deque<", 11))
return 1;
if (!strncmp(name, "std::_Deque_base<", 17))
return 1;
}
return 0;
}
int is_stl_string_from_name(const char * name, int len)
{
len = strlen (name);
if (len > 2 && name[len - 1] == '>' && !strncmp(name, "std::basic_string<char,", 23))
return 1;
return 0;
}
int is_stl_vector_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (type)
{
const char * type_name = ext_fcts.get_type_name(type);
int len = strlen(type_name);
return is_stl_vector_from_name(type_name, len);
}
return 0;
}
int is_stl_list_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (type)
{
const char * type_name = ext_fcts.get_type_name(type);
int len = strlen(type_name);
return is_stl_list_from_name(type_name, len);
}
return 0;
}
int is_stl_map_or_multimap_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (type)
{
const char * type_name = ext_fcts.get_type_name(type);
int len = strlen(type_name);
return is_stl_map_or_multimap_from_name(type_name, len);
}
return 0;
}
int is_stl_set_or_multiset_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (type)
{
const char * type_name = ext_fcts.get_type_name(type);
int len = strlen(type_name);
return is_stl_set_or_multiset_from_name(type_name, len);
}
return 0;
}
int is_stl_deque_from_varobj(struct varobj * var)
{
struct type * type = ext_fcts.get_varobj_type(var);
if (type)
{
const char * type_name = ext_fcts.get_type_name(type);
int len = strlen(type_name);
return is_stl_deque_from_name(type_name, len);
}
return 0;
}
int type_handled(const char * type_name, int type_name_len)
{
if (is_stl_vector_from_name(type_name, type_name_len)
|| is_stl_list_from_name(type_name, type_name_len)
|| is_stl_set_or_multiset_from_name(type_name, type_name_len)
|| is_stl_map_or_multimap_from_name(type_name, type_name_len)
|| is_stl_deque_from_name(type_name, type_name_len)
|| is_stl_string_from_name(type_name, type_name_len))
{
return 1;
}
return 0;
}
int get_num_children(struct varobj *varobj)
{
if (is_stl_vector_from_varobj(varobj))
{
return get_stl_vector_size_from_varobj(varobj);
}
else if (is_stl_list_from_varobj(varobj))
{
return get_stl_list_size_from_varobj(varobj);
}
else if (is_stl_map_or_multimap_from_varobj(varobj))
{
return get_stl_map_or_multimap_size_from_varobj(varobj);
}
else if (is_stl_set_or_multiset_from_varobj(varobj))
{
return get_stl_set_or_multiset_size_from_varobj(varobj);
}
else if (is_stl_deque_from_varobj(varobj))
{
return get_stl_deque_size_from_varobj(varobj);
}
return 0;
}
int print(const char * type_name, int type_name_len, CORE_ADDR address, struct ui_file * stream, int format, int recurse, enum val_prettyprint pretty)
{
if (is_stl_vector_from_name(type_name, type_name_len))
{
print_stl_vector(type_name, type_name_len, address, stream, format, recurse, pretty);
return 1;
}
else if (is_stl_list_from_name(type_name, type_name_len))
{
print_stl_list(type_name, type_name_len, address, stream, format, recurse, pretty);
return 1;
}
else if (is_stl_set_or_multiset_from_name(type_name, type_name_len))
{
print_stl_set(type_name, type_name_len, address, stream, format, recurse, pretty);
return 1;
}
else if (is_stl_map_or_multimap_from_name(type_name, type_name_len))
{
print_stl_map(type_name, type_name_len, address, stream, format, recurse, pretty);
return 1;
}
else if (is_stl_deque_from_name(type_name, type_name_len))
{
print_stl_deque(type_name, type_name_len, address, stream, format, recurse, pretty);
return 1;
}
else if (is_stl_string_from_name(type_name, type_name_len))
{
print_stl_string(type_name, type_name_len, address, stream, format, recurse, pretty);
return 1;
}
return 0;
}
int operator_handled(const char * type_name, int type_name_len, enum exp_opcode op)
{
if (is_stl_vector_from_name(type_name, type_name_len)
|| is_stl_list_from_name(type_name, type_name_len)
|| is_stl_set_or_multiset_from_name(type_name, type_name_len)
|| is_stl_map_or_multimap_from_name(type_name, type_name_len)
|| is_stl_deque_from_name(type_name, type_name_len))
{
if (op == BINOP_SUBSCRIPT) return 1;
if (op == UNOP_LENGTH) return 1;
if (op == UNOP_SIZEOF) return 1;
}
return 0;
}
struct value * unary_operation(const char * type_name, int type_name_len, CORE_ADDR address, enum exp_opcode op)
{
int size = 0;
switch(op)
{
case UNOP_LENGTH:
case UNOP_SIZEOF:
if (is_stl_vector_from_name(type_name, type_name_len))
{
size = get_stl_vector_size(type_name, ext_fcts.get_current_block(), address);
}
else if (is_stl_list_from_name(type_name, type_name_len))
{
size = get_stl_list_size(type_name, ext_fcts.get_current_block(), address);
}
else if (is_stl_map_or_multimap_from_name(type_name, type_name_len))
{
size = get_stl_map_or_multimap_size(type_name, ext_fcts.get_current_block(), address);
}
else if (is_stl_set_or_multiset_from_name(type_name, type_name_len))
{
size = get_stl_set_or_multiset_size(type_name, ext_fcts.get_current_block(), address);
}
else if (is_stl_deque_from_name(type_name, type_name_len))
{
size = get_stl_deque_size(type_name, ext_fcts.get_current_block(), address);
}
if (stlsizeof == 0 && op == UNOP_SIZEOF)
{
char * inner_type = (char *)malloc(type_name_len + 1);
get_stl_inner_type(type_name, inner_type);
size *= ext_fcts.get_type_length(ext_fcts.get_type(inner_type, ext_fcts.get_current_block()));
free(inner_type);
}
return ext_fcts.value_from_longest(ext_fcts.get_type("int", ext_fcts.get_current_block()), size);
default:
break;
}
return NULL;
}
struct value * binary_operation(const char * type_name, int type_name_len, CORE_ADDR address, struct value * other, enum exp_opcode op)
{
switch(op)
{
case BINOP_SUBSCRIPT:
if (is_stl_vector_from_name(type_name, type_name_len))
{
return get_stl_vector_item_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
}
else if (is_stl_list_from_name(type_name, type_name_len))
{
return get_stl_list_item_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
}
else if (is_stl_map_or_multimap_from_name(type_name, type_name_len))
{
return get_stl_map_pair_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
}
else if (is_stl_set_or_multiset_from_name(type_name, type_name_len))
{
return get_stl_set_item_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
}
else if (is_stl_deque_from_name(type_name, type_name_len))
{
return get_stl_deque_item_at(type_name, type_name_len, address, ext_fcts.value_as_long(other));
}
break;
default:
break;
}
return NULL;
}
struct type * get_child_item_type_at(struct varobj * varobj, int index)
{
return get_stl_container_inner_type(varobj);
}
struct value * get_child_item_value_at(struct varobj * varobj, int index)
{
struct type * type = ext_fcts.get_varobj_type(varobj);
const char * type_name = ext_fcts.get_type_name(type);
CORE_ADDR address = ext_fcts.get_value_address(ext_fcts.get_varobj_value(varobj));
int type_name_len = strlen(type_name);
if (is_stl_vector_from_name(type_name, type_name_len))
{
return get_stl_vector_item_at(type_name, type_name_len, address, index);
}
else if (is_stl_list_from_name(type_name, type_name_len))
{
return get_stl_list_item_at(type_name, type_name_len, address, index);
}
else if (is_stl_map_or_multimap_from_name(type_name, type_name_len))
{
return get_stl_map_pair_at(type_name, type_name_len, address, index);
}
else if (is_stl_set_or_multiset_from_name(type_name, type_name_len))
{
return get_stl_set_item_at(type_name, type_name_len, address, index);
}
else if (is_stl_deque_from_name(type_name, type_name_len))
{
return get_stl_deque_item_at(type_name, type_name_len, address, index);
}
return NULL;
}
[-- Attachment #4: Makefile --]
[-- Type: text/x-makefile, Size: 209 bytes --]
GDB_SOURCES=../gdb-6.8-patched
CC=gcc
CFLAGS=-I$(GDB_SOURCES)/gdb -I$(GDB_SOURCES)/include -I$(GDB_SOURCES)/gdb/config
all: stl.so
stl.so: main.c
$(CC) $(CFLAGS) -o $@ -shared -O3 $<
clean:
rm -f stl.so
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: GDB C plugin system, and STL container viewer as an example
2008-05-23 18:34 GDB C plugin system, and STL container viewer as an example Vincent Benony
@ 2008-05-23 19:30 ` Vladimir Prus
2008-05-23 19:53 ` Daniel Jacobowitz
2008-05-23 19:59 ` Vincent Benony
0 siblings, 2 replies; 9+ messages in thread
From: Vladimir Prus @ 2008-05-23 19:30 UTC (permalink / raw)
To: gdb-patches
Vincent Benony wrote:
> Hello,
>
> some days ago, I send here a (crap and buggy) patch that allows GDB to
> display STL containers. I know that this patch was too intrusive and
> dependent of the STL version.
>
> Today, I wrote another patch that allows me to load plugin into GDB
> that are called in particular situations, like displaying the content of
> a variable of a particular type, or creating varobjects in MI
> interpreter. It is used to format any kind of datas as I want it to be
> displayed.
>
> I submit a new version of my STL container viewer, but this time as a
> plugin. It handles STL container access as it was a classic C array, and
> answers queries like 'sizeof'... It also support MI interpreter, so that
> GDB could be used with frontend, still displaying data correctly. I
> tried it with Eclipse/CDT, KDevelop, KDBG, Nemiver and Insight/GDB. All
> works well !
I don't see how you report that fact that the number of children of a
varobj has changed. Without that, I'm not sure how useful MI display
of vectors is. Am I missing something?
- Volodya
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GDB C plugin system, and STL container viewer as an example
2008-05-23 19:30 ` Vladimir Prus
@ 2008-05-23 19:53 ` Daniel Jacobowitz
2008-05-27 18:17 ` Vincent Bénony
2008-05-23 19:59 ` Vincent Benony
1 sibling, 1 reply; 9+ messages in thread
From: Daniel Jacobowitz @ 2008-05-23 19:53 UTC (permalink / raw)
To: gdb-patches
On Fri, May 23, 2008 at 06:20:36PM +0400, Vladimir Prus wrote:
> I don't see how you report that fact that the number of children of a
> varobj has changed. Without that, I'm not sure how useful MI display
> of vectors is. Am I missing something?
Just my two cents but... rather than encourage further work on the C
mechanism, is there anyone besides me who could start reviewing the
Python patches, so that we can converge on a single mechanism and get
it into the tree? If everyone waits for me to get around to it, it's
going to be a while.
Vincent, are you at all interested in taking the code you've written
and integrating it with the gdb+python repository? (If so, you'll
need a copyright assignment, if you haven't got one already.)
FYI, I am unlikely to be reviewing patches for the next week or two
unless my plans turn out to be much more boring than I expect :-)
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GDB C plugin system, and STL container viewer as an example
2008-05-23 19:53 ` Daniel Jacobowitz
@ 2008-05-27 18:17 ` Vincent Bénony
2008-05-27 18:21 ` Thiago Jung Bauermann
0 siblings, 1 reply; 9+ messages in thread
From: Vincent Bénony @ 2008-05-27 18:17 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
Le 23 mai 08 à 16:30, Daniel Jacobowitz <drow@false.org> a écrit :
> On Fri, May 23, 2008 at 06:20:36PM +0400, Vladimir Prus wrote:
>> I don't see how you report that fact that the number of children of a
>> varobj has changed. Without that, I'm not sure how useful MI display
>> of vectors is. Am I missing something?
>
> Just my two cents but... rather than encourage further work on the C
> mechanism, is there anyone besides me who could start reviewing the
> Python patches, so that we can converge on a single mechanism and get
> it into the tree? If everyone waits for me to get around to it, it's
> going to be a while.
>
You're right, please don't consider my "work" as a real solution. It's
just a quick and dirty way to have a solution to inspect STL
containers today. I try at work to encourage the use of free software,
and I succeed to push the developpment of our software under Linux.
But, as we heavily use STL, I had to find something to deal with it
now, and by publishing the patch here, and just want to share it with
people like me that need something today, although it's far from
perfect. I'm pretty sure that your solution is the one that should be
considered.
> Vincent, are you at all interested in taking the code you've written
> and integrating it with the gdb+python repository? (If so, you'll
> need a copyright assignment, if you haven't got one already.)
>
Sure, I'll have a look at your API as soon as possible, and try to
write a cleaner version of my.... euh... stuff ;-) do you have some
kind of doc ? (sorry if you've already answered to this)
> FYI, I am unlikely to be reviewing patches for the next week or two
> unless my plans turn out to be much more boring than I expect :-)
>
> --
> Daniel Jacobowitz
> CodeSourcery
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GDB C plugin system, and STL container viewer as an example
2008-05-27 18:17 ` Vincent Bénony
@ 2008-05-27 18:21 ` Thiago Jung Bauermann
0 siblings, 0 replies; 9+ messages in thread
From: Thiago Jung Bauermann @ 2008-05-27 18:21 UTC (permalink / raw)
To: Vincent Bénony; +Cc: Daniel Jacobowitz, gdb-patches
On Sun, 2008-05-25 at 14:36 +0200, Vincent Bénony wrote:
> Sure, I'll have a look at your API as soon as possible, and try to
> write a cleaner version of my.... euh... stuff ;-)
That would be awesome.
> do you have some
> kind of doc ? (sorry if you've already answered to this)
Not yet, sorry. Python support is in the early days yet. I think this
patch from Vladimir is a bit in the direction of your work, so maybe it
will help you to have a look at it:
http://sourceware.org/ml/gdb-patches/2008-05/msg00106.html
Also, the "Python support in GDB" patch series is all we currently have
in terms of Python support. That code was taken from the git repo. You
can find information about how to access it here:
http://sourceware.org/gdb/wiki/OngoingWork
Feel free to ask about Python integration stuff on the GDB mailing list,
or on the #gdb channel at freenode.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: GDB C plugin system, and STL container viewer as an example
2008-05-23 19:30 ` Vladimir Prus
2008-05-23 19:53 ` Daniel Jacobowitz
@ 2008-05-23 19:59 ` Vincent Benony
2008-05-23 20:31 ` Vladimir Prus
1 sibling, 1 reply; 9+ messages in thread
From: Vincent Benony @ 2008-05-23 19:59 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
> I don't see how you report that fact that the number of children of a
> varobj has changed. Without that, I'm not sure how useful MI display
> of vectors is. Am I missing something?
>
> - Volodya
this is done by lines 1157 to 1166 of varobj.c
if (plugins_type_handled(varobj_get_gdb_type(*varp)))
{
int new_childs = plugins_get_num_children(*varp);
if (new_childs != (*varp)->num_children)
{
(*varp)->num_children = new_childs;
(*varp)->children = varobj_list_children (*varp);
VEC_safe_push (varobj_p, result, *varp);
}
}
I evaluate the number of children at each update, and I compare with the
current number of childs stored in the varobj structure, if different,
object is added to update list.
It seems to work well into KDevelop and Insight/GDB, ie if I step in my
source code, I can see children items beeing added at each push_back.
Only Eclipse/CDT has a problem handling a vector going from 0 to 1
child (child is not displayed, but Eclipse say that number of children
has changed, displaying the correct number ; seems like an Eclipse bug),
but it works when going from 1 to 2 children, or more...
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: GDB C plugin system, and STL container viewer as an example
2008-05-23 19:59 ` Vincent Benony
@ 2008-05-23 20:31 ` Vladimir Prus
2008-05-23 20:39 ` Vincent Benony
0 siblings, 1 reply; 9+ messages in thread
From: Vladimir Prus @ 2008-05-23 20:31 UTC (permalink / raw)
To: gdb-patches
Vincent Benony wrote:
>> I don't see how you report that fact that the number of children of a
>> varobj has changed. Without that, I'm not sure how useful MI display
>> of vectors is. Am I missing something?
>>
>> - Volodya
>
> this is done by lines 1157 to 1166 of varobj.c
>
>
> if (plugins_type_handled(varobj_get_gdb_type(*varp)))
> {
> int new_childs = plugins_get_num_children(*varp);
> if (new_childs != (*varp)->num_children)
> {
> (*varp)->num_children = new_childs;
> (*varp)->children = varobj_list_children (*varp);
> VEC_safe_push (varobj_p, result, *varp);
> }
> }
>
>
> I evaluate the number of children at each update, and I compare with the
> current number of childs stored in the varobj structure, if different,
> object is added to update list.
What happens for vector< vector<int> >? It does not seem like you handle the
inner items.
>
> It seems to work well into KDevelop
Strange, I don't know any codepath in KDevelop 3.5 that could possible handle this.
Which version did you try with?
- Volodya
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: GDB C plugin system, and STL container viewer as an example
2008-05-23 20:31 ` Vladimir Prus
@ 2008-05-23 20:39 ` Vincent Benony
2008-05-23 20:46 ` Vladimir Prus
0 siblings, 1 reply; 9+ messages in thread
From: Vincent Benony @ 2008-05-23 20:39 UTC (permalink / raw)
To: Vladimir Prus; +Cc: gdb-patches
Le vendredi 23 mai 2008 à 18:43 +0400, Vladimir Prus a écrit :
>
> What happens for vector< vector<int> >? It does not seem like you handle the
> inner items.
>
I do, my plugin can handle this kind of STL type imbrication.
> >
> > It seems to work well into KDevelop
>
> Strange, I don't know any codepath in KDevelop 3.5 that could possible handle this.
> Which version did you try with?
>
3.5.1
indeed, it seems there is a problem with KDevelop
If you try a very simple project like that :
#include <vector>
int main(int, char **)
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v[2]=5;
*(v.begin()) = 6;
return 0;
}
in KDevelop, place a breakpoint on the "v.push_back(2);" line, add a
watch expression to 'v'.
Expand local and watch views of 'v' variable. Then step line by line,
and you'll see that 'watch' part is correctly updated, whereas 'local'
part is not.
Could it be fixed by something in my GDB patch, or is it a KDevelop
problem, ie does KDevelop assumes that an array never changes its size ?
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: GDB C plugin system, and STL container viewer as an example
2008-05-23 20:39 ` Vincent Benony
@ 2008-05-23 20:46 ` Vladimir Prus
0 siblings, 0 replies; 9+ messages in thread
From: Vladimir Prus @ 2008-05-23 20:46 UTC (permalink / raw)
To: Vincent Benony; +Cc: gdb-patches
On Friday 23 May 2008 20:31:47 Vincent Benony wrote:
> Le vendredi 23 mai 2008 à 18:43 +0400, Vladimir Prus a écrit :
>
> >
> > What happens for vector< vector<int> >? It does not seem like you handle the
> > inner items.
> >
>
> I do, my plugin can handle this kind of STL type imbrication.
Can you clarify how? Suppose I have varobj V, of vector <vector<int> > type.
V has two children, V.0 and V.1, which are both empty. The first child is
resized and -var-update V is send to GDB.
If I read your patch correctly, then you'll only check V itself -- I don't
see where the V's children will be updated. Can you point me at the code.
> > >
> > > It seems to work well into KDevelop
> >
> > Strange, I don't know any codepath in KDevelop 3.5 that could possible handle this.
> > Which version did you try with?
> >
>
> 3.5.1
>
> indeed, it seems there is a problem with KDevelop
>
> If you try a very simple project like that :
>
> #include <vector>
>
> int main(int, char **)
> {
> std::vector<int> v;
> v.push_back(1);
> v.push_back(2);
> v.push_back(3);
> v.push_back(4);
> v[2]=5;
> *(v.begin()) = 6;
> return 0;
> }
>
> in KDevelop, place a breakpoint on the "v.push_back(2);" line, add a
> watch expression to 'v'.
>
> Expand local and watch views of 'v' variable. Then step line by line,
> and you'll see that 'watch' part is correctly updated,
This is because all versions of GDB except for CVS HEAD is uncapable of properly
supporting watches via MI interface. As result, KDevelop has to reevaluate watches
at each step, which probably leads to this "workiness"
> whereas 'local'
> part is not.
>
> Could it be fixed by something in my GDB patch, or is it a KDevelop
> problem, ie does KDevelop assumes that an array never changes its size ?
Current version of MI assumes so -- there's no way to say that the number of
children has changed, and nothing says that if a variable object is reported
as changed, the frontend is required to re-get the list of children.
- Volodya
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2008-05-25 18:03 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-05-23 18:34 GDB C plugin system, and STL container viewer as an example Vincent Benony
2008-05-23 19:30 ` Vladimir Prus
2008-05-23 19:53 ` Daniel Jacobowitz
2008-05-27 18:17 ` Vincent Bénony
2008-05-27 18:21 ` Thiago Jung Bauermann
2008-05-23 19:59 ` Vincent Benony
2008-05-23 20:31 ` Vladimir Prus
2008-05-23 20:39 ` Vincent Benony
2008-05-23 20:46 ` Vladimir Prus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox