Imported Upstream version 7.9
[platform/upstream/gdb.git] / gdb / gnu-v3-abi.c
index 3a83e2d..41c6735 100644 (file)
@@ -1,7 +1,7 @@
 /* Abstraction of GNU v3 abi.
    Contributed by Jim Blandy <jimb@redhat.com>
 
-   Copyright (C) 2001-2003, 2005-2012 Free Software Foundation, Inc.
+   Copyright (C) 2001-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "objfiles.h"
 #include "valprint.h"
 #include "c-lang.h"
-#include "exceptions.h"
-
-#include "gdb_assert.h"
-#include "gdb_string.h"
+#include "typeprint.h"
 
 static struct cp_abi_ops gnu_v3_abi_ops;
 
+/* A gdbarch key for std::type_info, in the event that it can't be
+   found in the debug info.  */
+
+static struct gdbarch_data *std_type_info_gdbarch_data;
+
+
 static int
 gnuv3_is_vtable_name (const char *name)
 {
@@ -164,7 +167,7 @@ build_gdb_vtable_type (struct gdbarch *arch)
   TYPE_TAG_NAME (t) = "gdb_gnu_v3_abi_vtable";
   INIT_CPLUS_SPECIFIC (t);
 
-  return t;
+  return make_type_with_address_space (t, TYPE_INSTANCE_FLAG_CODE_SPACE);
 }
 
 
@@ -282,9 +285,10 @@ gnuv3_rtti_type (struct value *value,
   const char *class_name;
   struct type *run_time_type;
   LONGEST offset_to_top;
+  char *atsign;
 
   /* We only have RTTI for class objects.  */
-  if (TYPE_CODE (values_type) != TYPE_CODE_CLASS)
+  if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT)
     return NULL;
 
   /* Java doesn't have RTTI following the C++ ABI.  */
@@ -305,7 +309,7 @@ gnuv3_rtti_type (struct value *value,
   /* Find the linker symbol for this vtable.  */
   vtable_symbol
     = lookup_minimal_symbol_by_pc (value_address (vtable)
-                                   + value_embedded_offset (vtable));
+                                   + value_embedded_offset (vtable)).minsym;
   if (! vtable_symbol)
     return NULL;
   
@@ -314,7 +318,7 @@ gnuv3_rtti_type (struct value *value,
      If we didn't like this approach, we could instead look in the
      type_info object itself to get the class name.  But this way
      should work just as well, and doesn't read target memory.  */
-  vtable_symbol_name = SYMBOL_DEMANGLED_NAME (vtable_symbol);
+  vtable_symbol_name = MSYMBOL_DEMANGLED_NAME (vtable_symbol);
   if (vtable_symbol_name == NULL
       || strncmp (vtable_symbol_name, "vtable for ", 11))
     {
@@ -326,6 +330,18 @@ gnuv3_rtti_type (struct value *value,
     }
   class_name = vtable_symbol_name + 11;
 
+  /* Strip off @plt and version suffixes.  */
+  atsign = strchr (class_name, '@');
+  if (atsign != NULL)
+    {
+      char *copy;
+
+      copy = alloca (atsign - class_name + 1);
+      memcpy (copy, class_name, atsign - class_name);
+      copy[atsign - class_name] = '\0';
+      class_name = copy;
+    }
+
   /* Try to look up the class name as a type name.  */
   /* FIXME: chastain/2003-11-26: block=NULL is bogus.  See pr gdb/1465.  */
   run_time_type = cp_lookup_rtti_type (class_name, NULL);
@@ -390,7 +406,7 @@ gnuv3_virtual_fn_field (struct value **value_p,
   struct gdbarch *gdbarch;
 
   /* Some simple sanity checks.  */
-  if (TYPE_CODE (values_type) != TYPE_CODE_CLASS)
+  if (TYPE_CODE (values_type) != TYPE_CODE_STRUCT)
     error (_("Only classes can have virtual functions."));
 
   /* Determine architecture.  */
@@ -592,8 +608,8 @@ gnuv3_print_method_ptr (const gdb_byte *contents,
         possible paths to the method based on the adjustment.  */
       if (physname)
        {
-         char *demangled_name = cplus_demangle (physname,
-                                                DMGL_ANSI | DMGL_PARAMS);
+         char *demangled_name = gdb_demangle (physname,
+                                              DMGL_ANSI | DMGL_PARAMS);
 
          fprintf_filtered (stream, "&virtual ");
          if (demangled_name == NULL)
@@ -610,7 +626,7 @@ gnuv3_print_method_ptr (const gdb_byte *contents,
     {
       /* Found a non-virtual function: print out the type.  */
       fputs_filtered ("(", stream);
-      c_print_type (type, "", stream, -1, 0);
+      c_print_type (type, "", stream, -1, 0, &type_print_raw_options);
       fputs_filtered (") ", stream);
     }
 
@@ -804,7 +820,6 @@ compute_vtable_size (htab_t offset_hash,
   struct type *type = check_typedef (value_type (value));
   void **slot;
   struct value_and_voffset search_vo, *current_vo;
-  CORE_ADDR addr = value_address (value) + value_embedded_offset (value);
 
   /* If the object is not dynamic, then we are done; as it cannot have
      dynamic base types either.  */
@@ -971,15 +986,226 @@ gnuv3_print_vtable (struct value *value)
   do_cleanups (cleanup);
 }
 
+/* Return a GDB type representing `struct std::type_info', laid out
+   appropriately for ARCH.
+
+   We use this function as the gdbarch per-architecture data
+   initialization function.  */
+
+static void *
+build_std_type_info_type (struct gdbarch *arch)
+{
+  struct type *t;
+  struct field *field_list, *field;
+  int offset;
+  struct type *void_ptr_type
+    = builtin_type (arch)->builtin_data_ptr;
+  struct type *char_type
+    = builtin_type (arch)->builtin_char;
+  struct type *char_ptr_type
+    = make_pointer_type (make_cv_type (1, 0, char_type, NULL), NULL);
+
+  field_list = xmalloc (sizeof (struct field [2]));
+  memset (field_list, 0, sizeof (struct field [2]));
+  field = &field_list[0];
+  offset = 0;
+
+  /* The vtable.  */
+  FIELD_NAME (*field) = "_vptr.type_info";
+  FIELD_TYPE (*field) = void_ptr_type;
+  SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT);
+  offset += TYPE_LENGTH (FIELD_TYPE (*field));
+  field++;
+
+  /* The name.  */
+  FIELD_NAME (*field) = "__name";
+  FIELD_TYPE (*field) = char_ptr_type;
+  SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT);
+  offset += TYPE_LENGTH (FIELD_TYPE (*field));
+  field++;
+
+  gdb_assert (field == (field_list + 2));
+
+  t = arch_type (arch, TYPE_CODE_STRUCT, offset, NULL);
+  TYPE_NFIELDS (t) = field - field_list;
+  TYPE_FIELDS (t) = field_list;
+  TYPE_TAG_NAME (t) = "gdb_gnu_v3_type_info";
+  INIT_CPLUS_SPECIFIC (t);
+
+  return t;
+}
+
+/* Implement the 'get_typeid_type' method.  */
+
+static struct type *
+gnuv3_get_typeid_type (struct gdbarch *gdbarch)
+{
+  struct symbol *typeinfo;
+  struct type *typeinfo_type;
+
+  typeinfo = lookup_symbol ("std::type_info", NULL, STRUCT_DOMAIN, NULL);
+  if (typeinfo == NULL)
+    typeinfo_type = gdbarch_data (gdbarch, std_type_info_gdbarch_data);
+  else
+    typeinfo_type = SYMBOL_TYPE (typeinfo);
+
+  return typeinfo_type;
+}
+
+/* Implement the 'get_typeid' method.  */
+
+static struct value *
+gnuv3_get_typeid (struct value *value)
+{
+  struct type *typeinfo_type;
+  struct type *type;
+  struct gdbarch *gdbarch;
+  struct cleanup *cleanup;
+  struct value *result;
+  char *typename, *canonical;
+
+  /* We have to handle values a bit trickily here, to allow this code
+     to work properly with non_lvalue values that are really just
+     disguised types.  */
+  if (value_lval_const (value) == lval_memory)
+    value = coerce_ref (value);
+
+  type = check_typedef (value_type (value));
+
+  /* In the non_lvalue case, a reference might have slipped through
+     here.  */
+  if (TYPE_CODE (type) == TYPE_CODE_REF)
+    type = check_typedef (TYPE_TARGET_TYPE (type));
+
+  /* Ignore top-level cv-qualifiers.  */
+  type = make_cv_type (0, 0, type, NULL);
+  gdbarch = get_type_arch (type);
+
+  typename = type_to_string (type);
+  if (typename == NULL)
+    error (_("cannot find typeinfo for unnamed type"));
+  cleanup = make_cleanup (xfree, typename);
+
+  /* We need to canonicalize the type name here, because we do lookups
+     using the demangled name, and so we must match the format it
+     uses.  E.g., GDB tends to use "const char *" as a type name, but
+     the demangler uses "char const *".  */
+  canonical = cp_canonicalize_string (typename);
+  if (canonical != NULL)
+    {
+      make_cleanup (xfree, canonical);
+      typename = canonical;
+    }
+
+  typeinfo_type = gnuv3_get_typeid_type (gdbarch);
+
+  /* We check for lval_memory because in the "typeid (type-id)" case,
+     the type is passed via a not_lval value object.  */
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+      && value_lval_const (value) == lval_memory
+      && gnuv3_dynamic_class (type))
+    {
+      struct value *vtable, *typeinfo_value;
+      CORE_ADDR address = value_address (value) + value_embedded_offset (value);
+
+      vtable = gnuv3_get_vtable (gdbarch, type, address);
+      if (vtable == NULL)
+       error (_("cannot find typeinfo for object of type '%s'"), typename);
+      typeinfo_value = value_field (vtable, vtable_field_type_info);
+      result = value_ind (value_cast (make_pointer_type (typeinfo_type, NULL),
+                                     typeinfo_value));
+    }
+  else
+    {
+      char *sym_name;
+      struct bound_minimal_symbol minsym;
+
+      sym_name = concat ("typeinfo for ", typename, (char *) NULL);
+      make_cleanup (xfree, sym_name);
+      minsym = lookup_minimal_symbol (sym_name, NULL, NULL);
+
+      if (minsym.minsym == NULL)
+       error (_("could not find typeinfo symbol for '%s'"), typename);
+
+      result = value_at_lazy (typeinfo_type, BMSYMBOL_VALUE_ADDRESS (minsym));
+    }
+
+  do_cleanups (cleanup);
+  return result;
+}
+
+/* Implement the 'get_typename_from_type_info' method.  */
+
+static char *
+gnuv3_get_typename_from_type_info (struct value *type_info_ptr)
+{
+  struct gdbarch *gdbarch = get_type_arch (value_type (type_info_ptr));
+  struct bound_minimal_symbol typeinfo_sym;
+  CORE_ADDR addr;
+  const char *symname;
+  const char *class_name;
+  const char *atsign;
+
+  addr = value_as_address (type_info_ptr);
+  typeinfo_sym = lookup_minimal_symbol_by_pc (addr);
+  if (typeinfo_sym.minsym == NULL)
+    error (_("could not find minimal symbol for typeinfo address %s"),
+          paddress (gdbarch, addr));
+
+#define TYPEINFO_PREFIX "typeinfo for "
+#define TYPEINFO_PREFIX_LEN (sizeof (TYPEINFO_PREFIX) - 1)
+  symname = MSYMBOL_DEMANGLED_NAME (typeinfo_sym.minsym);
+  if (symname == NULL || strncmp (symname, TYPEINFO_PREFIX,
+                                 TYPEINFO_PREFIX_LEN))
+    error (_("typeinfo symbol '%s' has unexpected name"),
+          MSYMBOL_LINKAGE_NAME (typeinfo_sym.minsym));
+  class_name = symname + TYPEINFO_PREFIX_LEN;
+
+  /* Strip off @plt and version suffixes.  */
+  atsign = strchr (class_name, '@');
+  if (atsign != NULL)
+    return savestring (class_name, atsign - class_name);
+  return xstrdup (class_name);
+}
+
+/* Implement the 'get_type_from_type_info' method.  */
+
+static struct type *
+gnuv3_get_type_from_type_info (struct value *type_info_ptr)
+{
+  char *typename;
+  struct cleanup *cleanup;
+  struct value *type_val;
+  struct expression *expr;
+  struct type *result;
+
+  typename = gnuv3_get_typename_from_type_info (type_info_ptr);
+  cleanup = make_cleanup (xfree, typename);
+
+  /* We have to parse the type name, since in general there is not a
+     symbol for a type.  This is somewhat bogus since there may be a
+     mis-parse.  Another approach might be to re-use the demangler's
+     internal form to reconstruct the type somehow.  */
+
+  expr = parse_expression (typename);
+  make_cleanup (xfree, expr);
+
+  type_val = evaluate_type (expr);
+  result = value_type (type_val);
+
+  do_cleanups (cleanup);
+  return result;
+}
+
 /* Determine if we are currently in a C++ thunk.  If so, get the address
    of the routine we are thunking to and continue to there instead.  */
 
 static CORE_ADDR 
 gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
 {
-  CORE_ADDR real_stop_pc, method_stop_pc;
+  CORE_ADDR real_stop_pc, method_stop_pc, func_addr;
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  struct minimal_symbol *thunk_sym, *fn_sym;
+  struct bound_minimal_symbol thunk_sym, fn_sym;
   struct obj_section *section;
   const char *thunk_name, *fn_name;
   
@@ -990,22 +1216,32 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
   /* Find the linker symbol for this potential thunk.  */
   thunk_sym = lookup_minimal_symbol_by_pc (real_stop_pc);
   section = find_pc_section (real_stop_pc);
-  if (thunk_sym == NULL || section == NULL)
+  if (thunk_sym.minsym == NULL || section == NULL)
     return 0;
 
   /* The symbol's demangled name should be something like "virtual
      thunk to FUNCTION", where FUNCTION is the name of the function
      being thunked to.  */
-  thunk_name = SYMBOL_DEMANGLED_NAME (thunk_sym);
+  thunk_name = MSYMBOL_DEMANGLED_NAME (thunk_sym.minsym);
   if (thunk_name == NULL || strstr (thunk_name, " thunk to ") == NULL)
     return 0;
 
   fn_name = strstr (thunk_name, " thunk to ") + strlen (" thunk to ");
   fn_sym = lookup_minimal_symbol (fn_name, NULL, section->objfile);
-  if (fn_sym == NULL)
+  if (fn_sym.minsym == NULL)
     return 0;
 
-  method_stop_pc = SYMBOL_VALUE_ADDRESS (fn_sym);
+  method_stop_pc = BMSYMBOL_VALUE_ADDRESS (fn_sym);
+
+  /* Some targets have minimal symbols pointing to function descriptors
+     (powerpc 64 for example).  Make sure to retrieve the address
+     of the real function from the function descriptor before passing on
+     the address to other layers of GDB.  */
+  func_addr = gdbarch_convert_from_func_ptr_addr (gdbarch, method_stop_pc,
+                                                  &current_target);
+  if (func_addr != 0)
+    method_stop_pc = func_addr;
+
   real_stop_pc = gdbarch_skip_trampoline_code
                   (gdbarch, frame, method_stop_pc);
   if (real_stop_pc == 0)
@@ -1041,10 +1277,14 @@ gnuv3_pass_by_reference (struct type *type)
 
   /* We're only interested in things that can have methods.  */
   if (TYPE_CODE (type) != TYPE_CODE_STRUCT
-      && TYPE_CODE (type) != TYPE_CODE_CLASS
       && TYPE_CODE (type) != TYPE_CODE_UNION)
     return 0;
 
+  /* A dynamic class has a non-trivial copy constructor.
+     See c++98 section 12.8 Copying class objects [class.copy].  */
+  if (gnuv3_dynamic_class (type))
+    return 1;
+
   for (fieldnum = 0; fieldnum < TYPE_NFN_FIELDS (type); fieldnum++)
     for (fieldelem = 0; fieldelem < TYPE_FN_FIELDLIST_LENGTH (type, fieldnum);
         fieldelem++)
@@ -1070,16 +1310,25 @@ gnuv3_pass_by_reference (struct type *type)
           with the mangled name.  We don't have a convenient function
           to strip off both leading scope qualifiers and trailing
           template arguments yet.  */
-       if (!is_constructor_name (TYPE_FN_FIELD_PHYSNAME (fn, fieldelem)))
+       if (!is_constructor_name (TYPE_FN_FIELD_PHYSNAME (fn, fieldelem))
+           && !TYPE_FN_FIELD_CONSTRUCTOR (fn, fieldelem))
          continue;
 
        /* If this method takes two arguments, and the second argument is
           a reference to this class, then it is a copy constructor.  */
-       if (TYPE_NFIELDS (fieldtype) == 2
-           && TYPE_CODE (TYPE_FIELD_TYPE (fieldtype, 1)) == TYPE_CODE_REF
-           && check_typedef (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (fieldtype,
-                                                                1))) == type)
-         return 1;
+       if (TYPE_NFIELDS (fieldtype) == 2)
+         {
+           struct type *arg_type = TYPE_FIELD_TYPE (fieldtype, 1);
+
+           if (TYPE_CODE (arg_type) == TYPE_CODE_REF)
+             {
+               struct type *arg_target_type;
+
+               arg_target_type = check_typedef (TYPE_TARGET_TYPE (arg_type));
+               if (class_types_same_p (arg_target_type, type))
+                 return 1;
+             }
+         }
       }
 
   /* Even if all the constructors and destructors were artificial, one
@@ -1102,6 +1351,8 @@ init_gnuv3_ops (void)
 {
   vtable_type_gdbarch_data
     = gdbarch_data_register_post_init (build_gdb_vtable_type);
+  std_type_info_gdbarch_data
+    = gdbarch_data_register_post_init (build_std_type_info_type);
 
   gnu_v3_abi_ops.shortname = "gnu-v3";
   gnu_v3_abi_ops.longname = "GNU G++ Version 3 ABI";
@@ -1120,6 +1371,11 @@ init_gnuv3_ops (void)
   gnu_v3_abi_ops.make_method_ptr = gnuv3_make_method_ptr;
   gnu_v3_abi_ops.method_ptr_to_value = gnuv3_method_ptr_to_value;
   gnu_v3_abi_ops.print_vtable = gnuv3_print_vtable;
+  gnu_v3_abi_ops.get_typeid = gnuv3_get_typeid;
+  gnu_v3_abi_ops.get_typeid_type = gnuv3_get_typeid_type;
+  gnu_v3_abi_ops.get_type_from_type_info = gnuv3_get_type_from_type_info;
+  gnu_v3_abi_ops.get_typename_from_type_info
+    = gnuv3_get_typename_from_type_info;
   gnu_v3_abi_ops.skip_trampoline = gnuv3_skip_trampoline;
   gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference;
 }
@@ -1132,4 +1388,5 @@ _initialize_gnu_v3_abi (void)
   init_gnuv3_ops ();
 
   register_cp_abi (&gnu_v3_abi_ops);
+  set_cp_abi_as_auto_default (gnu_v3_abi_ops.shortname);
 }