Initial pass at Go language support.
* NEWS: Mention Go. * Makefile.in (SFILES): Add go-exp.y, go-lang.c, go-typeprint.c, go-valprint.c. (COMMON_OBS): Add go-lang.o, go-val.print.o, go-typeprint.o. (YYFILES): Add go-exp.c. (YYOBJ): Add go-exp.o. (local-maintainer-clean): Delete go-exp.c. * defs.h (enum language): Add language_go. * dwarf2read.c: #include "go-lang.h". (fixup_go_packaging): New function. (process_full_comp_unit): Call it when processing Go CUs. (dwarf2_physname): Add Go support. (read_file_scope): Handle missing language spec for GNU Go. (set_cu_language): Handle DW_LANG_Go. * go-exp.y: New file. * go-lang.h: New file. * go-lang.c: New file. * go-typeprint.c: New file. * go-valprint.c: New file. * symtab.c: #include "go-lang.h". (symbol_set_language): Handle language_go. (symbol_find_demangled_name, symbol_set_names): Ditto. (symbol_natural_name, demangle_for_lookup, find_main_name): Ditto. testsuite/ * configure.ac: Create gdb.go/Makefile. * configure: Regenerate. * gdb.base/default.exp: Add "go" to "set language" testing. * gdb.go/Makefile.in: New file. * gdb.go/basic-types.exp: New file. * gdb.go/chan.exp: New file. * gdb.go/chan.go: New file. * gdb.go/handcall.exp: New file. * gdb.go/handcall.go: New file. * gdb.go/hello.exp: New file. * gdb.go/hello.go: New file. * gdb.go/integers.exp: New file. * gdb.go/integers.go: New file. * gdb.go/methods.exp: New file. * gdb.go/methods.go: New file. * gdb.go/package.exp: New file. * gdb.go/package1.go: New file. * gdb.go/package2.go: New file. * gdb.go/print.exp: New file. * gdb.go/strings.exp: New file. * gdb.go/strings.go: New file. * gdb.go/types.exp: New file. * gdb.go/types.go: New file. * gdb.go/unsafe.exp: New file. * gdb.go/unsafe.go: New file. * lib/future.exp: Add Go support. (gdb_find_go, gdb_find_go_linker): New procs. (gdb_default_target_compile): Add Go support. * lib/gdb.exp (skip_go_tests): New proc. * lib/go.exp: New file. doc/ * gdb.texinfo (Supported Languages): Add Go. (Go): New node.
This commit is contained in:
parent
e65f9ffb8e
commit
a766d390bb
42 changed files with 3840 additions and 21 deletions
|
@ -1,3 +1,30 @@
|
|||
2012-04-25 Doug Evans <dje@google.com>
|
||||
|
||||
Initial pass at Go language support.
|
||||
* NEWS: Mention Go.
|
||||
* Makefile.in (SFILES): Add go-exp.y, go-lang.c, go-typeprint.c,
|
||||
go-valprint.c.
|
||||
(COMMON_OBS): Add go-lang.o, go-val.print.o, go-typeprint.o.
|
||||
(YYFILES): Add go-exp.c.
|
||||
(YYOBJ): Add go-exp.o.
|
||||
(local-maintainer-clean): Delete go-exp.c.
|
||||
* defs.h (enum language): Add language_go.
|
||||
* dwarf2read.c: #include "go-lang.h".
|
||||
(fixup_go_packaging): New function.
|
||||
(process_full_comp_unit): Call it when processing Go CUs.
|
||||
(dwarf2_physname): Add Go support.
|
||||
(read_file_scope): Handle missing language spec for GNU Go.
|
||||
(set_cu_language): Handle DW_LANG_Go.
|
||||
* go-exp.y: New file.
|
||||
* go-lang.h: New file.
|
||||
* go-lang.c: New file.
|
||||
* go-typeprint.c: New file.
|
||||
* go-valprint.c: New file.
|
||||
* symtab.c: #include "go-lang.h".
|
||||
(symbol_set_language): Handle language_go.
|
||||
(symbol_find_demangled_name, symbol_set_names): Ditto.
|
||||
(symbol_natural_name, demangle_for_lookup, find_main_name): Ditto.
|
||||
|
||||
2012-04-24 Jim Meyering <meyering@redhat.com>
|
||||
|
||||
avoid a few strncpy-induced buffer overruns
|
||||
|
|
|
@ -704,6 +704,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
|
|||
f-exp.y f-lang.c f-typeprint.c f-valprint.c filesystem.c \
|
||||
findcmd.c findvar.c frame.c frame-base.c frame-unwind.c \
|
||||
gdbarch.c arch-utils.c gdbtypes.c gnu-v2-abi.c gnu-v3-abi.c \
|
||||
go-exp.y go-lang.c go-typeprint.c go-valprint.c \
|
||||
inf-loop.c \
|
||||
infcall.c \
|
||||
infcmd.c inflow.c infrun.c \
|
||||
|
@ -769,7 +770,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
|
|||
exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h amd64bsd-nat.h \
|
||||
i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
|
||||
ia64-tdep.h ada-lang.h ada-varobj.h varobj.h frv-tdep.h nto-tdep.h serial.h \
|
||||
c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h \
|
||||
c-lang.h d-lang.h golang.h frame.h event-loop.h block.h cli/cli-setshow.h \
|
||||
cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h cli/cli-utils.h \
|
||||
cli/cli-script.h macrotab.h symtab.h version.h \
|
||||
gnulib/import/string.in.h gnulib/import/str-two-way.h \
|
||||
|
@ -889,6 +890,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
|
|||
ada-tasks.o ada-varobj.o \
|
||||
ui-out.o cli-out.o \
|
||||
varobj.o vec.o \
|
||||
go-lang.o go-valprint.o go-typeprint.o \
|
||||
jv-lang.o jv-valprint.o jv-typeprint.o \
|
||||
m2-lang.o opencl-lang.o p-lang.o p-typeprint.o p-valprint.o \
|
||||
sentinel-frame.o \
|
||||
|
@ -933,13 +935,13 @@ YYFILES = c-exp.c \
|
|||
ada-lex.c \
|
||||
ada-exp.c \
|
||||
jv-exp.c \
|
||||
f-exp.c m2-exp.c p-exp.c
|
||||
f-exp.c go-exp.c m2-exp.c p-exp.c
|
||||
YYOBJ = c-exp.o \
|
||||
cp-name-parser.o \
|
||||
objc-exp.o \
|
||||
ada-exp.o \
|
||||
jv-exp.o \
|
||||
f-exp.o m2-exp.o p-exp.o
|
||||
f-exp.o go-exp.o m2-exp.o p-exp.o
|
||||
|
||||
# Things which need to be built when making a distribution.
|
||||
|
||||
|
@ -1241,7 +1243,7 @@ local-maintainer-clean:
|
|||
ada-lex.c ada-exp.c \
|
||||
objc-exp.c \
|
||||
jv-exp.tab \
|
||||
f-exp.c m2-exp.c p-exp.c
|
||||
f-exp.c go-exp.c m2-exp.c p-exp.c
|
||||
rm -f TAGS $(INFOFILES)
|
||||
rm -f $(YYFILES)
|
||||
rm -f nm.h config.status
|
||||
|
|
4
gdb/NEWS
4
gdb/NEWS
|
@ -32,6 +32,10 @@
|
|||
** A new method 'referenced_value' on gdb.Value objects which can
|
||||
dereference pointer as well as C++ reference values.
|
||||
|
||||
* Go language support.
|
||||
GDB now supports debugging programs written in the Go programming
|
||||
language.
|
||||
|
||||
* GDBserver now supports stdio connections.
|
||||
E.g. (gdb) target remote | ssh myhost gdbserver - hello
|
||||
|
||||
|
|
|
@ -197,6 +197,7 @@ enum language
|
|||
language_c, /* C */
|
||||
language_cplus, /* C++ */
|
||||
language_d, /* D */
|
||||
language_go, /* Go */
|
||||
language_objc, /* Objective-C */
|
||||
language_java, /* Java */
|
||||
language_fortran, /* Fortran */
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2012-04-25 Doug Evans <dje@google.com>
|
||||
|
||||
* gdb.texinfo (Supported Languages): Add Go.
|
||||
(Go): New node.
|
||||
|
||||
2012-04-25 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* gdbint.texinfo (Testsuite): New section `Board settings'.
|
||||
|
|
|
@ -12487,8 +12487,8 @@ being set automatically by @value{GDBN}.
|
|||
@node Supported Languages
|
||||
@section Supported Languages
|
||||
|
||||
@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, OpenCL C, Pascal,
|
||||
assembly, Modula-2, and Ada.
|
||||
@value{GDBN} supports C, C@t{++}, D, Go, Objective-C, Fortran, Java,
|
||||
OpenCL C, Pascal, assembly, Modula-2, and Ada.
|
||||
@c This is false ...
|
||||
Some @value{GDBN} features may be used in expressions regardless of the
|
||||
language you use: the @value{GDBN} @code{@@} and @code{::} operators,
|
||||
|
@ -12507,6 +12507,7 @@ language reference or tutorial.
|
|||
@menu
|
||||
* C:: C and C@t{++}
|
||||
* D:: D
|
||||
* Go:: Go
|
||||
* Objective-C:: Objective-C
|
||||
* OpenCL C:: OpenCL C
|
||||
* Fortran:: Fortran
|
||||
|
@ -13059,6 +13060,55 @@ See @ref{PowerPC,,PowerPC} for more details.
|
|||
GDC, LDC or DMD compilers. Currently @value{GDBN} supports only one D
|
||||
specific feature --- dynamic arrays.
|
||||
|
||||
@node Go
|
||||
@subsection Go
|
||||
|
||||
@cindex Go (programming language)
|
||||
@value{GDBN} can be used to debug programs written in Go and compiled with
|
||||
@file{gccgo} or @file{6g} compilers.
|
||||
|
||||
Here is a summary of the Go-specific features and restrictions:
|
||||
|
||||
@table @code
|
||||
@cindex current Go package
|
||||
@item The current Go package
|
||||
The name of the current package does not need to be specified when
|
||||
specifying global variables and functions.
|
||||
|
||||
For example, given the program:
|
||||
|
||||
@example
|
||||
package main
|
||||
var myglob = "Shall we?"
|
||||
func main () @{
|
||||
// ...
|
||||
@}
|
||||
@end example
|
||||
|
||||
When stopped inside @code{main} either of these work:
|
||||
|
||||
@example
|
||||
(gdb) p myglob
|
||||
(gdb) p main.myglob
|
||||
@end example
|
||||
|
||||
@cindex builtin Go types
|
||||
@item Builtin Go types
|
||||
The @code{string} type is recognized by @value{GDBN} and is printed
|
||||
as a string.
|
||||
|
||||
@cindex builtin Go functions
|
||||
@item Builtin Go functions
|
||||
The @value{GDBN} expression parser recognizes the @code{unsafe.Sizeof}
|
||||
function and handles it internally.
|
||||
@end table
|
||||
|
||||
@cindex restrictions on Go expressions
|
||||
@item Restrictions on Go expressions
|
||||
All Go operators are supported except @code{&^}.
|
||||
The Go @code{_} ``blank identifier'' is not supported.
|
||||
Automatic dereferencing of pointers is not supported.
|
||||
|
||||
@node Objective-C
|
||||
@subsection Objective-C
|
||||
|
||||
|
|
113
gdb/dwarf2read.c
113
gdb/dwarf2read.c
|
@ -59,6 +59,7 @@
|
|||
#include "completer.h"
|
||||
#include "vec.h"
|
||||
#include "c-lang.h"
|
||||
#include "go-lang.h"
|
||||
#include "valprint.h"
|
||||
#include <ctype.h>
|
||||
|
||||
|
@ -4822,6 +4823,78 @@ compute_delayed_physnames (struct dwarf2_cu *cu)
|
|||
}
|
||||
}
|
||||
|
||||
/* Go objects should be embedded in a DW_TAG_module DIE,
|
||||
and it's not clear if/how imported objects will appear.
|
||||
To keep Go support simple until that's worked out,
|
||||
go back through what we've read and create something usable.
|
||||
We could do this while processing each DIE, and feels kinda cleaner,
|
||||
but that way is more invasive.
|
||||
This is to, for example, allow the user to type "p var" or "b main"
|
||||
without having to specify the package name, and allow lookups
|
||||
of module.object to work in contexts that use the expression
|
||||
parser. */
|
||||
|
||||
static void
|
||||
fixup_go_packaging (struct dwarf2_cu *cu)
|
||||
{
|
||||
char *package_name = NULL;
|
||||
struct pending *list;
|
||||
int i;
|
||||
|
||||
for (list = global_symbols; list != NULL; list = list->next)
|
||||
{
|
||||
for (i = 0; i < list->nsyms; ++i)
|
||||
{
|
||||
struct symbol *sym = list->symbol[i];
|
||||
|
||||
if (SYMBOL_LANGUAGE (sym) == language_go
|
||||
&& SYMBOL_CLASS (sym) == LOC_BLOCK)
|
||||
{
|
||||
char *this_package_name = go_symbol_package_name (sym);
|
||||
|
||||
if (this_package_name == NULL)
|
||||
continue;
|
||||
if (package_name == NULL)
|
||||
package_name = this_package_name;
|
||||
else
|
||||
{
|
||||
if (strcmp (package_name, this_package_name) != 0)
|
||||
complaint (&symfile_complaints,
|
||||
_("Symtab %s has objects from two different Go packages: %s and %s"),
|
||||
(sym->symtab && sym->symtab->filename
|
||||
? sym->symtab->filename
|
||||
: cu->objfile->name),
|
||||
this_package_name, package_name);
|
||||
xfree (this_package_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (package_name != NULL)
|
||||
{
|
||||
struct objfile *objfile = cu->objfile;
|
||||
struct type *type = init_type (TYPE_CODE_MODULE, 0, 0,
|
||||
package_name, objfile);
|
||||
struct symbol *sym;
|
||||
|
||||
TYPE_TAG_NAME (type) = TYPE_NAME (type);
|
||||
|
||||
sym = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symbol);
|
||||
SYMBOL_SET_LANGUAGE (sym, language_go);
|
||||
SYMBOL_SET_NAMES (sym, package_name, strlen (package_name), 1, objfile);
|
||||
/* This is not VAR_DOMAIN because we want a way to ensure a lookup of,
|
||||
e.g., "main" finds the "main" module and not C's main(). */
|
||||
SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
|
||||
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
|
||||
SYMBOL_TYPE (sym) = type;
|
||||
|
||||
add_symbol_to_list (sym, &global_symbols);
|
||||
|
||||
xfree (package_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Generate full symbol information for PER_CU, whose DIEs have
|
||||
already been loaded into memory. */
|
||||
|
||||
|
@ -4846,6 +4919,10 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
|
|||
/* Do line number decoding in read_file_scope () */
|
||||
process_die (cu->dies, cu);
|
||||
|
||||
/* For now fudge the Go package. */
|
||||
if (cu->language == language_go)
|
||||
fixup_go_packaging (cu);
|
||||
|
||||
/* Now that we have processed all the DIEs in the CU, all the types
|
||||
should be complete, and it should now be safe to compute all of the
|
||||
physnames. */
|
||||
|
@ -5055,8 +5132,14 @@ do_ui_file_peek_last (void *object, const char *buffer, long length)
|
|||
}
|
||||
|
||||
/* Compute the fully qualified name of DIE in CU. If PHYSNAME is nonzero,
|
||||
compute the physname for the object, which include a method's
|
||||
formal parameters (C++/Java) and return type (Java).
|
||||
compute the physname for the object, which include a method's:
|
||||
- formal parameters (C++/Java),
|
||||
- receiver type (Go),
|
||||
- return type (Java).
|
||||
|
||||
The term "physname" is a bit confusing.
|
||||
For C++, for example, it is the demangled name.
|
||||
For Go, for example, it's the mangled name.
|
||||
|
||||
For Ada, return the DIE's linkage name rather than the fully qualified
|
||||
name. PHYSNAME is ignored..
|
||||
|
@ -5353,10 +5436,21 @@ dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
|||
variant `long name(params)' does not have the proper inferior type.
|
||||
*/
|
||||
|
||||
demangled = cplus_demangle (mangled, (DMGL_PARAMS | DMGL_ANSI
|
||||
| (cu->language == language_java
|
||||
? DMGL_JAVA | DMGL_RET_POSTFIX
|
||||
: DMGL_RET_DROP)));
|
||||
if (cu->language == language_go)
|
||||
{
|
||||
/* This is a lie, but we already lie to the caller new_symbol_full.
|
||||
new_symbol_full assumes we return the mangled name.
|
||||
This just undoes that lie until things are cleaned up. */
|
||||
demangled = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
demangled = cplus_demangle (mangled,
|
||||
(DMGL_PARAMS | DMGL_ANSI
|
||||
| (cu->language == language_java
|
||||
? DMGL_JAVA | DMGL_RET_POSTFIX
|
||||
: DMGL_RET_DROP)));
|
||||
}
|
||||
if (demangled)
|
||||
{
|
||||
make_cleanup (xfree, demangled);
|
||||
|
@ -5684,6 +5778,10 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
|||
if (cu->producer && strstr (cu->producer, "IBM XL C for OpenCL") != NULL)
|
||||
cu->language = language_opencl;
|
||||
|
||||
/* Similar hack for Go. */
|
||||
if (cu->producer && strstr (cu->producer, "GNU Go ") != NULL)
|
||||
set_cu_language (DW_LANG_Go, cu);
|
||||
|
||||
/* We assume that we're processing GCC output. */
|
||||
processing_gcc_compilation = 2;
|
||||
|
||||
|
@ -10759,6 +10857,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
|
|||
case DW_LANG_Fortran95:
|
||||
cu->language = language_fortran;
|
||||
break;
|
||||
case DW_LANG_Go:
|
||||
cu->language = language_go;
|
||||
break;
|
||||
case DW_LANG_Mips_Assembler:
|
||||
cu->language = language_asm;
|
||||
break;
|
||||
|
|
1618
gdb/go-exp.y
Normal file
1618
gdb/go-exp.y
Normal file
File diff suppressed because it is too large
Load diff
667
gdb/go-lang.c
Normal file
667
gdb/go-lang.c
Normal file
|
@ -0,0 +1,667 @@
|
|||
/* Go language support routines for GDB, the GNU debugger.
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* TODO:
|
||||
- split stacks
|
||||
- printing of native types
|
||||
- goroutines
|
||||
- lots more
|
||||
- gccgo mangling needs redoing
|
||||
It's too hard, for example, to know whether one is looking at a mangled
|
||||
Go symbol or not, and their are ambiguities, e.g., the demangler may
|
||||
get passed *any* symbol, including symbols from other languages
|
||||
and including symbols that are already demangled.
|
||||
One thought is to at least add an _G prefix.
|
||||
- 6g mangling isn't supported yet
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdb_assert.h"
|
||||
#include "gdb_obstack.h"
|
||||
#include "gdb_string.h"
|
||||
#include "block.h"
|
||||
#include "symtab.h"
|
||||
#include "language.h"
|
||||
#include "go-lang.h"
|
||||
#include "c-lang.h"
|
||||
#include "parser-defs.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/* The main function in the main package. */
|
||||
static const char GO_MAIN_MAIN[] = "main.main";
|
||||
|
||||
/* Function returning the special symbol name used by Go for the main
|
||||
procedure in the main program if it is found in minimal symbol list.
|
||||
This function tries to find minimal symbols so that it finds them even
|
||||
if the program was compiled without debugging information. */
|
||||
|
||||
const char *
|
||||
go_main_name (void)
|
||||
{
|
||||
struct minimal_symbol *msym;
|
||||
|
||||
msym = lookup_minimal_symbol (GO_MAIN_MAIN, NULL, NULL);
|
||||
if (msym != NULL)
|
||||
return GO_MAIN_MAIN;
|
||||
|
||||
/* No known entry procedure found, the main program is probably not Go. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return non-zero if TYPE is a gccgo string.
|
||||
We assume CHECK_TYPEDEF has already been done. */
|
||||
|
||||
static int
|
||||
gccgo_string_p (struct type *type)
|
||||
{
|
||||
/* gccgo strings don't necessarily have a name we can use. */
|
||||
|
||||
if (TYPE_NFIELDS (type) == 2)
|
||||
{
|
||||
struct type *type0 = TYPE_FIELD_TYPE (type, 0);
|
||||
struct type *type1 = TYPE_FIELD_TYPE (type, 1);
|
||||
|
||||
CHECK_TYPEDEF (type0);
|
||||
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)
|
||||
{
|
||||
struct type *target_type = TYPE_TARGET_TYPE (type0);
|
||||
|
||||
CHECK_TYPEDEF (target_type);
|
||||
|
||||
if (TYPE_CODE (target_type) == TYPE_CODE_INT
|
||||
&& TYPE_LENGTH (target_type) == 1
|
||||
&& strcmp (TYPE_NAME (target_type), "uint8") == 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return non-zero if TYPE is a 6g string.
|
||||
We assume CHECK_TYPEDEF has already been done. */
|
||||
|
||||
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)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Classify the kind of Go object that TYPE is.
|
||||
TYPE is a TYPE_CODE_STRUCT, used to represent a Go object. */
|
||||
|
||||
enum go_type
|
||||
go_classify_struct_type (struct type *type)
|
||||
{
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
/* Recognize strings as they're useful to be able to print without
|
||||
pretty-printers. */
|
||||
if (gccgo_string_p (type)
|
||||
|| sixg_string_p (type))
|
||||
return GO_TYPE_STRING;
|
||||
|
||||
return GO_TYPE_NONE;
|
||||
}
|
||||
|
||||
/* Subroutine of unpack_mangled_go_symbol to simplify it.
|
||||
Given "[foo.]bar.baz", store "bar" in *PACKAGEP and "baz" in *OBJECTP.
|
||||
We stomp on the last '.' to nul-terminate "bar".
|
||||
The caller is responsible for memory management. */
|
||||
|
||||
static void
|
||||
unpack_package_and_object (char *buf,
|
||||
const char **packagep, const char **objectp)
|
||||
{
|
||||
char *last_dot;
|
||||
|
||||
last_dot = strrchr (buf, '.');
|
||||
gdb_assert (last_dot != NULL);
|
||||
*objectp = last_dot + 1;
|
||||
*last_dot = '\0';
|
||||
last_dot = strrchr (buf, '.');
|
||||
if (last_dot != NULL)
|
||||
*packagep = last_dot + 1;
|
||||
else
|
||||
*packagep = buf;
|
||||
}
|
||||
|
||||
/* Given a mangled Go symbol, find its package name, object name, and
|
||||
method type (if present).
|
||||
E.g., for "libgo_net.textproto.String.N33_libgo_net.textproto.ProtocolError"
|
||||
*PACKAGEP = "textproto"
|
||||
*OBJECTP = "String"
|
||||
*METHOD_TYPE_PACKAGEP = "textproto"
|
||||
*METHOD_TYPE_OBJECTP = "ProtocolError"
|
||||
|
||||
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.
|
||||
|
||||
There may be value in returning the outer container,
|
||||
i.e., "net" in the above example, but for now it's not needed.
|
||||
Plus it's currently not straightforward to compute,
|
||||
it comes from -fgo-prefix, and there's no algorithm to compute it.
|
||||
|
||||
If we ever need to unpack the method type, this routine should work
|
||||
for that too. */
|
||||
|
||||
static char *
|
||||
unpack_mangled_go_symbol (const char *mangled_name,
|
||||
const char **packagep,
|
||||
const char **objectp,
|
||||
const char **method_type_packagep,
|
||||
const char **method_type_objectp,
|
||||
int *method_type_is_pointerp)
|
||||
{
|
||||
char *buf;
|
||||
char *p;
|
||||
int len = strlen (mangled_name);
|
||||
/* Pointer to last digit in "N<digit(s)>_". */
|
||||
char *saw_digit;
|
||||
/* Pointer to "N" if valid "N<digit(s)>_" found. */
|
||||
char *method_type;
|
||||
/* Pointer to the first '.'. */
|
||||
char *first_dot;
|
||||
/* Pointer to the last '.'. */
|
||||
char *last_dot;
|
||||
/* Non-zero if we saw a pointer indicator. */
|
||||
int saw_pointer;
|
||||
|
||||
*packagep = *objectp = NULL;
|
||||
*method_type_packagep = *method_type_objectp = NULL;
|
||||
*method_type_is_pointerp = 0;
|
||||
|
||||
/* main.init is mangled specially. */
|
||||
if (strcmp (mangled_name, "__go_init_main") == 0)
|
||||
{
|
||||
char *package = xstrdup ("main");
|
||||
|
||||
*packagep = package;
|
||||
*objectp = "init";
|
||||
return package;
|
||||
}
|
||||
|
||||
/* main.main is mangled specially (missing prefix). */
|
||||
if (strcmp (mangled_name, "main.main") == 0)
|
||||
{
|
||||
char *package = xstrdup ("main");
|
||||
|
||||
*packagep = package;
|
||||
*objectp = "main";
|
||||
return package;
|
||||
}
|
||||
|
||||
/* We may get passed, e.g., "main.T.Foo", which is *not* mangled.
|
||||
Alas it looks exactly like "prefix.package.object."
|
||||
To cope for now we only recognize the following prefixes:
|
||||
|
||||
go: the default
|
||||
libgo_.*: used by gccgo's runtime
|
||||
|
||||
Thus we don't support -fgo-prefix (except as used by the runtime). */
|
||||
if (strncmp (mangled_name, "go.", 3) != 0
|
||||
&& strncmp (mangled_name, "libgo_", 6) != 0)
|
||||
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 (first_dot == NULL)
|
||||
return NULL;
|
||||
/* Treat "foo.bar" as unmangled. It can collide with lots of other
|
||||
languages and it's not clear what the consequences are.
|
||||
And except for main.main, all gccgo symbols are at least
|
||||
prefix.package.object. */
|
||||
last_dot = strrchr (mangled_name, '.');
|
||||
if (last_dot == first_dot)
|
||||
return NULL;
|
||||
|
||||
/* More quick checks. */
|
||||
if (last_dot[1] == '\0' /* foo. */
|
||||
|| last_dot[-1] == '.') /* foo..bar */
|
||||
return NULL;
|
||||
|
||||
/* At this point we've decided we have a mangled Go symbol. */
|
||||
|
||||
buf = xstrdup (mangled_name);
|
||||
|
||||
/* Search backwards looking for "N<digit(s)>". */
|
||||
p = buf + len;
|
||||
saw_digit = method_type = NULL;
|
||||
saw_pointer = 0;
|
||||
while (p > buf)
|
||||
{
|
||||
int current = *(const unsigned char *) --p;
|
||||
int current_is_digit = isdigit (current);
|
||||
|
||||
if (saw_digit)
|
||||
{
|
||||
if (current_is_digit)
|
||||
continue;
|
||||
if (current == 'N'
|
||||
&& ((p > buf && p[-1] == '.')
|
||||
|| (p > buf + 1 && p[-1] == 'p' && p[-2] == '.')))
|
||||
{
|
||||
if (atoi (p + 1) == strlen (saw_digit + 2))
|
||||
{
|
||||
if (p[-1] == '.')
|
||||
method_type = p - 1;
|
||||
else
|
||||
{
|
||||
gdb_assert (p[-1] == 'p');
|
||||
saw_pointer = 1;
|
||||
method_type = p - 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Not what we're looking for, reset and keep looking. */
|
||||
saw_digit = NULL;
|
||||
saw_pointer = 0;
|
||||
continue;
|
||||
}
|
||||
if (current_is_digit && p[1] == '_')
|
||||
{
|
||||
/* Possible start of method "this" [sic] type. */
|
||||
saw_digit = p;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (method_type != NULL
|
||||
/* Ensure not something like "..foo". */
|
||||
&& (method_type > buf && method_type[-1] != '.'))
|
||||
{
|
||||
unpack_package_and_object (saw_digit + 2,
|
||||
method_type_packagep, method_type_objectp);
|
||||
*method_type = '\0';
|
||||
*method_type_is_pointerp = saw_pointer;
|
||||
}
|
||||
|
||||
unpack_package_and_object (buf, packagep, objectp);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Implements the la_demangle language_defn routine for language Go.
|
||||
|
||||
N.B. This may get passed *any* symbol, including symbols from other
|
||||
languages and including symbols that are already demangled.
|
||||
Both of these situations are kinda unfortunate, but that's how things
|
||||
are today.
|
||||
|
||||
N.B. This currently only supports gccgo's mangling.
|
||||
|
||||
N.B. gccgo's mangling needs, I think, changing.
|
||||
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)
|
||||
{
|
||||
struct obstack tempbuf;
|
||||
char *result;
|
||||
char *name_buf;
|
||||
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;
|
||||
|
||||
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);
|
||||
if (name_buf == NULL)
|
||||
return NULL;
|
||||
|
||||
obstack_init (&tempbuf);
|
||||
|
||||
/* Print methods as they appear in "method expressions". */
|
||||
if (method_type_package_name != NULL)
|
||||
{
|
||||
/* FIXME: Seems like we should include package_name here somewhere. */
|
||||
if (method_type_is_pointer)
|
||||
obstack_grow_str (&tempbuf, "(*");
|
||||
obstack_grow_str (&tempbuf, method_type_package_name);
|
||||
obstack_grow_str (&tempbuf, ".");
|
||||
obstack_grow_str (&tempbuf, method_type_object_name);
|
||||
if (method_type_is_pointer)
|
||||
obstack_grow_str (&tempbuf, ")");
|
||||
obstack_grow_str (&tempbuf, ".");
|
||||
obstack_grow_str (&tempbuf, object_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
obstack_grow_str (&tempbuf, package_name);
|
||||
obstack_grow_str (&tempbuf, ".");
|
||||
obstack_grow_str (&tempbuf, object_name);
|
||||
}
|
||||
obstack_grow_str0 (&tempbuf, "");
|
||||
|
||||
result = xstrdup (obstack_finish (&tempbuf));
|
||||
obstack_free (&tempbuf, NULL);
|
||||
xfree (name_buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Given a Go symbol, return its package or NULL if unknown.
|
||||
Space for the result is malloc'd, caller must free. */
|
||||
|
||||
char *
|
||||
go_symbol_package_name (const struct symbol *sym)
|
||||
{
|
||||
const char *mangled_name = SYMBOL_LINKAGE_NAME (sym);
|
||||
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_assert (SYMBOL_LANGUAGE (sym) == language_go);
|
||||
name_buf = unpack_mangled_go_symbol (mangled_name,
|
||||
&package_name, &object_name,
|
||||
&method_type_package_name,
|
||||
&method_type_object_name,
|
||||
&method_type_is_pointer);
|
||||
/* 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 the package that BLOCK is in, or NULL if there isn't one.
|
||||
Space for the result is malloc'd, caller must free. */
|
||||
|
||||
char *
|
||||
go_block_package_name (const struct block *block)
|
||||
{
|
||||
while (block != NULL)
|
||||
{
|
||||
struct symbol *function = BLOCK_FUNCTION (block);
|
||||
|
||||
if (function != NULL)
|
||||
{
|
||||
char *package_name = go_symbol_package_name (function);
|
||||
|
||||
if (package_name != NULL)
|
||||
return package_name;
|
||||
|
||||
/* Stop looking if we find a function without a package name.
|
||||
We're most likely outside of Go and thus the concept of the
|
||||
"current" package is gone. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
block = BLOCK_SUPERBLOCK (block);
|
||||
}
|
||||
|
||||
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, 0, 0, 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
|
||||
};
|
||||
|
||||
static void
|
||||
go_language_arch_info (struct gdbarch *gdbarch,
|
||||
struct language_arch_info *lai)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static const struct language_defn go_language_defn =
|
||||
{
|
||||
"go",
|
||||
language_go,
|
||||
range_check_off,
|
||||
type_check_off,
|
||||
case_sensitive_on,
|
||||
array_row_major,
|
||||
macro_expansion_no,
|
||||
&exp_descriptor_c,
|
||||
go_parse,
|
||||
go_error,
|
||||
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. */
|
||||
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_make_symbol_completion_list,
|
||||
go_language_arch_info,
|
||||
default_print_array_index,
|
||||
default_pass_by_reference,
|
||||
c_get_string,
|
||||
NULL,
|
||||
iterate_over_symbols,
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
static void *
|
||||
build_go_types (struct gdbarch *gdbarch)
|
||||
{
|
||||
struct builtin_go_type *builtin_go_type
|
||||
= GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_go_type);
|
||||
|
||||
builtin_go_type->builtin_void
|
||||
= arch_type (gdbarch, TYPE_CODE_VOID, 1, "void");
|
||||
builtin_go_type->builtin_char
|
||||
= arch_character_type (gdbarch, 8, 1, "char");
|
||||
builtin_go_type->builtin_bool
|
||||
= arch_boolean_type (gdbarch, 8, 0, "bool");
|
||||
builtin_go_type->builtin_int
|
||||
= arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch), 0, "int");
|
||||
builtin_go_type->builtin_uint
|
||||
= arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch), 1, "uint");
|
||||
builtin_go_type->builtin_uintptr
|
||||
= arch_integer_type (gdbarch, gdbarch_ptr_bit (gdbarch), 1, "uintptr");
|
||||
builtin_go_type->builtin_int8
|
||||
= arch_integer_type (gdbarch, 8, 0, "int8");
|
||||
builtin_go_type->builtin_int16
|
||||
= arch_integer_type (gdbarch, 16, 0, "int16");
|
||||
builtin_go_type->builtin_int32
|
||||
= arch_integer_type (gdbarch, 32, 0, "int32");
|
||||
builtin_go_type->builtin_int64
|
||||
= arch_integer_type (gdbarch, 64, 0, "int64");
|
||||
builtin_go_type->builtin_uint8
|
||||
= arch_integer_type (gdbarch, 8, 1, "uint8");
|
||||
builtin_go_type->builtin_uint16
|
||||
= arch_integer_type (gdbarch, 16, 1, "uint16");
|
||||
builtin_go_type->builtin_uint32
|
||||
= arch_integer_type (gdbarch, 32, 1, "uint32");
|
||||
builtin_go_type->builtin_uint64
|
||||
= arch_integer_type (gdbarch, 64, 1, "uint64");
|
||||
builtin_go_type->builtin_float32
|
||||
= arch_float_type (gdbarch, 32, "float32", NULL);
|
||||
builtin_go_type->builtin_float64
|
||||
= arch_float_type (gdbarch, 64, "float64", NULL);
|
||||
builtin_go_type->builtin_complex64
|
||||
= arch_complex_type (gdbarch, "complex64",
|
||||
builtin_go_type->builtin_float32);
|
||||
builtin_go_type->builtin_complex128
|
||||
= arch_complex_type (gdbarch, "complex128",
|
||||
builtin_go_type->builtin_float64);
|
||||
|
||||
return builtin_go_type;
|
||||
}
|
||||
|
||||
static struct gdbarch_data *go_type_data;
|
||||
|
||||
const struct builtin_go_type *
|
||||
builtin_go_type (struct gdbarch *gdbarch)
|
||||
{
|
||||
return gdbarch_data (gdbarch, go_type_data);
|
||||
}
|
||||
|
||||
extern initialize_file_ftype _initialize_go_language;
|
||||
|
||||
void
|
||||
_initialize_go_language (void)
|
||||
{
|
||||
go_type_data = gdbarch_data_register_post_init (build_go_types);
|
||||
|
||||
add_language (&go_language_defn);
|
||||
}
|
88
gdb/go-lang.h
Normal file
88
gdb/go-lang.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* Go language support definitions for GDB, the GNU debugger.
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if !defined (GO_LANG_H)
|
||||
#define GO_LANG_H 1
|
||||
|
||||
#include "gdbtypes.h"
|
||||
#include "symtab.h"
|
||||
#include "value.h"
|
||||
|
||||
struct builtin_go_type
|
||||
{
|
||||
struct type *builtin_void;
|
||||
struct type *builtin_char;
|
||||
struct type *builtin_bool;
|
||||
struct type *builtin_int;
|
||||
struct type *builtin_uint;
|
||||
struct type *builtin_uintptr;
|
||||
struct type *builtin_int8;
|
||||
struct type *builtin_int16;
|
||||
struct type *builtin_int32;
|
||||
struct type *builtin_int64;
|
||||
struct type *builtin_uint8;
|
||||
struct type *builtin_uint16;
|
||||
struct type *builtin_uint32;
|
||||
struct type *builtin_uint64;
|
||||
struct type *builtin_float32;
|
||||
struct type *builtin_float64;
|
||||
struct type *builtin_complex64;
|
||||
struct type *builtin_complex128;
|
||||
};
|
||||
|
||||
enum go_type
|
||||
{
|
||||
GO_TYPE_NONE, /* Not a Go object. */
|
||||
GO_TYPE_STRING
|
||||
};
|
||||
|
||||
/* Defined in go-exp.y. */
|
||||
|
||||
extern int go_parse (void);
|
||||
|
||||
extern void go_error (char *);
|
||||
|
||||
/* Defined in go-lang.c. */
|
||||
|
||||
extern const char *go_main_name (void);
|
||||
|
||||
extern enum go_type go_classify_struct_type (struct type *type);
|
||||
|
||||
extern char *go_demangle (const char *mangled, int options);
|
||||
|
||||
extern char *go_symbol_package_name (const struct symbol *sym);
|
||||
|
||||
extern char *go_block_package_name (const struct block *block);
|
||||
|
||||
extern const struct builtin_go_type *builtin_go_type (struct gdbarch *);
|
||||
|
||||
/* Defined in go-typeprint.c. */
|
||||
|
||||
extern void go_print_type (struct type *type, const char *varstring,
|
||||
struct ui_file *stream, int show, int level);
|
||||
|
||||
/* Defined in go-valprint.c. */
|
||||
|
||||
extern void go_val_print (struct type *type, const gdb_byte *valaddr,
|
||||
int embedded_offset, CORE_ADDR address,
|
||||
struct ui_file *stream, int recurse,
|
||||
const struct value *val,
|
||||
const struct value_print_options *options);
|
||||
|
||||
#endif /* !defined (GO_LANG_H) */
|
62
gdb/go-typeprint.c
Normal file
62
gdb/go-typeprint.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* Support for printing Go types for GDB, the GNU debugger.
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* TODO:
|
||||
- lots
|
||||
- if the more complex types get Python pretty-printers, we'll
|
||||
want a Python API for type printing
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "c-lang.h"
|
||||
#include "go-lang.h"
|
||||
|
||||
/* Print a description of a type TYPE.
|
||||
Output goes to STREAM (via stdio).
|
||||
If VARSTRING is a non-empty string, print as an Ada variable/field
|
||||
declaration.
|
||||
SHOW+1 is the maximum number of levels of internal type structure
|
||||
to show (this applies to record types, enumerated types, and
|
||||
array types).
|
||||
SHOW is the number of levels of internal type structure to show
|
||||
when there is a type name for the SHOWth deepest level (0th is
|
||||
outer level).
|
||||
When SHOW<0, no inner structure is shown.
|
||||
LEVEL indicates level of recursion (for nested definitions). */
|
||||
|
||||
void
|
||||
go_print_type (struct type *type, const char *varstring,
|
||||
struct ui_file *stream, int show, int level)
|
||||
{
|
||||
/* Borrowed from c-typeprint.c. */
|
||||
if (show > 0)
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
/* Print the type of "abc" as "string", not char[4]. */
|
||||
if (TYPE_CODE (type) == TYPE_CODE_ARRAY
|
||||
&& TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CHAR)
|
||||
{
|
||||
fputs_filtered ("string", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Punt the rest to C for now. */
|
||||
c_print_type (type, varstring, stream, show, level);
|
||||
}
|
120
gdb/go-valprint.c
Normal file
120
gdb/go-valprint.c
Normal file
|
@ -0,0 +1,120 @@
|
|||
/* Support for printing Go values for GDB, the GNU debugger.
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
NOTE: This currently only provides special support for printing gccgo
|
||||
strings. 6g objects are handled in Python.
|
||||
The remaining gccgo types may also be handled in Python.
|
||||
Strings are handled specially here, at least for now, in case the Python
|
||||
support is unavailable. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "gdbcore.h"
|
||||
#include "go-lang.h"
|
||||
#include "c-lang.h"
|
||||
#include "valprint.h"
|
||||
|
||||
/* Print a Go string.
|
||||
|
||||
Note: We assume
|
||||
gdb_assert (go_classify_struct_type (type) == GO_TYPE_STRING). */
|
||||
|
||||
static void
|
||||
print_go_string (struct type *type, const gdb_byte *valaddr,
|
||||
int embedded_offset, CORE_ADDR address,
|
||||
struct ui_file *stream, int recurse,
|
||||
const struct value *val,
|
||||
const struct value_print_options *options)
|
||||
{
|
||||
struct gdbarch *gdbarch = get_type_arch (type);
|
||||
struct type *elt_ptr_type = TYPE_FIELD_TYPE (type, 0);
|
||||
struct type *elt_type = TYPE_TARGET_TYPE (elt_ptr_type);
|
||||
LONGEST length;
|
||||
/* TODO(dje): The encapsulation of what a pointer is belongs in value.c.
|
||||
I.e. If there's going to be unpack_pointer, there should be
|
||||
unpack_value_field_as_pointer. Do this until we can get
|
||||
unpack_value_field_as_pointer. */
|
||||
LONGEST addr;
|
||||
|
||||
gdb_assert (valaddr == value_contents_for_printing_const (val));
|
||||
|
||||
if (! unpack_value_field_as_long (type, valaddr, embedded_offset, 0,
|
||||
val, &addr))
|
||||
error (_("Unable to read string address"));
|
||||
|
||||
if (! unpack_value_field_as_long (type, valaddr, embedded_offset, 1,
|
||||
val, &length))
|
||||
error (_("Unable to read string length"));
|
||||
|
||||
/* TODO(dje): Print address of struct or actual string? */
|
||||
if (options->addressprint)
|
||||
fputs_filtered (paddress (gdbarch, addr), stream);
|
||||
|
||||
if (length < 0)
|
||||
{
|
||||
fputs_filtered (_("<invalid length: "), stream);
|
||||
fputs_filtered (plongest (addr), stream);
|
||||
fputs_filtered (">", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO(dje): Perhaps we should pass "UTF8" for ENCODING.
|
||||
The target encoding is a global switch.
|
||||
Either choice is problematic. */
|
||||
val_print_string (elt_type, NULL, addr, length, stream, options);
|
||||
}
|
||||
|
||||
/* Implements the la_val_print routine for language Go. */
|
||||
|
||||
void
|
||||
go_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
|
||||
CORE_ADDR address, struct ui_file *stream, int recurse,
|
||||
const struct value *val,
|
||||
const struct value_print_options *options)
|
||||
{
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_STRUCT:
|
||||
{
|
||||
enum go_type go_type = go_classify_struct_type (type);
|
||||
|
||||
switch (go_type)
|
||||
{
|
||||
case GO_TYPE_STRING:
|
||||
if (! options->raw)
|
||||
{
|
||||
print_go_string (type, valaddr, embedded_offset, address,
|
||||
stream, recurse, val, options);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Fall through. */
|
||||
|
||||
default:
|
||||
c_val_print (type, valaddr, embedded_offset, address, stream,
|
||||
recurse, val, options);
|
||||
break;
|
||||
}
|
||||
}
|
44
gdb/symtab.c
44
gdb/symtab.c
|
@ -39,6 +39,7 @@
|
|||
#include "objc-lang.h"
|
||||
#include "d-lang.h"
|
||||
#include "ada-lang.h"
|
||||
#include "go-lang.h"
|
||||
#include "p-lang.h"
|
||||
#include "addrmap.h"
|
||||
|
||||
|
@ -500,6 +501,7 @@ symbol_set_language (struct general_symbol_info *gsymbol,
|
|||
{
|
||||
gsymbol->language = language;
|
||||
if (gsymbol->language == language_d
|
||||
|| gsymbol->language == language_go
|
||||
|| gsymbol->language == language_java
|
||||
|| gsymbol->language == language_objc
|
||||
|| gsymbol->language == language_fortran)
|
||||
|
@ -620,6 +622,22 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
|
|||
return demangled;
|
||||
}
|
||||
}
|
||||
/* FIXME(dje): Continually adding languages here is clumsy.
|
||||
Better to just call la_demangle if !auto, and if auto then call
|
||||
a utility routine that tries successive languages in turn and reports
|
||||
which one it finds. I realize the la_demangle options may be different
|
||||
for different languages but there's already a FIXME for that. */
|
||||
if (gsymbol->language == language_go
|
||||
|| gsymbol->language == language_auto)
|
||||
{
|
||||
demangled = go_demangle (mangled, 0);
|
||||
if (demangled != NULL)
|
||||
{
|
||||
gsymbol->language = language_go;
|
||||
return demangled;
|
||||
}
|
||||
}
|
||||
|
||||
/* We could support `gsymbol->language == language_fortran' here to provide
|
||||
module namespaces also for inferiors with only minimal symbol table (ELF
|
||||
symbols). Just the mangling standard is not standardized across compilers
|
||||
|
@ -742,7 +760,11 @@ symbol_set_names (struct general_symbol_info *gsymbol,
|
|||
&entry, INSERT));
|
||||
|
||||
/* If this name is not in the hash table, add it. */
|
||||
if (*slot == NULL)
|
||||
if (*slot == NULL
|
||||
/* A C version of the symbol may have already snuck into the table.
|
||||
This happens to, e.g., main.init (__go_init_main). Cope. */
|
||||
|| (gsymbol->language == language_go
|
||||
&& (*slot)->demangled[0] == '\0'))
|
||||
{
|
||||
char *demangled_name = symbol_find_demangled_name (gsymbol,
|
||||
linkage_name_copy);
|
||||
|
@ -804,6 +826,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
|
|||
{
|
||||
case language_cplus:
|
||||
case language_d:
|
||||
case language_go:
|
||||
case language_java:
|
||||
case language_objc:
|
||||
case language_fortran:
|
||||
|
@ -832,6 +855,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
|
|||
{
|
||||
case language_cplus:
|
||||
case language_d:
|
||||
case language_go:
|
||||
case language_java:
|
||||
case language_objc:
|
||||
case language_fortran:
|
||||
|
@ -1123,7 +1147,7 @@ demangle_for_lookup (const char *name, enum language lang,
|
|||
|
||||
modified_name = name;
|
||||
|
||||
/* If we are using C++, D, or Java, demangle the name before doing a
|
||||
/* If we are using C++, D, Go, or Java, demangle the name before doing a
|
||||
lookup, so we can always binary search. */
|
||||
if (lang == language_cplus)
|
||||
{
|
||||
|
@ -1164,6 +1188,15 @@ demangle_for_lookup (const char *name, enum language lang,
|
|||
make_cleanup (xfree, demangled_name);
|
||||
}
|
||||
}
|
||||
else if (lang == language_go)
|
||||
{
|
||||
demangled_name = go_demangle (name, 0);
|
||||
if (demangled_name)
|
||||
{
|
||||
modified_name = demangled_name;
|
||||
make_cleanup (xfree, demangled_name);
|
||||
}
|
||||
}
|
||||
|
||||
*result_name = modified_name;
|
||||
return cleanup;
|
||||
|
@ -4802,6 +4835,13 @@ find_main_name (void)
|
|||
return;
|
||||
}
|
||||
|
||||
new_main_name = go_main_name ();
|
||||
if (new_main_name != NULL)
|
||||
{
|
||||
set_main_name (new_main_name);
|
||||
return;
|
||||
}
|
||||
|
||||
new_main_name = pascal_main_name ();
|
||||
if (new_main_name != NULL)
|
||||
{
|
||||
|
|
|
@ -1,3 +1,36 @@
|
|||
2012-04-25 Doug Evans <dje@google.com>
|
||||
|
||||
* configure.ac: Create gdb.go/Makefile.
|
||||
* configure: Regenerate.
|
||||
* gdb.base/default.exp: Add "go" to "set language" testing.
|
||||
* gdb.go/Makefile.in: New file.
|
||||
* gdb.go/basic-types.exp: New file.
|
||||
* gdb.go/chan.exp: New file.
|
||||
* gdb.go/chan.go: New file.
|
||||
* gdb.go/handcall.exp: New file.
|
||||
* gdb.go/handcall.go: New file.
|
||||
* gdb.go/hello.exp: New file.
|
||||
* gdb.go/hello.go: New file.
|
||||
* gdb.go/integers.exp: New file.
|
||||
* gdb.go/integers.go: New file.
|
||||
* gdb.go/methods.exp: New file.
|
||||
* gdb.go/methods.go: New file.
|
||||
* gdb.go/package.exp: New file.
|
||||
* gdb.go/package1.go: New file.
|
||||
* gdb.go/package2.go: New file.
|
||||
* gdb.go/print.exp: New file.
|
||||
* gdb.go/strings.exp: New file.
|
||||
* gdb.go/strings.go: New file.
|
||||
* gdb.go/types.exp: New file.
|
||||
* gdb.go/types.go: New file.
|
||||
* gdb.go/unsafe.exp: New file.
|
||||
* gdb.go/unsafe.go: New file.
|
||||
* lib/future.exp: Add Go support.
|
||||
(gdb_find_go, gdb_find_go_linker): New procs.
|
||||
(gdb_default_target_compile): Add Go support.
|
||||
* lib/gdb.exp (skip_go_tests): New proc.
|
||||
* lib/go.exp: New file.
|
||||
|
||||
2012-04-25 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.threads/linux-dp.exp: Unset 'seen' before 'array set'.
|
||||
|
|
3
gdb/testsuite/configure
vendored
3
gdb/testsuite/configure
vendored
|
@ -3448,7 +3448,7 @@ done
|
|||
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
|
@ -4158,6 +4158,7 @@ do
|
|||
"gdb.disasm/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.disasm/Makefile" ;;
|
||||
"gdb.dwarf2/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.dwarf2/Makefile" ;;
|
||||
"gdb.fortran/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.fortran/Makefile" ;;
|
||||
"gdb.go/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.go/Makefile" ;;
|
||||
"gdb.server/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.server/Makefile" ;;
|
||||
"gdb.java/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.java/Makefile" ;;
|
||||
"gdb.hp/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/Makefile" ;;
|
||||
|
|
|
@ -91,7 +91,7 @@ AC_OUTPUT([Makefile \
|
|||
gdb.ada/Makefile \
|
||||
gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile \
|
||||
gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile \
|
||||
gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile \
|
||||
gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile \
|
||||
gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile \
|
||||
gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile \
|
||||
gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile \
|
||||
|
|
|
@ -528,7 +528,7 @@ gdb_test "set history size" "Argument required .integer to set it to.*" "set his
|
|||
#test set history
|
||||
gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand.(\[^\r\n\]*\[\r\n\])+List of set history subcommands:(\[^\r\n\]*\[\r\n\])+set history expansion -- Set history expansion on command input(\[^\r\n\]*\[\r\n\])+set history filename -- Set the filename in which to record the command history(\[^\r\n\]*\[\r\n\])+set history save -- Set saving of the history record on exit(\[^\r\n\]*\[\r\n\])+set history size -- Set the size of the command history(\[^\r\n\]*\[\r\n\])+Type \"help set history\" followed by set history subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set history"
|
||||
#test set language
|
||||
gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, java, modula-2, opencl, pascal." "set language"
|
||||
gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, go, java, modula-2, opencl, pascal." "set language"
|
||||
#test set listsize
|
||||
gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
|
||||
#test set print "p" abbreviation
|
||||
|
|
20
gdb/testsuite/gdb.go/Makefile.in
Normal file
20
gdb/testsuite/gdb.go/Makefile.in
Normal file
|
@ -0,0 +1,20 @@
|
|||
VPATH = @srcdir@
|
||||
srcdir = @srcdir@
|
||||
|
||||
EXECUTABLES = \
|
||||
chan handcall hello integers methods package \
|
||||
strings types unsafe
|
||||
|
||||
all info install-info dvi install uninstall installcheck check:
|
||||
@echo "Nothing to be done for $@..."
|
||||
|
||||
clean mostlyclean:
|
||||
-find . -name '*.o' -print | xargs rm -f
|
||||
-find . -name '*.ali' -print | xargs rm -f
|
||||
-rm -f *~ a.out
|
||||
-rm -f core core.coremaker coremaker.core corefile $(EXECUTABLES)
|
||||
|
||||
distclean maintainer-clean realclean: clean
|
||||
-rm -f Makefile config.status config.log
|
||||
-rm -f *-init.exp gdb.log gdb.sum
|
||||
-rm -fr *.log summary detail *.plog *.sum *.psum site.*
|
118
gdb/testsuite/gdb.go/basic-types.exp
Normal file
118
gdb/testsuite/gdb.go/basic-types.exp
Normal file
|
@ -0,0 +1,118 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test basic builtin types.
|
||||
# NOTE: The tests here intentionally do not require a go compiler.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
proc test_integer_literal_types_accepted {} {
|
||||
# Test various decimal values.
|
||||
|
||||
gdb_test "pt 123" "type = int"
|
||||
|
||||
gdb_test "pt void(42)" "type = void"
|
||||
gdb_test "pt byte(42)" "type = uint8"
|
||||
gdb_test "pt int(42)" "type = int"
|
||||
gdb_test "pt uint(42)" "type = uint"
|
||||
gdb_test "pt uintptr(42)" "type = uintptr"
|
||||
|
||||
gdb_test "pt int8(42)" "type = int8"
|
||||
gdb_test "pt int16(42)" "type = int16"
|
||||
gdb_test "pt int32(42)" "type = int32"
|
||||
gdb_test "pt int64(42)" "type = int64"
|
||||
|
||||
gdb_test "pt uint8(42)" "type = uint8"
|
||||
gdb_test "pt uint16(42)" "type = uint16"
|
||||
gdb_test "pt uint32(42)" "type = uint32"
|
||||
gdb_test "pt uint64(42)" "type = uint64"
|
||||
}
|
||||
|
||||
proc test_logical_literal_types_accepted {} {
|
||||
# Test the only possible values for a logical, TRUE and FALSE.
|
||||
|
||||
gdb_test "pt true" "type = bool"
|
||||
gdb_test "pt false" "type = bool"
|
||||
|
||||
gdb_test "pt bool(0)" "type = bool"
|
||||
gdb_test "pt bool(1)" "type = bool"
|
||||
}
|
||||
|
||||
proc test_character_literal_types_accepted {} {
|
||||
# Test various character values.
|
||||
|
||||
gdb_test "pt 'a'" "type = char"
|
||||
|
||||
# FIXME: Need more.
|
||||
}
|
||||
|
||||
proc test_string_literal_types_accepted {} {
|
||||
# Test various string values.
|
||||
|
||||
gdb_test "pt \"a simple string\"" "type = string"
|
||||
gdb_test "pt `a simple raw string`" "type = string"
|
||||
|
||||
# FIXME: Need more.
|
||||
}
|
||||
|
||||
proc test_float_literal_types_accepted {} {
|
||||
# Test various floating point formats.
|
||||
|
||||
gdb_test "pt .44" "type = float64"
|
||||
gdb_test "pt 44.0" "type = float64"
|
||||
gdb_test "pt 10e20" "type = float64"
|
||||
gdb_test "pt 10E20" "type = float64"
|
||||
|
||||
gdb_test "pt float32(.42)" "type = float32"
|
||||
|
||||
gdb_test "pt float64(.42)" "type = float64"
|
||||
}
|
||||
|
||||
proc test_complex_literal_types_accepted {} {
|
||||
# Test various complex formats.
|
||||
|
||||
gdb_test "pt complex64(.42)" "type = complex64"
|
||||
setup_xfail "*-*-*"
|
||||
gdb_test "pt complex64(.42i1.0)" "type = complex64"
|
||||
setup_xfail "*-*-*"
|
||||
gdb_test "pt complex64(i1.0)" "type = complex64"
|
||||
|
||||
gdb_test "pt complex128(.42)" "type = complex128"
|
||||
setup_xfail "*-*-*"
|
||||
gdb_test "pt complex128(.42i1.0)" "type = complex128"
|
||||
setup_xfail "*-*-*"
|
||||
gdb_test "pt complex128(i1.0)" "type = complex128"
|
||||
}
|
||||
|
||||
# Start with a fresh gdb.
|
||||
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_reinitialize_dir $srcdir/$subdir
|
||||
|
||||
if [set_lang_go] {
|
||||
test_integer_literal_types_accepted
|
||||
test_logical_literal_types_accepted
|
||||
test_character_literal_types_accepted
|
||||
test_string_literal_types_accepted
|
||||
test_float_literal_types_accepted
|
||||
test_complex_literal_types_accepted
|
||||
} else {
|
||||
warning "Go type tests suppressed."
|
||||
}
|
52
gdb/testsuite/gdb.go/chan.exp
Normal file
52
gdb/testsuite/gdb.go/chan.exp
Normal file
|
@ -0,0 +1,52 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Basic channel tests.
|
||||
# This is very much a work-in-progress.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
set testfile "chan"
|
||||
set srcfile ${testfile}.go
|
||||
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug go}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
|
||||
set bp_location2 [gdb_get_line_number "set breakpoint 2 here"]
|
||||
|
||||
if { [go_runto_main] < 0 } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_breakpoint ${srcfile}:${bp_location1}] } {
|
||||
pass "setting breakpoint 1"
|
||||
}
|
||||
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location1}.*" "Going to first breakpoint"
|
||||
|
||||
gdb_test_no_output "disable"
|
||||
|
||||
if { [gdb_breakpoint ${srcfile}:${bp_location2}] } {
|
||||
pass "setting breakpoint 2"
|
||||
}
|
||||
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location2}.*" "Going to second breakpoint"
|
20
gdb/testsuite/gdb.go/chan.go
Normal file
20
gdb/testsuite/gdb.go/chan.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func generate() chan int {
|
||||
ch := make(chan int)
|
||||
go func() {
|
||||
for i := 0; ; i++ {
|
||||
ch <- i // set breakpoint 1 here
|
||||
}
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
func main() {
|
||||
integers := generate()
|
||||
for i := 0; i < 100; i++ { // Print the first hundred integers.
|
||||
fmt.Println(<-integers) // set breakpoint 2 here
|
||||
}
|
||||
}
|
45
gdb/testsuite/gdb.go/handcall.exp
Normal file
45
gdb/testsuite/gdb.go/handcall.exp
Normal file
|
@ -0,0 +1,45 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test hand-calling go functions.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
set testfile "handcall"
|
||||
set srcfile ${testfile}.go
|
||||
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug go}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
|
||||
|
||||
if { [go_runto_main] < 0 } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_breakpoint ${srcfile}:${bp_location1}] } {
|
||||
pass "setting breakpoint 1"
|
||||
}
|
||||
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location1}.*" "Going to first breakpoint"
|
||||
|
||||
gdb_test "print add (1, 2)" " = 3"
|
||||
gdb_test "print main.add (1, 2)" " = 3"
|
15
gdb/testsuite/gdb.go/handcall.go
Normal file
15
gdb/testsuite/gdb.go/handcall.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package main
|
||||
|
||||
func add (a,b int) (int) {
|
||||
return a + b
|
||||
}
|
||||
|
||||
func sub (a,b int) (int) {
|
||||
return a - b
|
||||
}
|
||||
|
||||
var v_int int
|
||||
|
||||
func main () {
|
||||
v_int = 42 // set breakpoint 1 here
|
||||
}
|
60
gdb/testsuite/gdb.go/hello.exp
Normal file
60
gdb/testsuite/gdb.go/hello.exp
Normal file
|
@ -0,0 +1,60 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Basic tests.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
set testfile "hello"
|
||||
set srcfile ${testfile}.go
|
||||
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug go}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
|
||||
set bp_location2 [gdb_get_line_number "set breakpoint 2 here"]
|
||||
|
||||
if { [go_runto_main] < 0 } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_breakpoint ${srcfile}:${bp_location1}] } {
|
||||
pass "setting breakpoint 1"
|
||||
}
|
||||
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location1}.*" "Going to first breakpoint"
|
||||
|
||||
# This used to print "", i.e., the local "st" initialized as "".
|
||||
setup_xfail "*-*-*"
|
||||
|
||||
gdb_test "print st" \
|
||||
".* = $hex \"\"" \
|
||||
"Starting string check"
|
||||
|
||||
if { [gdb_breakpoint ${srcfile}:${bp_location2}] } {
|
||||
pass "setting breakpoint 2"
|
||||
}
|
||||
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location2}.*" "Going to second breakpoint"
|
||||
|
||||
gdb_test "print st" \
|
||||
".* = $hex \"Hello, world!\"" \
|
||||
"String after assignment check"
|
12
gdb/testsuite/gdb.go/hello.go
Normal file
12
gdb/testsuite/gdb.go/hello.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var myst = "Shall we?"
|
||||
|
||||
func main () {
|
||||
fmt.Println ("Before assignment") // set breakpoint 1 here
|
||||
st := "Hello, world!" // this intentionally shadows the global "st"
|
||||
fmt.Println (st) // set breakpoint 2 here
|
||||
fmt.Println (myst) // set breakpoint 2 here
|
||||
}
|
116
gdb/testsuite/gdb.go/integers.exp
Normal file
116
gdb/testsuite/gdb.go/integers.exp
Normal file
|
@ -0,0 +1,116 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test integer expressions.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
set testfile "integers"
|
||||
set srcfile ${testfile}.go
|
||||
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug go}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
|
||||
set bp_location2 [gdb_get_line_number "set breakpoint 2 here"]
|
||||
|
||||
if { [go_runto_main] < 0 } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_breakpoint ${srcfile}:${bp_location1}] } {
|
||||
pass "setting breakpoint 1"
|
||||
}
|
||||
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location1}.*" "Going to first breakpoint"
|
||||
|
||||
gdb_test "print i" ".* = 0" "Print i before assigned to 1"
|
||||
|
||||
gdb_test "next" "i = 1" "Next to 'i = 1' line"
|
||||
gdb_test "next" "j = 2" "Next to 'j = 2' line"
|
||||
# At that point,
|
||||
# i should be equal to 1
|
||||
gdb_test "print i" " = 1"
|
||||
# but j should still be equal to zero
|
||||
gdb_test "print j" " = 0" "Test j value before assignment"
|
||||
|
||||
gdb_test "next" "k = 3" "Next to 'k = 3' line"
|
||||
gdb_test "next" "l = k" "Next to 'l = k' line"
|
||||
|
||||
#j should be equal to 2
|
||||
gdb_test "print j" " = 2"
|
||||
# k should be equal to 3
|
||||
gdb_test "print k" " = 3"
|
||||
# But l should still be zero
|
||||
gdb_test "print l" " = 0"
|
||||
|
||||
# Test addition
|
||||
gdb_test "print i + j" " = 3"
|
||||
gdb_test "print i + k" " = 4"
|
||||
gdb_test "print j + k" " = 5"
|
||||
gdb_test "print i + j + k" " = 6"
|
||||
|
||||
# Test substraction
|
||||
gdb_test "print j - i" " = 1"
|
||||
gdb_test "print i - j" "= -1"
|
||||
gdb_test "print k -i -j" " = 0"
|
||||
gdb_test "print k -(i + j)" " = 0"
|
||||
|
||||
# Test unany minus
|
||||
gdb_test "print -i" " = -1"
|
||||
gdb_test "print (-i)" " = -1"
|
||||
gdb_test "print -(i)" " = -1"
|
||||
gdb_test "print -(i+j)" " = -3"
|
||||
|
||||
# Test boolean operators =, <>, <, <=, > and >=
|
||||
gdb_test "print i + 1 == j" " = true"
|
||||
gdb_test "print i + 1 != j" " = false"
|
||||
gdb_test "print i + 1 < j" " = false"
|
||||
gdb_test "print i + 1 <= j" " = true"
|
||||
gdb_test "print i + 1 > j" " = false"
|
||||
gdb_test "print i + 1 >= j" " = true"
|
||||
|
||||
# Test multiplication
|
||||
gdb_test "print 2 * i" " = 2"
|
||||
gdb_test "print j * k" " = 6"
|
||||
gdb_test "print 3000*i" " = 3000"
|
||||
|
||||
#Test div and mod operators
|
||||
gdb_test "print 35 / 2" " = 17"
|
||||
gdb_test "print 35 % 2" " = 1"
|
||||
|
||||
# Test several operators together
|
||||
gdb_test "print i+10*j+100*k" " = 321"
|
||||
gdb_test " print (i + 5) * (j + 7)" " = 54"
|
||||
|
||||
gdb_test "set var i = 2" " = 2"
|
||||
gdb_test "print i" " = 2" "Testing new i value"
|
||||
|
||||
if { [gdb_breakpoint ${srcfile}:${bp_location2}] } {
|
||||
pass "setting breakpoint 2"
|
||||
}
|
||||
|
||||
gdb_test "cont" \
|
||||
"Breakpoint .*:${bp_location2}.*" \
|
||||
"Going to second breakpoint"
|
||||
gdb_test "print i" \
|
||||
".* = 5.*" \
|
||||
"Value of i after assignment"
|
22
gdb/testsuite/gdb.go/integers.go
Normal file
22
gdb/testsuite/gdb.go/integers.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package main
|
||||
|
||||
var i = 0
|
||||
var j = 0
|
||||
var k = 0
|
||||
var l = 0
|
||||
|
||||
func main () {
|
||||
i = 0
|
||||
j = 0
|
||||
k = 0
|
||||
l = 0 // set breakpoint 1 here
|
||||
i = 1
|
||||
j = 2
|
||||
k = 3
|
||||
l = k
|
||||
|
||||
i = j + k
|
||||
|
||||
j = 0 // set breakpoint 2 here
|
||||
k = 0
|
||||
}
|
50
gdb/testsuite/gdb.go/methods.exp
Normal file
50
gdb/testsuite/gdb.go/methods.exp
Normal file
|
@ -0,0 +1,50 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test various aspects of methods.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
set testfile "methods"
|
||||
set srcfile ${testfile}.go
|
||||
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug go}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
set bp_location1 {main.T.Foo}
|
||||
set bp_location2 {(*main.T).Bar}
|
||||
set bp_location2_regexp {\(*main.T\).Bar}
|
||||
|
||||
if { [go_runto_main] < 0 } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_breakpoint ${bp_location1}] } {
|
||||
pass "setting breakpoint 1"
|
||||
}
|
||||
setup_xfail "*-*-*" ;# mangling issues IIRC
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location1}.*" "Going to first breakpoint"
|
||||
|
||||
if { [gdb_breakpoint ${bp_location2}] } {
|
||||
pass "setting breakpoint 2"
|
||||
}
|
||||
setup_xfail "*-*-*" ;# mangling issues IIRC
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location2_regexp}.*" "Going to second breakpoint"
|
21
gdb/testsuite/gdb.go/methods.go
Normal file
21
gdb/testsuite/gdb.go/methods.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type T struct { i int }
|
||||
|
||||
func (t T) Foo () {
|
||||
fmt.Println (t.i)
|
||||
}
|
||||
|
||||
func (t *T) Bar () {
|
||||
fmt.Println (t.i)
|
||||
}
|
||||
|
||||
func main () {
|
||||
fmt.Println ("Shall we?")
|
||||
var t T
|
||||
t.Foo ()
|
||||
var pt = new (T)
|
||||
pt.Bar ()
|
||||
}
|
50
gdb/testsuite/gdb.go/package.exp
Normal file
50
gdb/testsuite/gdb.go/package.exp
Normal file
|
@ -0,0 +1,50 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test various aspects of packages.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
set testfile "package"
|
||||
set binfile ${objdir}/${subdir}/${testfile}
|
||||
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${testfile}2.go" "${binfile}2.o" object {debug go}] != "" } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_compile "${srcdir}/${subdir}/${testfile}1.go ${binfile}2.o" "${binfile}" executable "debug go libdir=${objdir}/${subdir}"] != "" } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
clean_restart $testfile
|
||||
|
||||
if { [go_runto_main] < 0 } {
|
||||
untested methods
|
||||
return -1
|
||||
}
|
||||
|
||||
set bp_location1 {package2.Foo}
|
||||
set bp_location1_regexp {package2[.]Foo.*package2[.]go:}
|
||||
|
||||
if { [gdb_breakpoint ${bp_location1}] } {
|
||||
pass "setting breakpoint 1"
|
||||
}
|
||||
gdb_test "cont" "Breakpoint .*${bp_location1_regexp}.*" "Going to first breakpoint"
|
11
gdb/testsuite/gdb.go/package1.go
Normal file
11
gdb/testsuite/gdb.go/package1.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"package2"
|
||||
)
|
||||
|
||||
func main () {
|
||||
fmt.Println ("Shall we?")
|
||||
package2.Foo ()
|
||||
}
|
7
gdb/testsuite/gdb.go/package2.go
Normal file
7
gdb/testsuite/gdb.go/package2.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package package2
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Foo () {
|
||||
fmt.Println ("Hi, I'm package2.Foo.")
|
||||
}
|
70
gdb/testsuite/gdb.go/print.exp
Normal file
70
gdb/testsuite/gdb.go/print.exp
Normal file
|
@ -0,0 +1,70 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test printing of various values.
|
||||
# NOTE: The tests here intentionally do not require a go compiler.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
proc test_float_accepted {} {
|
||||
global gdb_prompt
|
||||
|
||||
# Test parsing of fp value with legit text following.
|
||||
gdb_test "p 1234.5+1" " = 1235.5" "check fp + text"
|
||||
|
||||
# Test all the suffixes (including no suffix).
|
||||
gdb_test "p 1." " = 1"
|
||||
gdb_test "p 1.5" " = 1.5"
|
||||
gdb_test "p 1.f" " = 1"
|
||||
gdb_test "p 1.5f" " = 1.5"
|
||||
gdb_test "p 1.l" " = 1"
|
||||
gdb_test "p 1.5l" " = 1.5"
|
||||
|
||||
# Test hexadecimal floating point.
|
||||
set test "p 0x1.1"
|
||||
gdb_test_multiple $test $test {
|
||||
-re " = 1\\.0625\r\n$gdb_prompt $" {
|
||||
pass $test
|
||||
}
|
||||
-re "Invalid number \"0x1\\.1\"\\.\r\n$gdb_prompt $" {
|
||||
# Older glibc does not support hex float, newer does.
|
||||
xfail $test
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc test_float_rejected {} {
|
||||
# Test bad suffixes.
|
||||
test_print_reject "p 1.1x"
|
||||
test_print_reject "p 1.1ff"
|
||||
test_print_reject "p 1.1ll"
|
||||
}
|
||||
|
||||
# Start with a fresh gdb.
|
||||
|
||||
gdb_exit
|
||||
gdb_start
|
||||
gdb_reinitialize_dir $srcdir/$subdir
|
||||
|
||||
if [set_lang_go] {
|
||||
test_float_accepted
|
||||
test_float_rejected
|
||||
} else {
|
||||
warning "Go print tests suppressed"
|
||||
}
|
42
gdb/testsuite/gdb.go/strings.exp
Normal file
42
gdb/testsuite/gdb.go/strings.exp
Normal file
|
@ -0,0 +1,42 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
set testfile "strings"
|
||||
set srcfile ${testfile}.go
|
||||
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug go}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
|
||||
|
||||
if { [go_runto_main] < 0 } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_breakpoint ${srcfile}:${bp_location1}] } {
|
||||
pass "setting breakpoint 1"
|
||||
}
|
||||
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location1}.*" "Going to first breakpoint"
|
||||
|
||||
gdb_test {print "abc" + "def"} {.* = "abcdef"}
|
10
gdb/testsuite/gdb.go/strings.go
Normal file
10
gdb/testsuite/gdb.go/strings.go
Normal file
|
@ -0,0 +1,10 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var v_string string = "foo"
|
||||
|
||||
func main () {
|
||||
fmt.Println ("hello") // set breakpoint 1 here
|
||||
fmt.Printf ("%s\n", v_string)
|
||||
}
|
51
gdb/testsuite/gdb.go/types.exp
Normal file
51
gdb/testsuite/gdb.go/types.exp
Normal file
|
@ -0,0 +1,51 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Various experiments with types.
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
set testfile "types"
|
||||
set srcfile ${testfile}.go
|
||||
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug go}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [go_runto_main] < 0 } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
# It's not clear yet what GCC will emit.
|
||||
# Pick something and xfail it until GCC solidifies.
|
||||
# And we still need to finish go-typeprint.c.
|
||||
|
||||
setup_xfail "*-*-*"
|
||||
gdb_test "ptype T" "type T *T"
|
||||
|
||||
setup_xfail "*-*-*"
|
||||
gdb_test "ptype T1" "type T1 *T2"
|
||||
setup_xfail "*-*-*"
|
||||
gdb_test "ptype T2" "type T2 *T1"
|
||||
|
||||
setup_xfail "*-*-*"
|
||||
gdb_test "ptype S1" "type S1 struct {.*p_s2 *S2.*}"
|
||||
setup_xfail "*-*-*"
|
||||
gdb_test "ptype S2" "type S2 struct {.*p_s1 *S1.*}"
|
24
gdb/testsuite/gdb.go/types.go
Normal file
24
gdb/testsuite/gdb.go/types.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Self-referential type.
|
||||
type T *T
|
||||
|
||||
// Mutually recursive types.
|
||||
type T1 *T2
|
||||
type T2 *T1
|
||||
|
||||
// Mutually recursive struct types.
|
||||
type S1 struct { p_s2 *S2 }
|
||||
type S2 struct { p_s1 *S1 }
|
||||
|
||||
func main () {
|
||||
fmt.Println ("Shall we?")
|
||||
var t T
|
||||
fmt.Println (t)
|
||||
var s1 S1
|
||||
var s2 S2
|
||||
fmt.Println (s1)
|
||||
fmt.Println (s2)
|
||||
}
|
44
gdb/testsuite/gdb.go/unsafe.exp
Normal file
44
gdb/testsuite/gdb.go/unsafe.exp
Normal file
|
@ -0,0 +1,44 @@
|
|||
# This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Test package "unsafe".
|
||||
|
||||
load_lib "go.exp"
|
||||
|
||||
if { [skip_go_tests] } { continue }
|
||||
|
||||
set testfile "unsafe"
|
||||
set srcfile ${testfile}.go
|
||||
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug go}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
|
||||
|
||||
if { [go_runto_main] < 0 } {
|
||||
untested $testfile
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_breakpoint ${srcfile}:${bp_location1}] } {
|
||||
pass "setting breakpoint 1"
|
||||
}
|
||||
|
||||
gdb_test "cont" "Breakpoint .*:${bp_location1}.*" "Going to first breakpoint"
|
||||
|
||||
gdb_test "print unsafe.Sizeof(42)" ".* = 4"
|
11
gdb/testsuite/gdb.go/unsafe.go
Normal file
11
gdb/testsuite/gdb.go/unsafe.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
import ("fmt"
|
||||
"unsafe")
|
||||
|
||||
var mystring = "Shall we?"
|
||||
|
||||
func main () {
|
||||
fmt.Printf ("%d\n", unsafe.Sizeof (42)) // set breakpoint 1 here
|
||||
fmt.Printf ("%d\n", unsafe.Sizeof (mystring))
|
||||
}
|
|
@ -60,6 +60,30 @@ proc gdb_find_gfortran {} {
|
|||
return $CC
|
||||
}
|
||||
|
||||
proc gdb_find_go {} {
|
||||
global tool_root_dir
|
||||
|
||||
set GO ""
|
||||
|
||||
if {![is_remote host]} {
|
||||
set file [lookfor_file $tool_root_dir gccgo]
|
||||
if { $file != "" } {
|
||||
set root [file dirname $file]
|
||||
set GO "$file -B$root/gcc/"
|
||||
}
|
||||
}
|
||||
|
||||
if { $GO == "" } {
|
||||
set GO [transform gccgo]
|
||||
}
|
||||
|
||||
return $GO
|
||||
}
|
||||
|
||||
proc gdb_find_go_linker {} {
|
||||
return [find_go]
|
||||
}
|
||||
|
||||
proc gdb_default_target_compile {source destfile type options} {
|
||||
global target_triplet
|
||||
global tool_root_dir
|
||||
|
@ -74,6 +98,11 @@ proc gdb_default_target_compile {source destfile type options} {
|
|||
set libs ""
|
||||
set compiler_type "c"
|
||||
set compiler ""
|
||||
set linker ""
|
||||
# linker_opts_order is one of "sources-then-flags", "flags-then-sources".
|
||||
# The order shouldn't matter. It's done this way to preserve
|
||||
# existing behavior.
|
||||
set linker_opts_order "sources-then-flags"
|
||||
set ldflags ""
|
||||
set dest [target_info name]
|
||||
|
||||
|
@ -138,6 +167,26 @@ proc gdb_default_target_compile {source destfile type options} {
|
|||
}
|
||||
}
|
||||
|
||||
if { $i == "go" } {
|
||||
set compiler_type "go"
|
||||
if {[board_info $dest exists goflags]} {
|
||||
append add_flags " [target_info goflags]"
|
||||
}
|
||||
if {[board_info $dest exists gocompiler]} {
|
||||
set compiler [target_info gocompiler]
|
||||
} else {
|
||||
set compiler [find_go]
|
||||
}
|
||||
if {[board_info $dest exists golinker]} {
|
||||
set linker [target_info golinker]
|
||||
} else {
|
||||
set linker [find_go_linker]
|
||||
}
|
||||
if {[board_info $dest exists golinker_opts_order]} {
|
||||
set linker_opts_order [target_info golinker_opts_order]
|
||||
}
|
||||
}
|
||||
|
||||
if {[regexp "^dest=" $i]} {
|
||||
regsub "^dest=" $i "" tmp
|
||||
if {[board_info $tmp exists name]} {
|
||||
|
@ -193,6 +242,8 @@ proc gdb_default_target_compile {source destfile type options} {
|
|||
global F77_FOR_TARGET
|
||||
global F90_FOR_TARGET
|
||||
global GNATMAKE_FOR_TARGET
|
||||
global GO_FOR_TARGET
|
||||
global GO_LD_FOR_TARGET
|
||||
|
||||
if {[info exists GNATMAKE_FOR_TARGET]} {
|
||||
if { $compiler_type == "ada" } {
|
||||
|
@ -224,6 +275,19 @@ proc gdb_default_target_compile {source destfile type options} {
|
|||
}
|
||||
}
|
||||
|
||||
if { $compiler_type == "go" } {
|
||||
if {[info exists GO_FOR_TARGET]} {
|
||||
set compiler $GO_FOR_TARGET
|
||||
}
|
||||
if {[info exists GO_LD_FOR_TARGET]} {
|
||||
set linker $GO_LD_FOR_TARGET
|
||||
}
|
||||
}
|
||||
|
||||
if { $type == "executable" && $linker != "" } {
|
||||
set compiler $linker
|
||||
}
|
||||
|
||||
if { $compiler == "" } {
|
||||
set compiler [board_info $dest compiler]
|
||||
if { $compiler == "" } {
|
||||
|
@ -366,10 +430,26 @@ proc gdb_default_target_compile {source destfile type options} {
|
|||
# This is obscure: we put SOURCES at the end when building an
|
||||
# object, because otherwise, in some situations, libtool will
|
||||
# become confused about the name of the actual source file.
|
||||
if {$type == "object"} {
|
||||
set opts "$add_flags $sources"
|
||||
} else {
|
||||
set opts "$sources $add_flags"
|
||||
switch $type {
|
||||
"object" {
|
||||
set opts "$add_flags $sources"
|
||||
}
|
||||
"executable" {
|
||||
switch $linker_opts_order {
|
||||
"flags-then-sources" {
|
||||
set opts "$add_flags $sources"
|
||||
}
|
||||
"sources-then-flags" {
|
||||
set opts "$sources $add_flags"
|
||||
}
|
||||
default {
|
||||
error "Invalid value for board_info linker_opts_order"
|
||||
}
|
||||
}
|
||||
}
|
||||
default {
|
||||
set opts "$sources $add_flags"
|
||||
}
|
||||
}
|
||||
|
||||
if {[is_remote host]} {
|
||||
|
@ -431,6 +511,12 @@ if {[info procs find_gfortran] == ""} {
|
|||
set use_gdb_compile 1
|
||||
}
|
||||
|
||||
if {[info procs find_go_linker] == ""} {
|
||||
rename gdb_find_go find_go
|
||||
rename gdb_find_go_linker find_go_linker
|
||||
# No need to set use_gdb_compile.
|
||||
}
|
||||
|
||||
if {$use_gdb_compile} {
|
||||
catch {rename default_target_compile {}}
|
||||
rename gdb_default_target_compile default_target_compile
|
||||
|
|
|
@ -1440,6 +1440,12 @@ proc skip_ada_tests {} {
|
|||
return 0
|
||||
}
|
||||
|
||||
# Return a 1 if I don't even want to try to test GO.
|
||||
|
||||
proc skip_go_tests {} {
|
||||
return 0
|
||||
}
|
||||
|
||||
# Return a 1 if I don't even want to try to test java.
|
||||
|
||||
proc skip_java_tests {} {
|
||||
|
|
37
gdb/testsuite/lib/go.exp
Normal file
37
gdb/testsuite/lib/go.exp
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# FIXME: Presumably skip_go_tests should be defined here,
|
||||
# but for consistency with other languages it currently lives in gdb.exp.
|
||||
|
||||
# Auxiliary function to set the language to Go.
|
||||
# The result is 1 (true) for success, 0 (false) for failure.
|
||||
|
||||
proc set_lang_go {} {
|
||||
if [gdb_test_no_output "set language go"] {
|
||||
return 0
|
||||
}
|
||||
if [gdb_test "show language" ".* source language is \"go\"." \
|
||||
"set language to \"go\""] {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
# Go version of runto_main.
|
||||
|
||||
proc go_runto_main { } {
|
||||
return [runto main.main]
|
||||
}
|
Loading…
Reference in a new issue