* Using STL containers with GDB
@ 2008-04-22 12:29 Vincent Benony
2008-04-22 14:41 ` Daniel Jacobowitz
2008-04-22 22:13 ` Nick Roberts
0 siblings, 2 replies; 14+ messages in thread
From: Vincent Benony @ 2008-04-22 12:29 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1275 bytes --]
Hi,
I use gdb at work for some time now. We currently develop a
multiplatform software which heavily use STL templates. As a result,
it's always difficult to me to debug such code.
I tried to find a way to debug more efficiently by using gdb scripts
that were able to dump std::vector or std::list, but it was always
painful.
So, yesterday, I decided myself to look at the code of GDB. After a
quick look, I wrote this patch. I know that it's not very clean, and
that it makes many assumptions about STL containers, and that it cannot
be considered as a long term feature for GDB, but, believe me, it's very
very usefull !
Now, I can look at the content of list, vector, set, map, multiset,
multimap and string simply with the classic "print" command of GDB.
Two switchs and a parameter are introduced :
* set print stl on / set print stl off
default is off. Controls the type of dumping (classic or "easy")
* set print stl_array_compatible on / set print stl_array_compatible
off
default is on. Controls the kind of formating of STL container when stl
print is on.
* set print stllimit N
set the maximum number of items we could dump when printing an STL
container to N. 0 means unlimited
I hope it could be useful for someone.
Sincerely
Vincent Benony
[-- Attachment #2: gdb-6.8-stl.patch --]
[-- Type: text/x-patch, Size: 19720 bytes --]
--- gdb-6.8/gdb/cp-valprint.c 2008-01-01 23:53:09.000000000 +0100
+++ gdb-6.8-patched/gdb/cp-valprint.c 2008-04-22 11:37:25.000000000 +0200
@@ -36,6 +36,10 @@
#include "valprint.h"
#include "cp-support.h"
#include "language.h"
+#include "block.h"
+#include "gdbcore.h"
+#include "value.h"
+#include "expression.h"
/* Controls printing of vtbl's */
int vtblprint;
@@ -70,6 +74,36 @@
value);
}
+/* Controls printing of STL containers */
+int stlprint;
+static void
+show_stlprint (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("\
+Printing of STL containers is %s.\n"),
+ value);
+}
+
+int stlprintcompatible;
+static void
+show_stlprintcompatible (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("\
+Compatible printing of STL containers is %s.\n"),
+ value);
+}
+
+int stllimit;
+static void
+show_stllimit (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("\
+Maximum elements of STL containers is set to %s.\n"), (stllimit == 0 || stllimit == (unsigned int)-1) ? "unlimited" : value);
+}
+
static struct obstack dont_print_vb_obstack;
static struct obstack dont_print_statmem_obstack;
@@ -148,6 +182,494 @@
DONT_PRINT is an array of baseclass types that we
should not print, or zero if called from top level. */
+int
+get_stl_inner_type (struct type *type, char *inner_type_name)
+{
+ int level = 1;
+ char *pname = type->main_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 (struct type *type, char *inner_type_key, char *inner_type_value)
+{
+ int level = 1;
+ char *pname = type->main_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;
+ }
+
+ return 1;
+}
+
+struct type *
+cp_get_type(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;
+}
+
+void
+cp_print_stl_vector(struct type *type, CORE_ADDR address,
+ struct ui_file *stream, int format, int recurse,
+ enum val_prettyprint pretty)
+{
+ char *inner_name;
+ CORE_ADDR pc;
+ struct frame_info *current_frame;
+ struct type *void_type;
+ struct type *inner_type;
+ struct block *block;
+ int ptr_size;
+ unsigned int idx;
+ CORE_ADDR begin;
+ CORE_ADDR end;
+ gdb_byte *b;
+
+ inner_name = (char *)malloc(strlen(type->main_type->name) + 1);
+
+ if (get_stl_inner_type(type, inner_name))
+ {
+ if (!stlprintcompatible) fprintf_filtered (stream, "vector<%s>", inner_name);
+ fprintf_filtered (stream, "{");
+ if (pretty) fprintf_filtered (stream, "\n");
+ current_frame = get_current_frame ();
+ pc = get_frame_address_in_block (current_frame);
+ block = block_for_pc (pc);
+ inner_type = cp_get_type (inner_name, block);
+ void_type = cp_get_type("void *", block);
+ ptr_size = TYPE_LENGTH(void_type);
+
+ if (inner_type == NULL)
+ {
+ if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
+ fprintf_filtered (stream, " // no information for type %s\n", inner_name);
+ }
+ else
+ {
+ idx = 0;
+ begin = (CORE_ADDR)read_memory_integer (address, ptr_size);
+ end = (CORE_ADDR)read_memory_integer (address + ptr_size, ptr_size);
+ b = (gdb_byte *)malloc(TYPE_LENGTH(inner_type));
+ while (begin != end)
+ {
+ if (idx >= stllimit)
+ {
+ fprintf_filtered (stream, "...");
+ break;
+ }
+ if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
+ if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx++);
+ read_memory(begin, b, TYPE_LENGTH(inner_type));
+ c_val_print(inner_type, b, 0, begin, stream, format, 0, recurse + 1, pretty);
+ begin += TYPE_LENGTH(inner_type);
+ if (begin != end) fprintf_filtered(stream, ", ");
+ if (pretty)
+ {
+ fprintf_filtered(stream, "\n");
+ }
+ }
+ free(b);
+ }
+ if (pretty) print_spaces_filtered (2 * recurse, stream);
+ fprintf_filtered (stream, "}");
+ if (recurse == 0) fprintf_filtered (stream, "\n");
+ }
+
+ free(inner_name);
+}
+
+void
+cp_print_stl_list(struct type *type, CORE_ADDR address,
+ struct ui_file *stream, int format, int recurse,
+ enum val_prettyprint pretty)
+{
+ char *inner_name;
+ CORE_ADDR pc;
+ CORE_ADDR node;
+ CORE_ADDR data_ptr;
+ struct frame_info *current_frame;
+ struct type *inner_type;
+ struct type *void_type;
+ struct block *block;
+ int ptr_size;
+ unsigned int idx;
+ gdb_byte *b;
+
+ inner_name = (char *)malloc(strlen(type->main_type->name) + 1);
+
+ if (get_stl_inner_type(type, inner_name))
+ {
+ if (!stlprintcompatible) fprintf_filtered (stream, "list<%s>", inner_name);
+ fprintf_filtered (stream, "{");
+ if (pretty) fprintf_filtered (stream, "\n");
+ current_frame = get_current_frame ();
+ pc = get_frame_address_in_block (current_frame);
+ block = block_for_pc (pc);
+ inner_type = cp_get_type (inner_name, block);
+ void_type = cp_get_type("void *", block);
+ ptr_size = TYPE_LENGTH(void_type);
+
+ if (inner_type == NULL)
+ {
+ if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
+ fprintf_filtered (stream, " // no information for type %s\n", inner_name);
+ }
+ else
+ {
+ idx = 0;
+ node = (CORE_ADDR)read_memory_integer (address, ptr_size);
+ b = (gdb_byte *)malloc(TYPE_LENGTH(inner_type));
+ do
+ {
+ if (idx >= stllimit)
+ {
+ fprintf_filtered (stream, "...");
+ break;
+ }
+ data_ptr = (CORE_ADDR)(node + ptr_size * 2);
+ if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
+ if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx++);
+ read_memory(data_ptr, b, TYPE_LENGTH(inner_type));
+ c_val_print(inner_type, b, 0, data_ptr, stream, format, 0, recurse + 1, pretty);
+ node = (CORE_ADDR)read_memory_integer (node, ptr_size);
+ if (node != address) fprintf_filtered(stream, ", ");
+ if (pretty)
+ {
+ fprintf_filtered(stream, "\n");
+ }
+ } while (node != address);
+ free(b);
+ }
+ if (pretty) print_spaces_filtered (2 * recurse, stream);
+ fprintf_filtered (stream, "}");
+ if (recurse == 0) fprintf_filtered (stream, "\n");
+ }
+
+ free(inner_name);
+}
+
+#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))
+
+void
+cp_print_stl_set(struct type *type, CORE_ADDR address,
+ struct ui_file *stream, int format, int recurse,
+ enum val_prettyprint pretty)
+{
+ char *inner_name;
+ CORE_ADDR pc;
+ CORE_ADDR node;
+ CORE_ADDR left;
+ CORE_ADDR tmp_node;
+ CORE_ADDR data_ptr;
+ struct frame_info *current_frame;
+ struct type *inner_type;
+ struct type *void_type;
+ struct block *block;
+ int ptr_size;
+ unsigned int idx;
+ int count;
+ gdb_byte *b;
+
+ inner_name = (char *)malloc(strlen(type->main_type->name) + 1);
+
+ if (get_stl_inner_type(type, inner_name))
+ {
+ if (!stlprintcompatible) fprintf_filtered (stream, "set<%s>", inner_name);
+ fprintf_filtered (stream, "{");
+ if (pretty) fprintf_filtered (stream, "\n");
+ current_frame = get_current_frame ();
+ pc = get_frame_address_in_block (current_frame);
+ block = block_for_pc (pc);
+ inner_type = cp_get_type (inner_name, block);
+ void_type = cp_get_type("void *", block);
+ ptr_size = TYPE_LENGTH(void_type);
+
+ if (inner_type == NULL)
+ {
+ if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
+ fprintf_filtered (stream, " // no information for type %s\n", inner_name);
+ }
+ else
+ {
+ b = (gdb_byte *)malloc(TYPE_LENGTH(inner_type));
+ 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 (idx >= stllimit)
+ {
+ fprintf_filtered (stream, "...");
+ break;
+ }
+ data_ptr = (CORE_ADDR)(node + ptr_size * 4);
+ if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
+ if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx);
+ read_memory(data_ptr, b, TYPE_LENGTH(inner_type));
+ c_val_print(inner_type, b, 0, data_ptr, stream, format, 0, 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) fprintf_filtered(stream, ", ");
+ if (pretty)
+ {
+ fprintf_filtered(stream, "\n");
+ }
+ }
+ free(b);
+ }
+ if (pretty) print_spaces_filtered (2 * recurse, stream);
+ fprintf_filtered (stream, "}");
+ if (recurse == 0) fprintf_filtered (stream, "\n");
+ }
+
+ free(inner_name);
+}
+
+void
+cp_print_stl_map(struct type *type, CORE_ADDR address,
+ struct ui_file *stream, int format, int recurse,
+ enum val_prettyprint pretty)
+{
+ char *inner_key;
+ char *inner_value;
+ CORE_ADDR pc;
+ CORE_ADDR node;
+ CORE_ADDR left;
+ CORE_ADDR tmp_node;
+ CORE_ADDR data_ptr;
+ struct frame_info *current_frame;
+ 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;
+ gdb_byte *b_key;
+ gdb_byte *b_value;
+
+ inner_key = (char *)malloc(strlen(type->main_type->name) + 1);
+ inner_value = (char *)malloc(strlen(type->main_type->name) + 1);
+
+ if (get_stl_inner_type_pair(type, inner_key, inner_value))
+ {
+ if (!stlprintcompatible) fprintf_filtered (stream, "map<%s, %s>", inner_key, inner_value);
+ fprintf_filtered (stream, "{");
+ if (pretty) fprintf_filtered (stream, "\n");
+ current_frame = get_current_frame ();
+ pc = get_frame_address_in_block (current_frame);
+ block = block_for_pc (pc);
+ inner_type_key = cp_get_type (inner_key, block);
+ inner_type_value = cp_get_type (inner_value, block);
+ void_type = cp_get_type("void *", block);
+ ptr_size = TYPE_LENGTH(void_type);
+
+ if (inner_type_key == NULL || inner_type_value == NULL)
+ {
+ if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
+ fprintf_filtered (stream, " // no information for type std::pair<%s, %s>\n", inner_key, inner_value);
+ }
+ else
+ {
+ b_key = (gdb_byte *)malloc(TYPE_LENGTH(inner_type_key));
+ b_value = (gdb_byte *)malloc(TYPE_LENGTH(inner_type_value));
+ 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 (idx >= stllimit)
+ {
+ fprintf_filtered (stream, "...");
+ break;
+ }
+ data_ptr = (CORE_ADDR)(node + ptr_size * 4);
+ read_memory(data_ptr, b_key, TYPE_LENGTH(inner_type_key));
+ read_memory(data_ptr + ptr_size, b_value, TYPE_LENGTH(inner_type_value));
+
+ if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
+ if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx);
+ fprintf_filtered (stream, "{");
+ if (pretty) fprintf_filtered(stream, "\n");
+
+ if (pretty) print_spaces_filtered (4 + 2 * recurse, stream);
+ if (!stlprintcompatible)
+ {
+ fprintf_filtered(stream, "key ");
+ if (pretty) fprintf_filtered(stream, " ");
+ fprintf_filtered(stream, "= ");
+ }
+ c_val_print(inner_type_key, b_key, 0, data_ptr, stream, format, 0, recurse + 3, pretty);
+ if (pretty) fprintf_filtered(stream, ",\n"); else fprintf_filtered(stream, ", ");
+ if (pretty) print_spaces_filtered (4 + 2 * recurse, stream);
+ if (!stlprintcompatible)
+ {
+ fprintf_filtered(stream, "value = ");
+ }
+ c_val_print(inner_type_value, b_value, 0, data_ptr, stream, format, 0, recurse + 3, pretty);
+ if (pretty) fprintf_filtered(stream, "\n");
+
+ if (pretty) print_spaces_filtered (4 + 2 * recurse, stream);
+ 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) fprintf_filtered(stream, ", ");
+ if (pretty)
+ {
+ fprintf_filtered(stream, "\n");
+ }
+ }
+ free(b_key);
+ free(b_value);
+ }
+ if (pretty) print_spaces_filtered (2 * recurse, stream);
+ fprintf_filtered (stream, "}");
+ if (recurse == 0) fprintf_filtered (stream, "\n");
+ }
+
+ free(inner_key);
+ free(inner_value);
+}
+
+void
+cp_print_stl_string(struct type *type, CORE_ADDR address,
+ struct ui_file *stream, int format, int recurse,
+ enum val_prettyprint pretty)
+{
+ struct type *char_type;
+ struct frame_info *current_frame;
+ struct block *block;
+ int ptr_size;
+ int pc;
+ CORE_ADDR string_ptr;
+
+ current_frame = get_current_frame ();
+ pc = get_frame_address_in_block (current_frame);
+ block = block_for_pc (pc);
+ char_type = cp_get_type("char *", block);
+ ptr_size = TYPE_LENGTH(char_type);
+
+ string_ptr = read_memory_integer (address, ptr_size);
+ val_print_string (string_ptr, -1, 1, stream);
+}
+
void
cp_print_value_fields (struct type *type, struct type *real_type,
const gdb_byte *valaddr, int offset, CORE_ADDR address,
@@ -161,6 +683,35 @@
CHECK_TYPEDEF (type);
+ if (stlprint)
+ {
+ if (!strncmp(type->main_type->name, "std::vector<", 12))
+ {
+ cp_print_stl_vector(type, address, stream, format, recurse, pretty);
+ return;
+ }
+ if (!strncmp(type->main_type->name, "std::list<", 10))
+ {
+ cp_print_stl_list(type, address, stream, format, recurse, pretty);
+ return;
+ }
+ if (!strncmp(type->main_type->name, "std::set<", 9) || !strncmp(type->main_type->name, "std::multiset<", 14))
+ {
+ cp_print_stl_set(type, address, stream, format, recurse, pretty);
+ return;
+ }
+ if (!strncmp(type->main_type->name, "std::map<", 9) || !strncmp(type->main_type->name, "std::multimap<", 14))
+ {
+ cp_print_stl_map(type, address, stream, format, recurse, pretty);
+ return;
+ }
+ if (!strncmp(type->main_type->name, "std::basic_string<char,", 23))
+ {
+ cp_print_stl_string(type, address, stream, format, recurse, pretty);
+ return;
+ }
+ }
+
fprintf_filtered (stream, "{");
len = TYPE_NFIELDS (type);
n_baseclasses = TYPE_N_BASECLASSES (type);
@@ -608,6 +1159,32 @@
show_objectprint,
&setprintlist, &showprintlist);
+ add_setshow_boolean_cmd ("stl", class_support, &stlprint, _("\
+Set printing of STL containers."), _("\
+Show printing of STL containers."), NULL,
+ NULL,
+ show_stlprint,
+ &setprintlist, &showprintlist);
+ stlprint = 0;
+
+ add_setshow_boolean_cmd ("stl_array_compatible", class_support, &stlprintcompatible, _("\
+Set compatibility with classic arrays while printing STL containers."), _("\
+Show compatibility of STL containers printing."), NULL,
+ NULL,
+ show_stlprintcompatible,
+ &setprintlist, &showprintlist);
+ stlprintcompatible = 1;
+
+ add_setshow_uinteger_cmd ("stllimit", class_support,
+ &stllimit,
+ _("Set the maximum number of elements to display in STL containers."),
+ _("Show the maximum number of elements to display in STL containers."),
+ _("Show the maximum number of elements to display in STL containers. Zero is unlimited."),
+ NULL,
+ show_stllimit,
+ &setprintlist, &showprintlist);
+ stllimit = 50;
+
/* Give people the defaults which they are used to. */
objectprint = 0;
vtblprint = 0;
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: Using STL containers with GDB
2008-04-22 12:29 Using STL containers with GDB Vincent Benony
@ 2008-04-22 14:41 ` Daniel Jacobowitz
2008-04-22 14:49 ` Vincent Benony
2008-04-22 22:13 ` Nick Roberts
1 sibling, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2008-04-22 14:41 UTC (permalink / raw)
To: Vincent Benony; +Cc: gdb-patches
On Tue, Apr 22, 2008 at 11:39:59AM +0200, Vincent Benony wrote:
> Hi,
>
> I use gdb at work for some time now. We currently develop a
> multiplatform software which heavily use STL templates. As a result,
> it's always difficult to me to debug such code.
>
> I tried to find a way to debug more efficiently by using gdb scripts
> that were able to dump std::vector or std::list, but it was always
> painful.
>
> So, yesterday, I decided myself to look at the code of GDB. After a
> quick look, I wrote this patch. I know that it's not very clean, and
> that it makes many assumptions about STL containers, and that it cannot
> be considered as a long term feature for GDB, but, believe me, it's very
> very usefull !
Thanks for doing this. As for a long term solution, please take a
look at the in-progress Python branch, in Volodya's git repository.
STL support is a big missing feature, but we'd like to add it by
external scripts so that they can be distributed along with the
library, modified without recompiling GDB, and so forth. I think
Vladimir's got it printing std::vector already.
I really hope we'll have it included in the next release!
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Using STL containers with GDB
2008-04-22 14:41 ` Daniel Jacobowitz
@ 2008-04-22 14:49 ` Vincent Benony
2008-04-22 17:51 ` Thiago Jung Bauermann
0 siblings, 1 reply; 14+ messages in thread
From: Vincent Benony @ 2008-04-22 14:49 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
> Thanks for doing this. As for a long term solution, please take a
> look at the in-progress Python branch, in Volodya's git repository.
> STL support is a big missing feature, but we'd like to add it by
> external scripts so that they can be distributed along with the
> library, modified without recompiling GDB, and so forth. I think
> Vladimir's got it printing std::vector already.
>
> I really hope we'll have it included in the next release!
>
Thank you for the information, I tought this projet was aborted, but
it's a great news that a python scripting support is planned for GDB !
This will be a cleaner solution to have those features implemented in
external libs.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Using STL containers with GDB
2008-04-22 14:49 ` Vincent Benony
@ 2008-04-22 17:51 ` Thiago Jung Bauermann
2008-04-22 18:37 ` Vladimir Prus
0 siblings, 1 reply; 14+ messages in thread
From: Thiago Jung Bauermann @ 2008-04-22 17:51 UTC (permalink / raw)
To: Vincent Benony; +Cc: Daniel Jacobowitz, gdb-patches
On Tue, 2008-04-22 at 14:28 +0200, Vincent Benony wrote:
> > Thanks for doing this. As for a long term solution, please take a
> > look at the in-progress Python branch, in Volodya's git repository.
<snip>
> > I really hope we'll have it included in the next release!
> >
>
> Thank you for the information, I tought this projet was aborted, but
> it's a great news that a python scripting support is planned for GDB !
> This will be a cleaner solution to have those features implemented in
> external libs.
FYI, I'm thinking of preparing patches with the code from the git
repository by the weekend, or early next week (Tromey and Volodya, if
you have other plans I'm fine, just let me know, also if you want to do
the patches yourselves I'm fine too :-D ) and post them as RFC to this
list.
We'll know then if you folks think we've been taking the right direction
and if there are use cases we are not covering with the current features
(probably). All is input welcome!
Of course you are all free to peek at the git repository at any time as
well. :-)
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Using STL containers with GDB
2008-04-22 17:51 ` Thiago Jung Bauermann
@ 2008-04-22 18:37 ` Vladimir Prus
0 siblings, 0 replies; 14+ messages in thread
From: Vladimir Prus @ 2008-04-22 18:37 UTC (permalink / raw)
To: gdb-patches
Thiago Jung Bauermann wrote:
> On Tue, 2008-04-22 at 14:28 +0200, Vincent Benony wrote:
>> > Thanks for doing this. As for a long term solution, please take a
>> > look at the in-progress Python branch, in Volodya's git repository.
> <snip>
>> > I really hope we'll have it included in the next release!
>> >
>>
>> Thank you for the information, I tought this projet was aborted, but
>> it's a great news that a python scripting support is planned for GDB !
>> This will be a cleaner solution to have those features implemented in
>> external libs.
>
> FYI, I'm thinking of preparing patches with the code from the git
> repository by the weekend, or early next week (Tromey and Volodya, if
> you have other plans I'm fine, just let me know, also if you want to do
> the patches yourselves I'm fine too :-D ) and post them as RFC to this
> list.
I expect to have MI dynamic varobjs done in an hour. I mostly care about MI,
but the visualizer classes I have in mind can be easily wrapper in some
functions callable from cli.
- Volodya
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Using STL containers with GDB
2008-04-22 12:29 Using STL containers with GDB Vincent Benony
2008-04-22 14:41 ` Daniel Jacobowitz
@ 2008-04-22 22:13 ` Nick Roberts
2008-04-22 22:56 ` Daniel Jacobowitz
1 sibling, 1 reply; 14+ messages in thread
From: Nick Roberts @ 2008-04-22 22:13 UTC (permalink / raw)
To: Vincent Benony; +Cc: gdb-patches
> So, yesterday, I decided myself to look at the code of GDB. After a
> quick look, I wrote this patch. I know that it's not very clean, and
> that it makes many assumptions about STL containers, and that it cannot
> be considered as a long term feature for GDB, but, believe me, it's very
> very usefull !
>
> Now, I can look at the content of list, vector, set, map, multiset,
> multimap and string simply with the classic "print" command of GDB.
The Python branch appears to work for executables compiled with Gcc only. I'm
curious to know if this approach will work for executables built using other
compilers?
--
Nick http://www.inet.net.nz/~nickrob
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Using STL containers with GDB
2008-04-22 22:13 ` Nick Roberts
@ 2008-04-22 22:56 ` Daniel Jacobowitz
2008-04-23 6:49 ` Vincent Bénony
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2008-04-22 22:56 UTC (permalink / raw)
To: Nick Roberts; +Cc: Vincent Benony, gdb-patches
On Wed, Apr 23, 2008 at 09:35:09AM +1200, Nick Roberts wrote:
> > So, yesterday, I decided myself to look at the code of GDB. After a
> > quick look, I wrote this patch. I know that it's not very clean, and
> > that it makes many assumptions about STL containers, and that it cannot
> > be considered as a long term feature for GDB, but, believe me, it's very
> > very usefull !
> >
> > Now, I can look at the content of list, vector, set, map, multiset,
> > multimap and string simply with the classic "print" command of GDB.
>
> The Python branch appears to work for executables compiled with Gcc only. I'm
> curious to know if this approach will work for executables built using other
> compilers?
Vincent's implementation has the layout of the GNU STL implementation
hardcoded into it - so even less portable than the Python
implementation, which uses the field names.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Using STL containers with GDB
2008-04-22 22:56 ` Daniel Jacobowitz
@ 2008-04-23 6:49 ` Vincent Bénony
2008-04-23 8:53 ` Eli Zaretskii
2008-04-23 10:12 ` Nick Roberts
0 siblings, 2 replies; 14+ messages in thread
From: Vincent Bénony @ 2008-04-23 6:49 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Nick Roberts, gdb-patches
Le 22 avr. 08 à 23:51, Daniel Jacobowitz a écrit :
>>
>> The Python branch appears to work for executables compiled with Gcc
>> only. I'm
>> curious to know if this approach will work for executables built
>> using other
>> compilers?
>
> Vincent's implementation has the layout of the GNU STL implementation
> hardcoded into it - so even less portable than the Python
> implementation, which uses the field names.
You are right, this patch is very hardcoded. I assume that fields of
STL containers are always in the same order. I ask GDB the size of
"void *", and I compute fields offsets using this information to read
things I need. If you use another compiler, but with GNU STL headers,
this patch *should* continue to work...
The reason why I do not use fields name is that I had some problems
with GDB parser: my first approach was to use GDB scripts, but there
were many problems, like no recursive dump (an std::list into an
std::vector for example), and I was unable to cast a pointer into a
type that was a template, I mean GDB parser was able to parse a
expression like
(gdb) p (struct Something*) pointer
but not something like
(gdb) p (std::list<int> *) pointer
So, you should see my patch as a quick an ugly way of using GDB to
debug program that use STL container today, but not a patch to be
included into GDB for future releases.
My idea was first to consider having GDB call some kind of external
script in particular situation, and this seems to be the goal of
Python scripting system, and that's why I feel very enthusiast about
this project.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Using STL containers with GDB
2008-04-23 6:49 ` Vincent Bénony
@ 2008-04-23 8:53 ` Eli Zaretskii
2008-04-23 9:29 ` BENONY Vincent
2008-04-23 10:12 ` Nick Roberts
1 sibling, 1 reply; 14+ messages in thread
From: Eli Zaretskii @ 2008-04-23 8:53 UTC (permalink / raw)
To: Vincent Bénony; +Cc: drow, nickrob, gdb-patches
> Cc: Nick Roberts <nickrob@snap.net.nz>, gdb-patches@sourceware.org
> From: =?ISO-8859-1?Q?Vincent_B=E9nony?= <vbenony@nordnet.fr>
> Date: Wed, 23 Apr 2008 07:48:22 +0200
>
> I mean GDB parser was able to parse a expression like
>
> (gdb) p (struct Something*) pointer
>
> but not something like
>
> (gdb) p (std::list<int> *) pointer
Does it work if you quote the problematic parts, like this:
(gdb) p ('std::list<int>' *) pointer
?
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: Using STL containers with GDB
2008-04-23 8:53 ` Eli Zaretskii
@ 2008-04-23 9:29 ` BENONY Vincent
0 siblings, 0 replies; 14+ messages in thread
From: BENONY Vincent @ 2008-04-23 9:29 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: drow, nickrob, gdb-patches
Eli Zaretskii a écrit :
>> Cc: Nick Roberts <nickrob@snap.net.nz>, gdb-patches@sourceware.org
>> From: =?ISO-8859-1?Q?Vincent_B=E9nony?= <vbenony@nordnet.fr>
>> Date: Wed, 23 Apr 2008 07:48:22 +0200
>>
>> I mean GDB parser was able to parse a expression like
>>
>> (gdb) p (struct Something*) pointer
>>
>> but not something like
>>
>> (gdb) p (std::list<int> *) pointer
>
> Does it work if you quote the problematic parts, like this:
>
> (gdb) p ('std::list<int>' *) pointer
>
> ?
>
I saw a trick like this somewhere, but sadly it doesn't work for me.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Using STL containers with GDB
2008-04-23 6:49 ` Vincent Bénony
2008-04-23 8:53 ` Eli Zaretskii
@ 2008-04-23 10:12 ` Nick Roberts
2008-04-23 12:22 ` Daniel Jacobowitz
1 sibling, 1 reply; 14+ messages in thread
From: Nick Roberts @ 2008-04-23 10:12 UTC (permalink / raw)
To: Vincent Bénony; +Cc: Daniel Jacobowitz, gdb-patches
> >> The Python branch appears to work for executables compiled with Gcc
> >> only. I'm
> >> curious to know if this approach will work for executables built
> >> using other
> >> compilers?
> >
> > Vincent's implementation has the layout of the GNU STL implementation
> > hardcoded into it - so even less portable than the Python
> > implementation, which uses the field names.
>
> You are right, this patch is very hardcoded. I assume that fields of
> STL containers are always in the same order. I ask GDB the size of
> "void *", and I compute fields offsets using this information to read
> things I need. If you use another compiler, but with GNU STL headers,
> this patch *should* continue to work...
Thar's what I wonder: would your approach, implemented as a Python script,
give the best of both worlds?
--
Nick http://www.inet.net.nz/~nickrob
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: Using STL containers with GDB
2008-04-23 10:12 ` Nick Roberts
@ 2008-04-23 12:22 ` Daniel Jacobowitz
0 siblings, 0 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2008-04-23 12:22 UTC (permalink / raw)
To: Nick Roberts; +Cc: Vincent Bénony, gdb-patches
On Wed, Apr 23, 2008 at 08:54:58PM +1200, Nick Roberts wrote:
> > You are right, this patch is very hardcoded. I assume that fields of
> > STL containers are always in the same order. I ask GDB the size of
> > "void *", and I compute fields offsets using this information to read
> > things I need. If you use another compiler, but with GNU STL headers,
> > this patch *should* continue to work...
>
> Thar's what I wonder: would your approach, implemented as a Python script,
> give the best of both worlds?
If you're talking about another compiler, in what way is this better
than doing it by field name?
If you're using the GNU STL, you'll get the same field names and class
layout regardless of the compiler. If you're not, then both the field
names and class layout will be different.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 14+ messages in thread
* Using STL Containers With GDB
@ 2009-05-27 20:27 Ken Lauterbach
2009-05-27 21:24 ` Paul Pluzhnikov
0 siblings, 1 reply; 14+ messages in thread
From: Ken Lauterbach @ 2009-05-27 20:27 UTC (permalink / raw)
To: gdb-patches; +Cc: Ken Lauterbach
Hi,
Recently I took the changes that Vincent Benony submitted last year and
then modified them to get them to work with RH 3.2.3 GCC. I am aware of
all the issues that were raised by Vincent and others in the original
posts, I am just submitting this in case someone else finds it useful.
Below is the new/modified code, including Vincent's changes as well.
Regards,
Ken Lauterbach
#include "block.h"
#include "gdbcore.h"
#include "value.h"
#include "expression.h"
#include "ctype.h" //isdigit()
/* Controls printing of STL containers */
int stlprint;
static void
show_stlprint (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Printing of STL containers is %s.\n"), value);
}
int stlprintcompatible;
static void
show_stlprintcompatible (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Compatible printing of STL containers is %s.\n"),value);
}
int stllimit;
static void
show_stllimit (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Maximum elements of STL containers is set to %s.\n"),
(stllimit == 0 || stllimit == (unsigned int)-1) ? "unlimited" : value);
}
int
get_stl_inner_type (struct type *type, char *inner_type_name)
{
int level = 1;
char *pname = type->main_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 (struct type *type, char *inner_type_key, char *inner_type_value)
{
// remove const from type
// causes seg fault later otherwise
int level = 1;
char *pname = type->main_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;
}
return 1;
}
struct type *
cp_get_type(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;
}
void
cp_print_stl_vector(struct type *type, CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
char *inner_name;
CORE_ADDR pc;
struct frame_info *current_frame;
struct type *void_type;
struct type *inner_type;
struct block *block;
int ptr_size;
unsigned int idx;
CORE_ADDR begin;
CORE_ADDR end;
gdb_byte *b;
inner_name = (char *)malloc(strlen(type->main_type->name) + 1);
if (get_stl_inner_type(type, inner_name))
{
if (!stlprintcompatible) fprintf_filtered (stream, "vector<%s>", inner_name);
fprintf_filtered (stream, "{");
if (pretty) fprintf_filtered (stream, "\n");
current_frame = get_current_frame ();
pc = get_frame_address_in_block (current_frame);
block = block_for_pc (pc);
inner_type = cp_get_type (inner_name, block);
void_type = cp_get_type("void *", block);
ptr_size = TYPE_LENGTH(void_type);
if (inner_type == NULL)
{
if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
fprintf_filtered (stream, " // no information for type %s\n", inner_name);
}
else
{
idx = 0;
begin = (CORE_ADDR)read_memory_integer (address, ptr_size);
end = (CORE_ADDR)read_memory_integer (address + ptr_size, ptr_size);
b = (gdb_byte *)malloc(TYPE_LENGTH(inner_type));
while (begin != end)
{
if (idx >= stllimit)
{
fprintf_filtered (stream, "...");
break;
}
if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx++);
read_memory(begin, b, TYPE_LENGTH(inner_type));
c_val_print(inner_type, b, 0, begin, stream, format, 0, recurse + 1, pretty);
begin += TYPE_LENGTH(inner_type);
if (begin != end) fprintf_filtered(stream, ", ");
if (pretty)
{
fprintf_filtered(stream, "\n");
}
}
free(b);
}
if (pretty) print_spaces_filtered (2 * recurse, stream);
fprintf_filtered (stream, "}");
if (recurse == 0) fprintf_filtered (stream, "\n");
}
free(inner_name);
}
int
inner_name_is_pointer(
char *inner_name
){
int len = strlen(inner_name);
if ( len > 0 && inner_name[len-1] == '*' ){
return 1;
}
return 0;
}
#define VTABLE_PREFIX_LEN 4
struct type *
get_real_inner_type2(
char *inner_name2,
struct block *block,
CORE_ADDR addr
)
{
struct type *inner_type2 = 0;
struct type *real_inner_type2 = 0;
struct main_type *main_type = 0;
char *real_name2 = 0;
inner_type2 = cp_get_type (inner_name2, block);
main_type = inner_type2->main_type;
if ( main_type->nfields > 0 && 0 == strncmp(main_type->fields[0].name,"_vptr.",6) ){
struct minimal_symbol *msymbol;
gdb_byte *b2 = 0;
CORE_ADDR addr2 = 0;
char * fullname = 0;
char * shortname = 0;
read_memory(addr, (gdb_byte *) &addr2, sizeof addr2);
msymbol = lookup_minimal_symbol_by_pc(addr2);
if ( msymbol ){
fullname = DEPRECATED_SYMBOL_NAME(msymbol);
shortname = fullname + VTABLE_PREFIX_LEN; //this should be _ZTV
for ( ; *shortname && isdigit(*shortname) ; shortname++ ){} // get rid of digits, like 9 or 13
//fprintf(stderr,"found _vptr %s %s %s\n", main_type->fields[0].name,fullname,shortname);
inner_type2 = cp_get_type(shortname, block);
}
}
return inner_type2;
}
void
cp_print_stl_list(struct type *type, CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
char *inner_name;
char *inner_name2;
CORE_ADDR pc;
CORE_ADDR node;
CORE_ADDR next_node;
CORE_ADDR head_node;
CORE_ADDR data_ptr;
CORE_ADDR data_ptr2;
struct frame_info *current_frame;
struct type *inner_type;
struct type *inner_type2 = 0;
struct type *void_type;
struct block *block;
int ptr_size;
unsigned int idx;
gdb_byte *b;
gdb_byte *b2 = 0;
inner_name = (char *)malloc(strlen(type->main_type->name) + 1);
inner_name2 = (char *)malloc(strlen(type->main_type->name) + 1);
if (get_stl_inner_type(type, inner_name))
{
if (!stlprintcompatible) fprintf_filtered (stream, "list<%s>", inner_name);
fprintf_filtered (stream, "{");
if (pretty) fprintf_filtered (stream, "\n");
current_frame = get_current_frame ();
pc = get_frame_address_in_block (current_frame);
block = block_for_pc (pc);
inner_type = cp_get_type (inner_name, block);
void_type = cp_get_type("void *", block);
ptr_size = TYPE_LENGTH(void_type);
if (inner_type == NULL)
{
if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
fprintf_filtered (stream, " // no information for type %s\n", inner_name);
}
else
{
if ( inner_name_is_pointer(inner_name)) {
strcpy(inner_name2,inner_name);
inner_name2[strlen(inner_name2)-1] = 0;
//fprintf_filtered (stream, "inner type is pointer\n");
}
idx = 0;
head_node = (CORE_ADDR)read_memory_integer (address, ptr_size);
node = (CORE_ADDR)read_memory_integer (head_node, ptr_size);
b = (gdb_byte *)malloc(TYPE_LENGTH(inner_type));
do
{
if (idx >= stllimit)
{
fprintf_filtered (stream, "...");
break;
}
data_ptr = (CORE_ADDR)(node + ptr_size * 2);
if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
if (!stlprintcompatible) {
fprintf_filtered(stream, "[%d] = ", idx);
}
idx++;
read_memory(data_ptr, b, TYPE_LENGTH(inner_type));
c_val_print(inner_type, b, 0, data_ptr, stream, format, 0, recurse + 1, pretty);
if ( inner_name_is_pointer(inner_name) ){
//data_ptr2 = unpack_pointer( inner_type2, b);
memcpy(&data_ptr2, b, sizeof(CORE_ADDR));
inner_type2 = get_real_inner_type2(inner_name2,block,data_ptr2);
b2 = (gdb_byte *)malloc(TYPE_LENGTH(inner_type2));
read_memory(data_ptr2, b2, TYPE_LENGTH(inner_type2));
fprintf_filtered(stream," <%s> = ",inner_type2->main_type->name);
c_val_print(inner_type2, b2, 0, data_ptr2, stream, format, 0, recurse + 1, pretty);
free(b2);
b2 = 0;
}
node = (CORE_ADDR)read_memory_integer (node, ptr_size);
if (node != head_node) fprintf_filtered(stream, ", ");
if (pretty)
{
fprintf_filtered(stream, "\n");
}
} while (node != head_node);
free(b);
}
if (pretty) print_spaces_filtered (2 * recurse, stream);
fprintf_filtered (stream, "}");
if (recurse == 0) fprintf_filtered (stream, "\n");
}
free(inner_name);
}
#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 const int gRbTreeHeadOffset = 0;
static const int gRbTreeNodeOffset = 2;
static const int gRbTreeCountOffset = 1;
static const int gRbTreeDataPointerOffset = 4;
//static int gValueOffset = 0;
void
cp_print_stl_set(struct type *type, CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
char *inner_name;
CORE_ADDR pc;
CORE_ADDR head;
CORE_ADDR node;
CORE_ADDR left;
CORE_ADDR tmp_node;
CORE_ADDR data_ptr;
struct frame_info *current_frame;
struct type *inner_type;
struct type *void_type;
struct block *block;
int ptr_size;
unsigned int idx;
int count;
gdb_byte *b;
inner_name = (char *)malloc(strlen(type->main_type->name) + 1);
if (get_stl_inner_type(type, inner_name))
{
if (!stlprintcompatible) fprintf_filtered (stream, "set<%s>", inner_name);
fprintf_filtered (stream, "{");
if (pretty) fprintf_filtered (stream, "\n");
current_frame = get_current_frame ();
pc = get_frame_address_in_block (current_frame);
block = block_for_pc (pc);
inner_type = cp_get_type (inner_name, block);
void_type = cp_get_type("void *", block);
ptr_size = TYPE_LENGTH(void_type);
if (inner_type == NULL)
{
if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
fprintf_filtered (stream, " // no information for type %s\n", inner_name);
}
else
{
b = (gdb_byte *)malloc(TYPE_LENGTH(inner_type));
head = (CORE_ADDR)read_memory_integer (address + gRbTreeHeadOffset * ptr_size, ptr_size);
node = (CORE_ADDR)read_memory_integer (head + gRbTreeNodeOffset * ptr_size, ptr_size);
count = (int)read_memory_integer(address + gRbTreeCountOffset * ptr_size, ptr_size);
for (idx=0; idx<count; idx++)
{
if (idx >= stllimit)
{
fprintf_filtered (stream, "...");
break;
}
data_ptr = (CORE_ADDR)(node + ptr_size * gRbTreeDataPointerOffset);
if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx);
read_memory(data_ptr, b, TYPE_LENGTH(inner_type));
c_val_print(inner_type, b, 0, data_ptr, stream, format, 0, 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(tmp_node))
{
node = tmp_node;
tmp_node = TREE_PARENT(node);
}
if (TREE_RIGHT(node) != tmp_node)
{
node = tmp_node;
}
}
if (idx != count - 1) fprintf_filtered(stream, ", ");
if (pretty)
{
fprintf_filtered(stream, "\n");
}
}
free(b);
}
if (pretty) print_spaces_filtered (2 * recurse, stream);
fprintf_filtered (stream, "}");
if (recurse == 0) fprintf_filtered (stream, "\n");
}
free(inner_name);
}
void
cp_print_stl_map(struct type *type, CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
char *inner_key;
char *inner_value;
CORE_ADDR pc;
CORE_ADDR head;
CORE_ADDR node;
CORE_ADDR left;
CORE_ADDR tmp_node;
CORE_ADDR data_ptr;
struct frame_info *current_frame;
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;
gdb_byte *b_key;
gdb_byte *b_value;
int key_len;
int val_len;
inner_key = (char *)malloc(strlen(type->main_type->name) + 1);
inner_value = (char *)malloc(strlen(type->main_type->name) + 1);
if (get_stl_inner_type_pair(type, inner_key, inner_value))
{
if (!stlprintcompatible) fprintf_filtered (stream, "map<%s, %s>", inner_key, inner_value);
fprintf_filtered (stream, "{");
if (pretty) fprintf_filtered (stream, "\n");
current_frame = get_current_frame ();
pc = get_frame_address_in_block (current_frame);
block = block_for_pc (pc);
inner_type_key = cp_get_type (inner_key, block);
inner_type_value = cp_get_type (inner_value, block);
void_type = cp_get_type("void *", block);
ptr_size = TYPE_LENGTH(void_type);
if (inner_type_key == NULL || inner_type_value == NULL)
{
if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
fprintf_filtered (stream, " // no information for type std::pair<%s, %s>\n", inner_key, inner_value);
}
else
{
key_len = TYPE_LENGTH(inner_type_key);
val_len = TYPE_LENGTH(inner_type_value);
b_key = (gdb_byte *)malloc(key_len);
b_value = (gdb_byte *)malloc(val_len);
head = (CORE_ADDR)read_memory_integer (address + gRbTreeHeadOffset * ptr_size, ptr_size);
node = (CORE_ADDR)read_memory_integer (head + gRbTreeNodeOffset * ptr_size, ptr_size);
count = (int)read_memory_integer(address + gRbTreeCountOffset * ptr_size, ptr_size);
for (idx=0; idx<count; idx++)
{
if (idx >= stllimit)
{
fprintf_filtered (stream, "...");
break;
}
data_ptr = (CORE_ADDR)(node + ptr_size * gRbTreeDataPointerOffset);
read_memory(data_ptr, b_key, key_len);
read_memory(data_ptr + key_len, b_value, val_len);
if (pretty) print_spaces_filtered (2 + 2 * recurse, stream);
if (!stlprintcompatible) fprintf_filtered(stream, "[%d] = ", idx);
fprintf_filtered (stream, "{");
if (pretty) fprintf_filtered(stream, "\n");
if (pretty) print_spaces_filtered (4 + 2 * recurse, stream);
if (!stlprintcompatible)
{
fprintf_filtered(stream, "key ");
if (pretty) fprintf_filtered(stream, " ");
fprintf_filtered(stream, "= ");
}
c_val_print(inner_type_key, b_key, 0, data_ptr , stream, format, 0, recurse + 3, pretty);
if (pretty) fprintf_filtered(stream, ",\n"); else fprintf_filtered(stream, ", ");
if (pretty) print_spaces_filtered (4 + 2 * recurse, stream);
if (!stlprintcompatible)
{
fprintf_filtered(stream, "value = ");
}
c_val_print(inner_type_value, b_value, 0, data_ptr + key_len, stream, format, 0, recurse + 3, pretty);
if (pretty) fprintf_filtered(stream, "\n");
if (pretty) print_spaces_filtered (4 + 2 * recurse, stream);
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(tmp_node))
{
node = tmp_node;
tmp_node = TREE_PARENT(node);
}
if (TREE_RIGHT(node) != tmp_node)
{
node = tmp_node;
}
}
if (idx != count - 1) fprintf_filtered(stream, ", ");
if (pretty)
{
fprintf_filtered(stream, "\n");
}
}
free(b_key);
free(b_value);
}
if (pretty) print_spaces_filtered (2 * recurse, stream);
fprintf_filtered (stream, "}");
if (recurse == 0) fprintf_filtered (stream, "\n");
}
free(inner_key);
free(inner_value);
}
void
cp_print_stl_string(struct type *type, CORE_ADDR address,
struct ui_file *stream, int format, int recurse,
enum val_prettyprint pretty)
{
struct type *char_type;
struct frame_info *current_frame;
struct block *block;
int ptr_size;
int pc;
CORE_ADDR string_ptr;
current_frame = get_current_frame ();
pc = get_frame_address_in_block (current_frame);
block = block_for_pc (pc);
char_type = cp_get_type("char *", block);
ptr_size = TYPE_LENGTH(char_type);
string_ptr = read_memory_integer (address, ptr_size);
val_print_string (string_ptr, -1, 1, stream);
}
CHECK_TYPEDEF (type);
if ( stlprint && type->main_type->name )
{
// comment out certain stl types for now
if (!strncmp(type->main_type->name, "std::vector<", 12))
{
cp_print_stl_vector(type, address, stream, format, recurse, pretty);
return;
}
if (!strncmp(type->main_type->name, "std::list<", 10))
{
cp_print_stl_list(type, address, stream, format, recurse, pretty);
return;
}
if (!strncmp(type->main_type->name, "std::set<", 9) || !strncmp(type->main_type->name, "std::multiset<", 14))
{
cp_print_stl_set(type, address, stream, format, recurse, pretty);
return;
}
if (!strncmp(type->main_type->name, "std::map<", 9) || !strncmp(type->main_type->name, "std::multimap<", 14))
{
cp_print_stl_map(type, address, stream, format, recurse, pretty);
return;
}
if (!strncmp(type->main_type->name, "std::basic_string<char,", 23) ||
!strncmp(type->main_type->name, "std::string", 11) )
{
cp_print_stl_string(type, address, stream, format, recurse, pretty);
return;
}
}
add_setshow_boolean_cmd ("stl", class_support, &stlprint, _("\
Set printing of STL containers."), _("\
Show printing of STL containers."), NULL,
NULL,
show_stlprint,
&setprintlist, &showprintlist);
stlprint = 0;
add_setshow_boolean_cmd ("stl_array_compatible", class_support, &stlprintcompatible, _("\
Set compatibility with classic arrays while printing STL containers."), _("\
Show compatibility of STL containers printing."), NULL,
NULL,
show_stlprintcompatible,
&setprintlist, &showprintlist);
stlprintcompatible = 1;
add_setshow_uinteger_cmd ("stllimit", class_support,
&stllimit,
_("Set the maximum number of elements to display in STL containers."),
_("Show the maximum number of elements to display in STL containers."),
_("Show the maximum number of elements to display in STL containers. Zero is unlimited."),
NULL,
show_stllimit,
&setprintlist, &showprintlist);
stllimit = 50;
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2009-05-27 21:24 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-04-22 12:29 Using STL containers with GDB Vincent Benony
2008-04-22 14:41 ` Daniel Jacobowitz
2008-04-22 14:49 ` Vincent Benony
2008-04-22 17:51 ` Thiago Jung Bauermann
2008-04-22 18:37 ` Vladimir Prus
2008-04-22 22:13 ` Nick Roberts
2008-04-22 22:56 ` Daniel Jacobowitz
2008-04-23 6:49 ` Vincent Bénony
2008-04-23 8:53 ` Eli Zaretskii
2008-04-23 9:29 ` BENONY Vincent
2008-04-23 10:12 ` Nick Roberts
2008-04-23 12:22 ` Daniel Jacobowitz
2009-05-27 20:27 Using STL Containers With GDB Ken Lauterbach
2009-05-27 21:24 ` Paul Pluzhnikov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox