This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
GDB C plugin system, and STL container viewer as an example
- From: Vincent Benony <vbenony at nordnet dot fr>
- To: gdb-patches at sourceware dot org
- Date: Fri, 23 May 2008 11:45:09 +0200
- Subject: GDB C plugin system, and STL container viewer as an example
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 !
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."));
+ }
+}
+
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));
#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;
}
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