From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11448 invoked by alias); 27 May 2009 20:27:54 -0000 Received: (qmail 11424 invoked by uid 22791); 27 May 2009 20:27:50 -0000 X-SWARE-Spam-Status: No, hits=1.4 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_65,KAM_STOCKGEN,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail2.panix.com (HELO mail2.panix.com) (166.84.1.73) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 27 May 2009 20:27:41 +0000 Received: from panix2.panix.com (panix2.panix.com [166.84.1.2]) by mail2.panix.com (Postfix) with ESMTP id B798238EA0; Wed, 27 May 2009 16:27:38 -0400 (EDT) Received: by panix2.panix.com (Postfix, from userid 13744) id AB71633D02; Wed, 27 May 2009 16:27:38 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by panix2.panix.com (Postfix) with ESMTP id 9DFD033CE7; Wed, 27 May 2009 16:27:38 -0400 (EDT) Date: Wed, 27 May 2009 20:27:00 -0000 From: Ken Lauterbach To: gdb-patches@sourceware.org cc: Ken Lauterbach Subject: Using STL Containers With GDB Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed 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: 2009-05/txt/msg00591.txt.bz2 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= 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= 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_stringmain_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;