From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25312 invoked by alias); 23 May 2008 09:45:48 -0000 Received: (qmail 25288 invoked by uid 22791); 23 May 2008 09:45:41 -0000 X-Spam-Check-By: sourceware.org Received: from mailman.allo-creation.fr (HELO ns39154.ovh.net) (91.121.20.133) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 23 May 2008 09:45:14 +0000 Received: (qmail 29954 invoked by uid 508); 23 May 2008 10:05:58 -0000 Received: from unknown (HELO ?192.168.1.4?) (82.226.112.216) by 87-98-251-24.ovh.net with SMTP; 23 May 2008 10:05:58 -0000 Subject: GDB C plugin system, and STL container viewer as an example From: Vincent Benony To: gdb-patches@sourceware.org Content-Type: multipart/mixed; boundary="=-LX5Fugo9H+HbNvpRRuNr" Date: Fri, 23 May 2008 18:34:00 -0000 Message-Id: <1211535909.8253.16.camel@bsr-desktop> Mime-Version: 1.0 X-Mailer: Evolution 2.22.1 X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-05/txt/msg00680.txt.bz2 --=-LX5Fugo9H+HbNvpRRuNr Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-length: 2010 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,std::allocator > > (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 ! --=-LX5Fugo9H+HbNvpRRuNr Content-Disposition: attachment; filename=gdb-6.8-plugin.patch Content-Type: text/x-patch; name=gdb-6.8-plugin.patch; charset=UTF-8 Content-Transfer-Encoding: 7bit Content-length: 27559 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 +#include + +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 #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)); --=-LX5Fugo9H+HbNvpRRuNr Content-Disposition: attachment; filename=main.c Content-Type: text/x-csrc; name=main.c; charset=UTF-8 Content-Transfer-Encoding: 7bit Content-length: 49323 #include "stdio.h" #include "plugin.h" #include 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')) { 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= 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= 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= count) { free (inner_key); free (inner_value); free (pair_name); return NULL; } for (idx=0; idx= 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