[gdb/symtab] Fix style issues in v9 .gdb_index section support
[binutils-gdb.git] / gdb / go-lang.c
index 7441bb30f6fbd56dd57670bb434e9298c06c6f5b..72ed9e73cd0c1fdb621f21c185410cbeeafbf94b 100644 (file)
@@ -1,6 +1,6 @@
 /* Go language support routines for GDB, the GNU debugger.
 
-   Copyright (C) 2012-2017 Free Software Foundation, Inc.
+   Copyright (C) 2012-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -32,7 +32,7 @@
 */
 
 #include "defs.h"
-#include "gdb_obstack.h"
+#include "gdbsupport/gdb_obstack.h"
 #include "block.h"
 #include "symtab.h"
 #include "language.h"
@@ -40,6 +40,7 @@
 #include "go-lang.h"
 #include "c-lang.h"
 #include "parser-defs.h"
+#include "gdbarch.h"
 
 #include <ctype.h>
 
@@ -72,26 +73,26 @@ gccgo_string_p (struct type *type)
 {
   /* gccgo strings don't necessarily have a name we can use.  */
 
-  if (TYPE_NFIELDS (type) == 2)
+  if (type->num_fields () == 2)
     {
-      struct type *type0 = TYPE_FIELD_TYPE (type, 0);
-      struct type *type1 = TYPE_FIELD_TYPE (type, 1);
+      struct type *type0 = type->field (0).type ();
+      struct type *type1 = type->field (1).type ();
 
       type0 = check_typedef (type0);
       type1 = check_typedef (type1);
 
-      if (TYPE_CODE (type0) == TYPE_CODE_PTR
-         && strcmp (TYPE_FIELD_NAME (type, 0), "__data") == 0
-         && TYPE_CODE (type1) == TYPE_CODE_INT
-         && strcmp (TYPE_FIELD_NAME (type, 1), "__length") == 0)
+      if (type0->code () == TYPE_CODE_PTR
+         && strcmp (type->field (0).name (), "__data") == 0
+         && type1->code () == TYPE_CODE_INT
+         && strcmp (type->field (1).name (), "__length") == 0)
        {
-         struct type *target_type = TYPE_TARGET_TYPE (type0);
+         struct type *target_type = type0->target_type ();
 
          target_type = check_typedef (target_type);
 
-         if (TYPE_CODE (target_type) == TYPE_CODE_INT
-             && TYPE_LENGTH (target_type) == 1
-             && strcmp (TYPE_NAME (target_type), "uint8") == 0)
+         if (target_type->code () == TYPE_CODE_INT
+             && target_type->length () == 1
+             && strcmp (target_type->name (), "uint8") == 0)
            return 1;
        }
     }
@@ -105,9 +106,9 @@ gccgo_string_p (struct type *type)
 static int
 sixg_string_p (struct type *type)
 {
-  if (TYPE_NFIELDS (type) == 2
-      && TYPE_TAG_NAME (type) != NULL
-      && strcmp (TYPE_TAG_NAME (type), "string") == 0)
+  if (type->num_fields () == 2
+      && type->name () != NULL
+      && strcmp (type->name (), "string") == 0)
     return 1;
 
   return 0;
@@ -162,11 +163,8 @@ unpack_package_and_object (char *buf,
 
    Space for the resulting strings is malloc'd in one buffer.
    PACKAGEP,OBJECTP,METHOD_TYPE* will (typically) point into this buffer.
-   [There are a few exceptions, but the caller is still responsible for
-   freeing the resulting pointer.]
    A pointer to this buffer is returned, or NULL if symbol isn't a
    mangled Go symbol.
-   The caller is responsible for freeing the result.
 
    *METHOD_TYPE_IS_POINTERP is set to a boolean indicating if
    the method type is a pointer.
@@ -179,7 +177,7 @@ unpack_package_and_object (char *buf,
    If we ever need to unpack the method type, this routine should work
    for that too.  */
 
-static char *
+static gdb::unique_xmalloc_ptr<char>
 unpack_mangled_go_symbol (const char *mangled_name,
                          const char **packagep,
                          const char **objectp,
@@ -208,9 +206,10 @@ unpack_mangled_go_symbol (const char *mangled_name,
   /* main.init is mangled specially.  */
   if (strcmp (mangled_name, "__go_init_main") == 0)
     {
-      char *package = xstrdup ("main");
+      gdb::unique_xmalloc_ptr<char> package
+       = make_unique_xstrdup ("main");
 
-      *packagep = package;
+      *packagep = package.get ();
       *objectp = "init";
       return package;
     }
@@ -218,9 +217,10 @@ unpack_mangled_go_symbol (const char *mangled_name,
   /* main.main is mangled specially (missing prefix).  */
   if (strcmp (mangled_name, "main.main") == 0)
     {
-      char *package = xstrdup ("main");
+      gdb::unique_xmalloc_ptr<char> package
+       = make_unique_xstrdup ("main");
 
-      *packagep = package;
+      *packagep = package.get ();
       *objectp = "main";
       return package;
     }
@@ -233,16 +233,28 @@ unpack_mangled_go_symbol (const char *mangled_name,
      libgo_.*: used by gccgo's runtime
 
      Thus we don't support -fgo-prefix (except as used by the runtime).  */
-  if (!startswith (mangled_name, "go.")
-      && !startswith (mangled_name, "libgo_"))
+  bool v3;
+  if (startswith (mangled_name, "go_0"))
+    /* V3 mangling detected, see
+       https://go-review.googlesource.com/c/gofrontend/+/271726 .  */
+    v3 = true;
+  else if (startswith (mangled_name, "go.")
+          || startswith (mangled_name, "libgo_"))
+    v3 = false;
+  else
     return NULL;
 
   /* Quick check for whether a search may be fruitful.  */
   /* Ignore anything with @plt, etc. in it.  */
   if (strchr (mangled_name, '@') != NULL)
     return NULL;
+
   /* It must have at least two dots.  */
-  first_dot = strchr (mangled_name, '.');
+  if (v3)
+    first_dot = strchr (mangled_name, '0');
+  else
+    first_dot = strchr (mangled_name, '.');
+
   if (first_dot == NULL)
     return NULL;
   /* Treat "foo.bar" as unmangled.  It can collide with lots of other
@@ -260,7 +272,20 @@ unpack_mangled_go_symbol (const char *mangled_name,
 
   /* At this point we've decided we have a mangled Go symbol.  */
 
-  buf = xstrdup (mangled_name);
+  gdb::unique_xmalloc_ptr<char> result = make_unique_xstrdup (mangled_name);
+  buf = result.get ();
+
+  if (v3)
+    {
+      /* Replace "go_0" with "\0go.".  */
+      buf[0] = '\0';
+      buf[1] = 'g';
+      buf[2] = 'o';
+      buf[3] = '.';
+
+      /* Skip the '\0'.  */
+      buf++;
+    }
 
   /* Search backwards looking for "N<digit(s)>".  */
   p = buf + len;
@@ -316,7 +341,7 @@ unpack_mangled_go_symbol (const char *mangled_name,
     }
 
   unpack_package_and_object (buf, packagep, objectp);
-  return buf;
+  return result;
 }
 
 /* Implements the la_demangle language_defn routine for language Go.
@@ -332,12 +357,9 @@ unpack_mangled_go_symbol (const char *mangled_name,
    This demangler can't work in all situations,
    thus not too much effort is currently put into it.  */
 
-char *
-go_demangle (const char *mangled_name, int options)
+gdb::unique_xmalloc_ptr<char>
+go_language::demangle_symbol (const char *mangled_name, int options) const
 {
-  struct obstack tempbuf;
-  char *result;
-  char *name_buf;
   const char *package_name;
   const char *object_name;
   const char *method_type_package_name;
@@ -347,15 +369,16 @@ go_demangle (const char *mangled_name, int options)
   if (mangled_name == NULL)
     return NULL;
 
-  name_buf = unpack_mangled_go_symbol (mangled_name,
-                                      &package_name, &object_name,
-                                      &method_type_package_name,
-                                      &method_type_object_name,
-                                      &method_type_is_pointer);
+  gdb::unique_xmalloc_ptr<char> name_buf
+    (unpack_mangled_go_symbol (mangled_name,
+                              &package_name, &object_name,
+                              &method_type_package_name,
+                              &method_type_object_name,
+                              &method_type_is_pointer));
   if (name_buf == NULL)
     return NULL;
 
-  obstack_init (&tempbuf);
+  auto_obstack tempbuf;
 
   /* Print methods as they appear in "method expressions".  */
   if (method_type_package_name != NULL)
@@ -379,37 +402,24 @@ go_demangle (const char *mangled_name, int options)
     }
   obstack_grow_str0 (&tempbuf, "");
 
-  result = xstrdup ((const char *) obstack_finish (&tempbuf));
-  obstack_free (&tempbuf, NULL);
-  xfree (name_buf);
-  return result;
+  return make_unique_xstrdup ((const char *) obstack_finish (&tempbuf));
 }
 
-/* la_sniff_from_mangled_name for Go.  */
+/* See go-lang.h.  */
 
-static int
-go_sniff_from_mangled_name (const char *mangled, char **demangled)
-{
-  *demangled = go_demangle (mangled, 0);
-  return *demangled != NULL;
-}
-
-/* Given a Go symbol, return its package or NULL if unknown.
-   Space for the result is malloc'd, caller must free.  */
-
-char *
+gdb::unique_xmalloc_ptr<char>
 go_symbol_package_name (const struct symbol *sym)
 {
-  const char *mangled_name = SYMBOL_LINKAGE_NAME (sym);
+  const char *mangled_name = sym->linkage_name ();
   const char *package_name;
   const char *object_name;
   const char *method_type_package_name;
   const char *method_type_object_name;
   int method_type_is_pointer;
-  char *name_buf;
-  char *result;
+  gdb::unique_xmalloc_ptr<char> name_buf;
 
-  gdb_assert (SYMBOL_LANGUAGE (sym) == language_go);
+  if (sym->language () != language_go)
+    return nullptr;
   name_buf = unpack_mangled_go_symbol (mangled_name,
                                       &package_name, &object_name,
                                       &method_type_package_name,
@@ -418,24 +428,22 @@ go_symbol_package_name (const struct symbol *sym)
   /* Some Go symbols don't have mangled form we interpret (yet).  */
   if (name_buf == NULL)
     return NULL;
-  result = xstrdup (package_name);
-  xfree (name_buf);
-  return result;
+  return make_unique_xstrdup (package_name);
 }
 
-/* Return the package that BLOCK is in, or NULL if there isn't one.
-   Space for the result is malloc'd, caller must free.  */
+/* See go-lang.h.  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 go_block_package_name (const struct block *block)
 {
   while (block != NULL)
     {
-      struct symbol *function = BLOCK_FUNCTION (block);
+      struct symbol *function = block->function ();
 
       if (function != NULL)
        {
-         char *package_name = go_symbol_package_name (function);
+         gdb::unique_xmalloc_ptr<char> package_name
+           = go_symbol_package_name (function);
 
          if (package_name != NULL)
            return package_name;
@@ -446,232 +454,110 @@ go_block_package_name (const struct block *block)
          return NULL;
        }
 
-      block = BLOCK_SUPERBLOCK (block);
+      block = block->superblock ();
     }
 
   return NULL;
 }
 
-/* Table mapping opcodes into strings for printing operators
-   and precedences of the operators.
-   TODO(dje): &^ ?  */
-
-static const struct op_print go_op_print_tab[] =
-{
-  {",", BINOP_COMMA, PREC_COMMA, 0},
-  {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
-  {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
-  {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
-  {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
-  {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
-  {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
-  {"==", BINOP_EQUAL, PREC_EQUAL, 0},
-  {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
-  {"<=", BINOP_LEQ, PREC_ORDER, 0},
-  {">=", BINOP_GEQ, PREC_ORDER, 0},
-  {">", BINOP_GTR, PREC_ORDER, 0},
-  {"<", BINOP_LESS, PREC_ORDER, 0},
-  {">>", BINOP_RSH, PREC_SHIFT, 0},
-  {"<<", BINOP_LSH, PREC_SHIFT, 0},
-  {"+", BINOP_ADD, PREC_ADD, 0},
-  {"-", BINOP_SUB, PREC_ADD, 0},
-  {"*", BINOP_MUL, PREC_MUL, 0},
-  {"/", BINOP_DIV, PREC_MUL, 0},
-  {"%", BINOP_REM, PREC_MUL, 0},
-  {"@", BINOP_REPEAT, PREC_REPEAT, 0},
-  {"-", UNOP_NEG, PREC_PREFIX, 0},
-  {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
-  {"^", UNOP_COMPLEMENT, PREC_PREFIX, 0},
-  {"*", UNOP_IND, PREC_PREFIX, 0},
-  {"&", UNOP_ADDR, PREC_PREFIX, 0},
-  {"unsafe.Sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
-  {"++", UNOP_POSTINCREMENT, PREC_SUFFIX, 0},
-  {"--", UNOP_POSTDECREMENT, PREC_SUFFIX, 0},
-  {NULL, OP_NULL, PREC_SUFFIX, 0}
-};
-
-enum go_primitive_types {
-  go_primitive_type_void,
-  go_primitive_type_char,
-  go_primitive_type_bool,
-  go_primitive_type_int,
-  go_primitive_type_uint,
-  go_primitive_type_uintptr,
-  go_primitive_type_int8,
-  go_primitive_type_int16,
-  go_primitive_type_int32,
-  go_primitive_type_int64,
-  go_primitive_type_uint8,
-  go_primitive_type_uint16,
-  go_primitive_type_uint32,
-  go_primitive_type_uint64,
-  go_primitive_type_float32,
-  go_primitive_type_float64,
-  go_primitive_type_complex64,
-  go_primitive_type_complex128,
-  nr_go_primitive_types
-};
+/* See language.h.  */
 
-static void
-go_language_arch_info (struct gdbarch *gdbarch,
-                      struct language_arch_info *lai)
+void
+go_language::language_arch_info (struct gdbarch *gdbarch,
+                                struct language_arch_info *lai) const
 {
   const struct builtin_go_type *builtin = builtin_go_type (gdbarch);
 
-  lai->string_char_type = builtin->builtin_char;
-
-  lai->primitive_type_vector
-    = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_go_primitive_types + 1,
-                             struct type *);
-
-  lai->primitive_type_vector [go_primitive_type_void]
-    = builtin->builtin_void;
-  lai->primitive_type_vector [go_primitive_type_char]
-    = builtin->builtin_char;
-  lai->primitive_type_vector [go_primitive_type_bool]
-    = builtin->builtin_bool;
-  lai->primitive_type_vector [go_primitive_type_int]
-    = builtin->builtin_int;
-  lai->primitive_type_vector [go_primitive_type_uint]
-    = builtin->builtin_uint;
-  lai->primitive_type_vector [go_primitive_type_uintptr]
-    = builtin->builtin_uintptr;
-  lai->primitive_type_vector [go_primitive_type_int8]
-    = builtin->builtin_int8;
-  lai->primitive_type_vector [go_primitive_type_int16]
-    = builtin->builtin_int16;
-  lai->primitive_type_vector [go_primitive_type_int32]
-    = builtin->builtin_int32;
-  lai->primitive_type_vector [go_primitive_type_int64]
-    = builtin->builtin_int64;
-  lai->primitive_type_vector [go_primitive_type_uint8]
-    = builtin->builtin_uint8;
-  lai->primitive_type_vector [go_primitive_type_uint16]
-    = builtin->builtin_uint16;
-  lai->primitive_type_vector [go_primitive_type_uint32]
-    = builtin->builtin_uint32;
-  lai->primitive_type_vector [go_primitive_type_uint64]
-    = builtin->builtin_uint64;
-  lai->primitive_type_vector [go_primitive_type_float32]
-    = builtin->builtin_float32;
-  lai->primitive_type_vector [go_primitive_type_float64]
-    = builtin->builtin_float64;
-  lai->primitive_type_vector [go_primitive_type_complex64]
-    = builtin->builtin_complex64;
-  lai->primitive_type_vector [go_primitive_type_complex128]
-    = builtin->builtin_complex128;
-
-  lai->bool_type_symbol = "bool";
-  lai->bool_type_default = builtin->builtin_bool;
+  /* Helper function to allow shorter lines below.  */
+  auto add  = [&] (struct type * t) -> struct type *
+  {
+    lai->add_primitive_type (t);
+    return t;
+  };
+
+  add (builtin->builtin_void);
+  add (builtin->builtin_char);
+  add (builtin->builtin_bool);
+  add (builtin->builtin_int);
+  add (builtin->builtin_uint);
+  add (builtin->builtin_uintptr);
+  add (builtin->builtin_int8);
+  add (builtin->builtin_int16);
+  add (builtin->builtin_int32);
+  add (builtin->builtin_int64);
+  add (builtin->builtin_uint8);
+  add (builtin->builtin_uint16);
+  add (builtin->builtin_uint32);
+  add (builtin->builtin_uint64);
+  add (builtin->builtin_float32);
+  add (builtin->builtin_float64);
+  add (builtin->builtin_complex64);
+  add (builtin->builtin_complex128);
+
+  lai->set_string_char_type (builtin->builtin_char);
+  lai->set_bool_type (builtin->builtin_bool, "bool");
 }
 
-extern const struct language_defn go_language_defn =
-{
-  "go",
-  "Go",
-  language_go,
-  range_check_off,
-  case_sensitive_on,
-  array_row_major,
-  macro_expansion_no,
-  NULL,
-  &exp_descriptor_c,
-  go_parse,
-  go_yyerror,
-  null_post_parser,
-  c_printchar,                 /* Print a character constant.  */
-  c_printstr,                  /* Function to print string constant.  */
-  c_emit_char,                 /* Print a single char.  */
-  go_print_type,               /* Print a type using appropriate syntax.  */
-  c_print_typedef,             /* Print a typedef using appropriate
-                                  syntax.  */
-  go_val_print,                        /* Print a value using appropriate syntax.  */
-  c_value_print,               /* Print a top-level value.  */
-  default_read_var_value,      /* la_read_var_value */
-  NULL,                                /* Language specific skip_trampoline.  */
-  NULL,                                /* name_of_this */
-  basic_lookup_symbol_nonlocal, 
-  basic_lookup_transparent_type,
-  go_demangle,                 /* Language specific symbol demangler.  */
-  go_sniff_from_mangled_name,
-  NULL,                                /* Language specific
-                                  class_name_from_physname.  */
-  go_op_print_tab,             /* Expression operators for printing.  */
-  1,                           /* C-style arrays.  */
-  0,                           /* String lower bound.  */
-  default_word_break_characters,
-  default_collect_symbol_completion_matches,
-  go_language_arch_info,
-  default_print_array_index,
-  default_pass_by_reference,
-  c_get_string,
-  c_watch_location_expression,
-  NULL,                                /* la_get_symbol_name_cmp */
-  iterate_over_symbols,
-  &default_varobj_ops,
-  NULL,
-  NULL,
-  LANG_MAGIC
-};
-
-static void *
+/* Single instance of the Go language class.  */
+
+static go_language go_language_defn;
+
+static struct builtin_go_type *
 build_go_types (struct gdbarch *gdbarch)
 {
-  struct builtin_go_type *builtin_go_type
-    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_go_type);
+  struct builtin_go_type *builtin_go_type = new struct builtin_go_type;
 
-  builtin_go_type->builtin_void
-    = arch_type (gdbarch, TYPE_CODE_VOID, 1, "void");
+  type_allocator alloc (gdbarch);
+  builtin_go_type->builtin_void = builtin_type (gdbarch)->builtin_void;
   builtin_go_type->builtin_char
-    = arch_character_type (gdbarch, 8, 1, "char");
+    = init_character_type (alloc, 8, 1, "char");
   builtin_go_type->builtin_bool
-    = arch_boolean_type (gdbarch, 8, 0, "bool");
+    = init_boolean_type (alloc, 8, 0, "bool");
   builtin_go_type->builtin_int
-    = arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch), 0, "int");
+    = init_integer_type (alloc, gdbarch_int_bit (gdbarch), 0, "int");
   builtin_go_type->builtin_uint
-    = arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch), 1, "uint");
+    = init_integer_type (alloc, gdbarch_int_bit (gdbarch), 1, "uint");
   builtin_go_type->builtin_uintptr
-    = arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 1, "uintptr");
+    = init_integer_type (alloc, gdbarch_ptr_bit (gdbarch), 1, "uintptr");
   builtin_go_type->builtin_int8
-    = arch_integer_type (gdbarch, 8, 0, "int8");
+    = init_integer_type (alloc, 8, 0, "int8");
   builtin_go_type->builtin_int16
-    = arch_integer_type (gdbarch, 16, 0, "int16");
+    = init_integer_type (alloc, 16, 0, "int16");
   builtin_go_type->builtin_int32
-    = arch_integer_type (gdbarch, 32, 0, "int32");
+    = init_integer_type (alloc, 32, 0, "int32");
   builtin_go_type->builtin_int64
-    = arch_integer_type (gdbarch, 64, 0, "int64");
+    = init_integer_type (alloc, 64, 0, "int64");
   builtin_go_type->builtin_uint8
-    = arch_integer_type (gdbarch, 8, 1, "uint8");
+    = init_integer_type (alloc, 8, 1, "uint8");
   builtin_go_type->builtin_uint16
-    = arch_integer_type (gdbarch, 16, 1, "uint16");
+    = init_integer_type (alloc, 16, 1, "uint16");
   builtin_go_type->builtin_uint32
-    = arch_integer_type (gdbarch, 32, 1, "uint32");
+    = init_integer_type (alloc, 32, 1, "uint32");
   builtin_go_type->builtin_uint64
-    = arch_integer_type (gdbarch, 64, 1, "uint64");
+    = init_integer_type (alloc, 64, 1, "uint64");
   builtin_go_type->builtin_float32
-    = arch_float_type (gdbarch, 32, "float32", floatformats_ieee_single);
+    = init_float_type (alloc, 32, "float32", floatformats_ieee_single);
   builtin_go_type->builtin_float64
-    = arch_float_type (gdbarch, 64, "float64", floatformats_ieee_double);
+    = init_float_type (alloc, 64, "float64", floatformats_ieee_double);
   builtin_go_type->builtin_complex64
-    = arch_complex_type (gdbarch, "complex64",
-                        builtin_go_type->builtin_float32);
+    = init_complex_type ("complex64", builtin_go_type->builtin_float32);
   builtin_go_type->builtin_complex128
-    = arch_complex_type (gdbarch, "complex128",
-                        builtin_go_type->builtin_float64);
+    = init_complex_type ("complex128", builtin_go_type->builtin_float64);
 
   return builtin_go_type;
 }
 
-static struct gdbarch_data *go_type_data;
+static const registry<gdbarch>::key<struct builtin_go_type> go_type_data;
 
 const struct builtin_go_type *
 builtin_go_type (struct gdbarch *gdbarch)
 {
-  return (const struct builtin_go_type *) gdbarch_data (gdbarch, go_type_data);
-}
+  struct builtin_go_type *result = go_type_data.get (gdbarch);
+  if (result == nullptr)
+    {
+      result = build_go_types (gdbarch);
+      go_type_data.set (gdbarch, result);
+    }
 
-void
-_initialize_go_language (void)
-{
-  go_type_data = gdbarch_data_register_post_init (build_go_types);
+  return result;
 }