static const char *
gnuv3_find_method_in (struct type *domain, CORE_ADDR voffset,
		      LONGEST adjustment)
{
  int i;
  const char *physname;

  /* Search this class first.  */
  physname = NULL;
  if (adjustment == 0)
    {
      int len;

      len = TYPE_NFN_FIELDS (domain);
      for (i = 0; i < len; i++)
	{
	  int len2, j;
	  struct fn_field *f;

	  f = TYPE_FN_FIELDLIST1 (domain, i);
	  len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);

	  check_stub_method_group (domain, i);
	  for (j = 0; j < len2; j++)
	    if (TYPE_FN_FIELD_VOFFSET (f, j) == voffset)
	      return TYPE_FN_FIELD_PHYSNAME (f, j);
	}
    }

  /* Next search non-virtual bases.  If it's in a virtual base,
     we're out of luck.  */
  for (i = 0; i < TYPE_N_BASECLASSES (domain); i++)
    {
      int pos;
      struct type *basetype;

      if (BASETYPE_VIA_VIRTUAL (domain, i))
	continue;

      pos = TYPE_BASECLASS_BITPOS (domain, i) / 8;
      basetype = TYPE_FIELD_TYPE (domain, i);
      /* Recurse with a modified adjustment.  We don't need to adjust
	 voffset.  */
      if (adjustment >= pos && adjustment < pos + TYPE_LENGTH (basetype))
	return gnuv3_find_method_in (basetype, voffset, adjustment - pos);
    }

  return NULL;
}
Example #2
0
static void
gnuv3_print_method_ptr (const gdb_byte *contents,
			struct type *type,
			struct ui_file *stream)
{
  struct type *domain = TYPE_DOMAIN_TYPE (type);
  struct gdbarch *gdbarch = get_type_arch (domain);
  CORE_ADDR ptr_value;
  LONGEST adjustment;
  int vbit;

  /* Extract the pointer to member.  */
  vbit = gnuv3_decode_method_ptr (gdbarch, contents, &ptr_value, &adjustment);

  /* Check for NULL.  */
  if (ptr_value == 0 && vbit == 0)
    {
      fprintf_filtered (stream, "NULL");
      return;
    }

  /* Search for a virtual method.  */
  if (vbit)
    {
      CORE_ADDR voffset;
      const char *physname;

      /* It's a virtual table offset, maybe in this class.  Search
	 for a field with the correct vtable offset.  First convert it
	 to an index, as used in TYPE_FN_FIELD_VOFFSET.  */
      voffset = ptr_value / TYPE_LENGTH (vtable_ptrdiff_type (gdbarch));

      physname = gnuv3_find_method_in (domain, voffset, adjustment);

      /* If we found a method, print that.  We don't bother to disambiguate
	 possible paths to the method based on the adjustment.  */
      if (physname)
	{
	  char *demangled_name = gdb_demangle (physname,
					       DMGL_ANSI | DMGL_PARAMS);

	  fprintf_filtered (stream, "&virtual ");
	  if (demangled_name == NULL)
	    fputs_filtered (physname, stream);
	  else
	    {
	      fputs_filtered (demangled_name, stream);
	      xfree (demangled_name);
	    }
	  return;
	}
    }
  else if (ptr_value != 0)
    {
      /* Found a non-virtual function: print out the type.  */
      fputs_filtered ("(", stream);
      c_print_type (type, "", stream, -1, 0, &type_print_raw_options);
      fputs_filtered (") ", stream);
    }

  /* We didn't find it; print the raw data.  */
  if (vbit)
    {
      fprintf_filtered (stream, "&virtual table offset ");
      print_longest (stream, 'd', 1, ptr_value);
    }
  else
    {
      struct value_print_options opts;

      get_user_print_options (&opts);
      print_address_demangle (&opts, gdbarch, ptr_value, stream, demangle);
    }

  if (adjustment)
    {
      fprintf_filtered (stream, ", this adjustment ");
      print_longest (stream, 'd', 1, adjustment);
    }
}