/* Go language support routines for GDB, the GNU debugger.
- Copyright (C) 2012-2021 Free Software Foundation, Inc.
+ Copyright (C) 2012-2023 Free Software Foundation, Inc.
This file is part of GDB.
*/
#include "defs.h"
-#include "gdb_obstack.h"
+#include "gdbsupport/gdb_obstack.h"
#include "block.h"
#include "symtab.h"
#include "language.h"
type1 = check_typedef (type1);
if (type0->code () == TYPE_CODE_PTR
- && strcmp (TYPE_FIELD_NAME (type, 0), "__data") == 0
+ && strcmp (type->field (0).name (), "__data") == 0
&& type1->code () == TYPE_CODE_INT
- && strcmp (TYPE_FIELD_NAME (type, 1), "__length") == 0)
+ && 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 (target_type->code () == TYPE_CODE_INT
- && TYPE_LENGTH (target_type) == 1
+ && target_type->length () == 1
&& strcmp (target_type->name (), "uint8") == 0)
return 1;
}
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.
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,
/* 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;
}
/* 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;
}
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
/* 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;
}
unpack_package_and_object (buf, packagep, objectp);
- return buf;
+ return result;
}
/* Implements the la_demangle language_defn routine for language Go.
This demangler can't work in all situations,
thus not too much effort is currently put into it. */
-char *
+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;
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)
}
obstack_grow_str0 (&tempbuf, "");
- result = xstrdup ((const char *) obstack_finish (&tempbuf));
- obstack_free (&tempbuf, NULL);
- xfree (name_buf);
- return result;
-}
-
-/* See language.h. */
-
-const struct exp_descriptor *
-go_language::expression_ops () const
-{
- return &exp_descriptor_c;
+ return make_unique_xstrdup ((const char *) obstack_finish (&tempbuf));
}
-/* Given a Go symbol, return its package or NULL if unknown.
- Space for the result is malloc'd, caller must free. */
+/* See go-lang.h. */
-char *
+gdb::unique_xmalloc_ptr<char>
go_symbol_package_name (const struct symbol *sym)
{
const char *mangled_name = sym->linkage_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 (sym->language () == 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,
/* 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;
return NULL;
}
- block = BLOCK_SUPERBLOCK (block);
+ block = block->superblock ();
}
return NULL;
}
-/* See go-lang.h.
-
- TODO(dje): &^ ? */
-
-const struct op_print go_language::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}
-};
-
/* See language.h. */
void
static go_language go_language_defn;
-static void *
+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, TARGET_CHAR_BIT, "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
= init_complex_type ("complex64", builtin_go_type->builtin_float32);
builtin_go_type->builtin_complex128
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
-_initialize_go_language ()
-{
- go_type_data = gdbarch_data_register_post_init (build_go_types);
+ return result;
}