This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Using STL Containers With GDB


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;





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]