X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fjv-lang.c;h=2e700e3a2b16e00bd1bf1ab7b19b499445ab9d19;hb=e0881a8e0fbb8bd5d4d14683390269b97e4e90d7;hp=b76796301ec930b10b3cc14498cd06dbbe3e09b6;hpb=f86f5ca3f51ad4cd6a84f094bc9ea7b0e97f132c;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index b76796301e..2e700e3a2b 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1,11 +1,13 @@
/* Java language support routines for GDB, the GNU debugger.
- Copyright 1997, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
+
+ Copyright (C) 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2007, 2008, 2009,
+ 2010 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 2 of the License, or
+ 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,
@@ -14,9 +16,7 @@
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, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see . */
#include "defs.h"
#include "symtab.h"
@@ -37,16 +37,7 @@
#include "demangle.h"
#include "dictionary.h"
#include
-
-struct type *java_int_type;
-struct type *java_byte_type;
-struct type *java_short_type;
-struct type *java_long_type;
-struct type *java_boolean_type;
-struct type *java_char_type;
-struct type *java_float_type;
-struct type *java_double_type;
-struct type *java_void_type;
+#include "gdb_assert.h"
/* Local functions */
@@ -55,13 +46,18 @@ extern void _initialize_java_language (void);
static int java_demangled_signature_length (char *);
static void java_demangled_signature_copy (char *, char *);
-static struct symtab *get_java_class_symtab (void);
+static struct symtab *get_java_class_symtab (struct gdbarch *gdbarch);
static char *get_java_utf8_name (struct obstack *obstack, struct value *name);
static int java_class_is_primitive (struct value *clas);
-static struct type *java_lookup_type (char *signature);
static struct value *java_value_string (char *ptr, int len);
-static void java_emit_char (int c, struct ui_file * stream, int quoter);
+static void java_emit_char (int c, struct type *type,
+ struct ui_file * stream, int quoter);
+
+static char *java_class_name_from_physname (const char *physname);
+
+static const struct objfile_data *jv_dynamics_objfile_data_key;
+static const struct objfile_data *jv_type_objfile_data_key;
/* This objfile contains symtabs that have been dynamically created
to record dynamically loaded Java classes and dynamically
@@ -69,7 +65,25 @@ static void java_emit_char (int c, struct ui_file * stream, int quoter);
static struct objfile *dynamics_objfile = NULL;
-static struct type *java_link_class_type (struct type *, struct value *);
+/* symtab contains classes read from the inferior. */
+
+static struct symtab *class_symtab = NULL;
+
+static struct type *java_link_class_type (struct gdbarch *,
+ struct type *, struct value *);
+
+/* A function called when the dynamics_objfile is freed. We use this
+ to clean up some internal state. */
+static void
+jv_per_objfile_free (struct objfile *objfile, void *ignore)
+{
+ gdb_assert (objfile == dynamics_objfile);
+ /* Clean up all our cached state. These objects are all allocated
+ in the dynamics_objfile, so we don't need to actually free
+ anything. */
+ dynamics_objfile = NULL;
+ class_symtab = NULL;
+}
/* FIXME: carlton/2003-02-04: This is the main or only caller of
allocate_objfile with first argument NULL; as a result, this code
@@ -78,55 +92,51 @@ static struct type *java_link_class_type (struct type *, struct value *);
dynamic library) after this code has been called. */
static struct objfile *
-get_dynamics_objfile (void)
+get_dynamics_objfile (struct gdbarch *gdbarch)
{
if (dynamics_objfile == NULL)
{
- dynamics_objfile = allocate_objfile (NULL, 0);
+ /* Mark it as shared so that it is cleared when the inferior is
+ re-run. */
+ dynamics_objfile = allocate_objfile (NULL, OBJF_SHARED);
+ dynamics_objfile->gdbarch = gdbarch;
+ /* We don't have any data to store, but this lets us get a
+ notification when the objfile is destroyed. Since we have to
+ store a non-NULL value, we just pick something arbitrary and
+ safe. */
+ set_objfile_data (dynamics_objfile, jv_dynamics_objfile_data_key,
+ &dynamics_objfile);
}
return dynamics_objfile;
}
-#if 1
-/* symtab contains classes read from the inferior. */
-
-static struct symtab *class_symtab = NULL;
-
static void free_class_block (struct symtab *symtab);
static struct symtab *
-get_java_class_symtab (void)
+get_java_class_symtab (struct gdbarch *gdbarch)
{
if (class_symtab == NULL)
{
- struct objfile *objfile = get_dynamics_objfile ();
+ struct objfile *objfile = get_dynamics_objfile (gdbarch);
struct blockvector *bv;
struct block *bl;
+
class_symtab = allocate_symtab ("", objfile);
class_symtab->language = language_java;
bv = (struct blockvector *)
- obstack_alloc (&objfile->symbol_obstack,
+ obstack_alloc (&objfile->objfile_obstack,
sizeof (struct blockvector) + sizeof (struct block *));
BLOCKVECTOR_NBLOCKS (bv) = 1;
BLOCKVECTOR (class_symtab) = bv;
/* Allocate dummy STATIC_BLOCK. */
- bl = (struct block *)
- obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
- BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack,
+ bl = allocate_block (&objfile->objfile_obstack);
+ BLOCK_DICT (bl) = dict_create_linear (&objfile->objfile_obstack,
NULL);
- BLOCK_START (bl) = 0;
- BLOCK_END (bl) = 0;
- BLOCK_FUNCTION (bl) = NULL;
- BLOCK_SUPERBLOCK (bl) = NULL;
- BLOCK_NAMESPACE (bl) = NULL;
- BLOCK_GCC_COMPILED (bl) = 0;
BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
- /* Allocate GLOBAL_BLOCK. This has to be relocatable. */
- bl = (struct block *)
- obstack_alloc (&objfile->symbol_obstack, sizeof (struct block));
- *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ /* Allocate GLOBAL_BLOCK. */
+ bl = allocate_block (&objfile->objfile_obstack);
BLOCK_DICT (bl) = dict_create_hashed_expandable ();
BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
class_symtab->free_func = free_class_block;
@@ -137,22 +147,23 @@ get_java_class_symtab (void)
static void
add_class_symtab_symbol (struct symbol *sym)
{
- struct symtab *symtab = get_java_class_symtab ();
+ struct symtab *symtab
+ = get_java_class_symtab (get_objfile_arch (SYMBOL_SYMTAB (sym)->objfile));
struct blockvector *bv = BLOCKVECTOR (symtab);
+
dict_add_symbol (BLOCK_DICT (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)), sym);
}
-static struct symbol *add_class_symbol (struct type *type, CORE_ADDR addr);
-
static struct symbol *
add_class_symbol (struct type *type, CORE_ADDR addr)
{
struct symbol *sym;
+
sym = (struct symbol *)
- obstack_alloc (&dynamics_objfile->symbol_obstack, sizeof (struct symbol));
+ obstack_alloc (&dynamics_objfile->objfile_obstack, sizeof (struct symbol));
memset (sym, 0, sizeof (struct symbol));
SYMBOL_LANGUAGE (sym) = language_java;
- DEPRECATED_SYMBOL_NAME (sym) = TYPE_TAG_NAME (type);
+ SYMBOL_SET_LINKAGE_NAME (sym, TYPE_TAG_NAME (type));
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
/* SYMBOL_VALUE (sym) = valu; */
SYMBOL_TYPE (sym) = type;
@@ -170,18 +181,18 @@ free_class_block (struct symtab *symtab)
dict_free (BLOCK_DICT (bl));
}
-#endif
struct type *
java_lookup_class (char *name)
{
struct symbol *sym;
- sym = lookup_symbol (name, expression_context_block, STRUCT_DOMAIN,
- (int *) 0, (struct symtab **) NULL);
+
+ sym = lookup_symbol (name, expression_context_block, STRUCT_DOMAIN, NULL);
if (sym != NULL)
return SYMBOL_TYPE (sym);
#if 0
CORE_ADDR addr;
+
if (called from parser)
{
call lookup_class (or similar) in inferior;
@@ -193,11 +204,12 @@ java_lookup_class (char *name)
else
addr = 0;
struct type *type;
+
type = alloc_type (objfile);
TYPE_CODE (type) = TYPE_CODE_STRUCT;
INIT_CPLUS_SPECIFIC (type);
- TYPE_TAG_NAME (type) = obsavestring (name, strlen (name), &objfile->type_obstack);
- TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+ TYPE_TAG_NAME (type) = obsavestring (name, strlen (name), &objfile->objfile_obstack);
+ TYPE_STUB (type) = 1;
TYPE ? = addr;
return type;
#else
@@ -216,13 +228,13 @@ get_java_utf8_name (struct obstack *obstack, struct value *name)
struct value *temp = name;
int name_length;
CORE_ADDR data_addr;
+
temp = value_struct_elt (&temp, NULL, "length", NULL, "structure");
name_length = (int) value_as_long (temp);
- data_addr = VALUE_ADDRESS (temp) + VALUE_OFFSET (temp)
- + TYPE_LENGTH (VALUE_TYPE (temp));
+ data_addr = value_address (temp) + TYPE_LENGTH (value_type (temp));
chrs = obstack_alloc (obstack, name_length + 1);
chrs[name_length] = '\0';
- read_memory (data_addr, chrs, name_length);
+ read_memory (data_addr, (gdb_byte *) chrs, name_length);
return chrs;
}
@@ -233,10 +245,10 @@ java_class_from_object (struct value *obj_val)
class are fixed. FIXME */
struct value *vtable_val;
- if (TYPE_CODE (VALUE_TYPE (obj_val)) == TYPE_CODE_PTR
- && TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (obj_val))) == 0)
+ if (TYPE_CODE (value_type (obj_val)) == TYPE_CODE_PTR
+ && TYPE_LENGTH (TYPE_TARGET_TYPE (value_type (obj_val))) == 0)
obj_val = value_at (get_java_object_type (),
- value_as_address (obj_val), NULL);
+ value_as_address (obj_val));
vtable_val = value_struct_elt (&obj_val, NULL, "vtable", NULL, "structure");
return value_struct_elt (&vtable_val, NULL, "class", NULL, "structure");
@@ -248,13 +260,14 @@ java_class_is_primitive (struct value *clas)
{
struct value *vtable = value_struct_elt (&clas, NULL, "vtable", NULL, "struct");
CORE_ADDR i = value_as_address (vtable);
+
return (int) (i & 0x7fffffff) == (int) 0x7fffffff;
}
/* Read a GCJ Class object, and generated a gdb (TYPE_CODE_STRUCT) type. */
struct type *
-type_from_class (struct value *clas)
+type_from_class (struct gdbarch *gdbarch, struct value *clas)
{
struct type *type;
char *name;
@@ -263,18 +276,20 @@ type_from_class (struct value *clas)
struct value *utf8_name;
char *nptr;
CORE_ADDR addr;
+#if 0
struct block *bl;
struct dict_iterator iter;
+#endif
int is_array = 0;
- type = check_typedef (VALUE_TYPE (clas));
+ type = check_typedef (value_type (clas));
if (TYPE_CODE (type) == TYPE_CODE_PTR)
{
if (value_logical_not (clas))
return NULL;
clas = value_ind (clas);
}
- addr = VALUE_ADDRESS (clas) + VALUE_OFFSET (clas);
+ addr = value_address (clas);
#if 0
get_java_class_symtab ();
@@ -286,20 +301,21 @@ type_from_class (struct value *clas)
}
#endif
- objfile = get_dynamics_objfile ();
+ objfile = get_dynamics_objfile (gdbarch);
if (java_class_is_primitive (clas))
{
struct value *sig;
+
temp = clas;
sig = value_struct_elt (&temp, NULL, "method_count", NULL, "structure");
- return java_primitive_type (value_as_long (sig));
+ return java_primitive_type (gdbarch, value_as_long (sig));
}
/* Get Class name. */
/* if clasloader non-null, prepend loader address. FIXME */
temp = clas;
utf8_name = value_struct_elt (&temp, NULL, "name", NULL, "structure");
- name = get_java_utf8_name (&objfile->type_obstack, utf8_name);
+ name = get_java_utf8_name (&objfile->objfile_obstack, utf8_name);
for (nptr = name; *nptr != 0; nptr++)
{
if (*nptr == '/')
@@ -318,29 +334,31 @@ type_from_class (struct value *clas)
{
char *signature = name;
int namelen = java_demangled_signature_length (signature);
+
if (namelen > strlen (name))
- name = obstack_alloc (&objfile->type_obstack, namelen + 1);
+ name = obstack_alloc (&objfile->objfile_obstack, namelen + 1);
java_demangled_signature_copy (name, signature);
name[namelen] = '\0';
is_array = 1;
temp = clas;
/* Set array element type. */
temp = value_struct_elt (&temp, NULL, "methods", NULL, "structure");
- VALUE_TYPE (temp) = lookup_pointer_type (VALUE_TYPE (clas));
- TYPE_TARGET_TYPE (type) = type_from_class (temp);
+ deprecated_set_value_type (temp, lookup_pointer_type (value_type (clas)));
+ TYPE_TARGET_TYPE (type) = type_from_class (gdbarch, temp);
}
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_TAG_NAME (type) = name;
add_class_symtab_symbol (add_class_symbol (type, addr));
- return java_link_class_type (type, clas);
+ return java_link_class_type (gdbarch, type, clas);
}
/* Fill in class TYPE with data from the CLAS value. */
-struct type *
-java_link_class_type (struct type *type, struct value *clas)
+static struct type *
+java_link_class_type (struct gdbarch *gdbarch,
+ struct type *type, struct value *clas)
{
struct value *temp;
char *unqualified_name;
@@ -354,16 +372,17 @@ java_link_class_type (struct type *type, struct value *clas)
struct value *method = NULL;
struct value *field = NULL;
int i, j;
- struct objfile *objfile = get_dynamics_objfile ();
+ struct objfile *objfile = get_dynamics_objfile (gdbarch);
struct type *tsuper;
+ gdb_assert (name != NULL);
unqualified_name = strrchr (name, '.');
if (unqualified_name == NULL)
unqualified_name = name;
temp = clas;
temp = value_struct_elt (&temp, NULL, "superclass", NULL, "structure");
- if (name != NULL && strcmp (name, "java.lang.Object") == 0)
+ if (strcmp (name, "java.lang.Object") == 0)
{
tsuper = get_java_object_type ();
if (tsuper && TYPE_CODE (tsuper) == TYPE_CODE_PTR)
@@ -371,7 +390,7 @@ java_link_class_type (struct type *type, struct value *clas)
type_is_object = 1;
}
else
- tsuper = type_from_class (temp);
+ tsuper = type_from_class (gdbarch, temp);
#if 1
ninterfaces = 0;
@@ -428,16 +447,16 @@ java_link_class_type (struct type *type, struct value *clas)
fields = NULL;
nfields--; /* First set up dummy "class" field. */
- SET_FIELD_PHYSADDR (TYPE_FIELD (type, nfields),
- VALUE_ADDRESS (clas) + VALUE_OFFSET (clas));
+ SET_FIELD_PHYSADDR (TYPE_FIELD (type, nfields), value_address (clas));
TYPE_FIELD_NAME (type, nfields) = "class";
- TYPE_FIELD_TYPE (type, nfields) = VALUE_TYPE (clas);
+ TYPE_FIELD_TYPE (type, nfields) = value_type (clas);
SET_TYPE_FIELD_PRIVATE (type, nfields);
for (i = TYPE_N_BASECLASSES (type); i < nfields; i++)
{
int accflags;
int boffset;
+
if (fields == NULL)
{
temp = clas;
@@ -446,13 +465,16 @@ java_link_class_type (struct type *type, struct value *clas)
}
else
{ /* Re-use field value for next field. */
- VALUE_ADDRESS (field) += TYPE_LENGTH (VALUE_TYPE (field));
- VALUE_LAZY (field) = 1;
+ CORE_ADDR addr
+ = value_address (field) + TYPE_LENGTH (value_type (field));
+
+ set_value_address (field, addr);
+ set_value_lazy (field, 1);
}
temp = field;
temp = value_struct_elt (&temp, NULL, "name", NULL, "structure");
TYPE_FIELD_NAME (type, i) =
- get_java_utf8_name (&objfile->type_obstack, temp);
+ get_java_utf8_name (&objfile->objfile_obstack, temp);
temp = field;
accflags = value_as_long (value_struct_elt (&temp, NULL, "accflags",
NULL, "structure"));
@@ -483,9 +505,10 @@ java_link_class_type (struct type *type, struct value *clas)
else
{
struct type *ftype;
+
temp = field;
temp = value_struct_elt (&temp, NULL, "type", NULL, "structure");
- ftype = type_from_class (temp);
+ ftype = type_from_class (gdbarch, temp);
if (TYPE_CODE (ftype) == TYPE_CODE_STRUCT)
ftype = lookup_pointer_type (ftype);
TYPE_FIELD_TYPE (type, i) = ftype;
@@ -498,7 +521,7 @@ java_link_class_type (struct type *type, struct value *clas)
TYPE_NFN_FIELDS_TOTAL (type) = nmethods;
j = nmethods * sizeof (struct fn_field);
fn_fields = (struct fn_field *)
- obstack_alloc (&dynamics_objfile->symbol_obstack, j);
+ obstack_alloc (&dynamics_objfile->objfile_obstack, j);
memset (fn_fields, 0, j);
fn_fieldlists = (struct fn_fieldlist *)
alloca (nmethods * sizeof (struct fn_fieldlist));
@@ -508,6 +531,7 @@ java_link_class_type (struct type *type, struct value *clas)
{
char *mname;
int k;
+
if (methods == NULL)
{
temp = clas;
@@ -516,14 +540,17 @@ java_link_class_type (struct type *type, struct value *clas)
}
else
{ /* Re-use method value for next method. */
- VALUE_ADDRESS (method) += TYPE_LENGTH (VALUE_TYPE (method));
- VALUE_LAZY (method) = 1;
+ CORE_ADDR addr
+ = value_address (method) + TYPE_LENGTH (value_type (method));
+
+ set_value_address (method, addr);
+ set_value_lazy (method, 1);
}
/* Get method name. */
temp = method;
temp = value_struct_elt (&temp, NULL, "name", NULL, "structure");
- mname = get_java_utf8_name (&objfile->type_obstack, temp);
+ mname = get_java_utf8_name (&objfile->objfile_obstack, temp);
if (strcmp (mname, "") == 0)
mname = unqualified_name;
@@ -547,8 +574,9 @@ java_link_class_type (struct type *type, struct value *clas)
if (strcmp (mname, fn_fieldlists[j].name) == 0)
{ /* Found an existing method with the same name. */
int l;
+
if (mname != unqualified_name)
- obstack_free (&objfile->type_obstack, mname);
+ obstack_free (&objfile->objfile_obstack, mname);
mname = fn_fieldlists[j].name;
fn_fieldlists[j].length++;
k = i - k; /* Index of new slot. */
@@ -563,13 +591,15 @@ java_link_class_type (struct type *type, struct value *clas)
}
fn_fields[k].physname = "";
fn_fields[k].is_stub = 1;
- fn_fields[k].type = make_function_type (java_void_type, NULL); /* FIXME */
+ /* FIXME */
+ fn_fields[k].type = lookup_function_type
+ (builtin_java_type (gdbarch)->builtin_void);
TYPE_CODE (fn_fields[k].type) = TYPE_CODE_METHOD;
}
j = TYPE_NFN_FIELDS (type) * sizeof (struct fn_fieldlist);
TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
- obstack_alloc (&dynamics_objfile->symbol_obstack, j);
+ obstack_alloc (&dynamics_objfile->objfile_obstack, j);
memcpy (TYPE_FN_FIELDLISTS (type), fn_fieldlists, j);
return type;
@@ -577,27 +607,50 @@ java_link_class_type (struct type *type, struct value *clas)
static struct type *java_object_type;
+/* A free function that is attached to the objfile defining
+ java_object_type. This is used to clear the cached type whenever
+ its owning objfile is destroyed. */
+static void
+jv_clear_object_type (struct objfile *objfile, void *ignore)
+{
+ java_object_type = NULL;
+}
+
+static void
+set_java_object_type (struct type *type)
+{
+ struct objfile *owner;
+
+ gdb_assert (java_object_type == NULL);
+
+ owner = TYPE_OBJFILE (type);
+ if (owner)
+ set_objfile_data (owner, jv_type_objfile_data_key, &java_object_type);
+ java_object_type = type;
+}
+
struct type *
get_java_object_type (void)
{
if (java_object_type == NULL)
{
struct symbol *sym;
- sym = lookup_symbol ("java.lang.Object", NULL, STRUCT_DOMAIN,
- (int *) 0, (struct symtab **) NULL);
+
+ sym = lookup_symbol ("java.lang.Object", NULL, STRUCT_DOMAIN, NULL);
if (sym == NULL)
- error ("cannot find java.lang.Object");
- java_object_type = SYMBOL_TYPE (sym);
+ error (_("cannot find java.lang.Object"));
+ set_java_object_type (SYMBOL_TYPE (sym));
}
return java_object_type;
}
int
-get_java_object_header_size (void)
+get_java_object_header_size (struct gdbarch *gdbarch)
{
struct type *objtype = get_java_object_type ();
+
if (objtype == NULL)
- return (2 * TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ return (2 * gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT);
else
return TYPE_LENGTH (objtype);
}
@@ -621,7 +674,7 @@ is_object_type (struct type *type)
if (name != NULL && strcmp (name, "vtable") == 0)
{
if (java_object_type == NULL)
- java_object_type = type;
+ set_java_object_type (type);
return 1;
}
}
@@ -629,77 +682,109 @@ is_object_type (struct type *type)
}
struct type *
-java_primitive_type (int signature)
+java_primitive_type (struct gdbarch *gdbarch, int signature)
{
+ const struct builtin_java_type *builtin = builtin_java_type (gdbarch);
+
switch (signature)
{
case 'B':
- return java_byte_type;
+ return builtin->builtin_byte;
case 'S':
- return java_short_type;
+ return builtin->builtin_short;
case 'I':
- return java_int_type;
+ return builtin->builtin_int;
case 'J':
- return java_long_type;
+ return builtin->builtin_long;
case 'Z':
- return java_boolean_type;
+ return builtin->builtin_boolean;
case 'C':
- return java_char_type;
+ return builtin->builtin_char;
case 'F':
- return java_float_type;
+ return builtin->builtin_float;
case 'D':
- return java_double_type;
+ return builtin->builtin_double;
case 'V':
- return java_void_type;
+ return builtin->builtin_void;
}
- error ("unknown signature '%c' for primitive type", (char) signature);
+ error (_("unknown signature '%c' for primitive type"), (char) signature);
}
/* If name[0 .. namelen-1] is the name of a primitive Java type,
return that type. Otherwise, return NULL. */
struct type *
-java_primitive_type_from_name (char *name, int namelen)
+java_primitive_type_from_name (struct gdbarch *gdbarch,
+ char *name, int namelen)
{
+ const struct builtin_java_type *builtin = builtin_java_type (gdbarch);
+
switch (name[0])
{
case 'b':
if (namelen == 4 && memcmp (name, "byte", 4) == 0)
- return java_byte_type;
+ return builtin->builtin_byte;
if (namelen == 7 && memcmp (name, "boolean", 7) == 0)
- return java_boolean_type;
+ return builtin->builtin_boolean;
break;
case 'c':
if (namelen == 4 && memcmp (name, "char", 4) == 0)
- return java_char_type;
+ return builtin->builtin_char;
case 'd':
if (namelen == 6 && memcmp (name, "double", 6) == 0)
- return java_double_type;
+ return builtin->builtin_double;
break;
case 'f':
if (namelen == 5 && memcmp (name, "float", 5) == 0)
- return java_float_type;
+ return builtin->builtin_float;
break;
case 'i':
if (namelen == 3 && memcmp (name, "int", 3) == 0)
- return java_int_type;
+ return builtin->builtin_int;
break;
case 'l':
if (namelen == 4 && memcmp (name, "long", 4) == 0)
- return java_long_type;
+ return builtin->builtin_long;
break;
case 's':
if (namelen == 5 && memcmp (name, "short", 5) == 0)
- return java_short_type;
+ return builtin->builtin_short;
break;
case 'v':
if (namelen == 4 && memcmp (name, "void", 4) == 0)
- return java_void_type;
+ return builtin->builtin_void;
break;
}
return NULL;
}
+static char *
+java_primitive_type_name (int signature)
+{
+ switch (signature)
+ {
+ case 'B':
+ return "byte";
+ case 'S':
+ return "short";
+ case 'I':
+ return "int";
+ case 'J':
+ return "long";
+ case 'Z':
+ return "boolean";
+ case 'C':
+ return "char";
+ case 'F':
+ return "float";
+ case 'D':
+ return "double";
+ case 'V':
+ return "void";
+ }
+ error (_("unknown signature '%c' for primitive type"), (char) signature);
+}
+
/* Return the length (in bytes) of demangled name of the Java type
signature string SIGNATURE. */
@@ -707,6 +792,7 @@ static int
java_demangled_signature_length (char *signature)
{
int array = 0;
+
for (; *signature == '['; signature++)
array += 2; /* Two chars for "[]". */
switch (signature[0])
@@ -715,7 +801,7 @@ java_demangled_signature_length (char *signature)
/* Subtract 2 for 'L' and ';'. */
return strlen (signature) - 2 + array;
default:
- return strlen (TYPE_NAME (java_primitive_type (signature[0]))) + array;
+ return strlen (java_primitive_type_name (signature[0])) + array;
}
}
@@ -727,6 +813,7 @@ java_demangled_signature_copy (char *result, char *signature)
int array = 0;
char *ptr;
int i;
+
while (*signature == '[')
{
array++;
@@ -747,7 +834,7 @@ java_demangled_signature_copy (char *result, char *signature)
}
break;
default:
- ptr = TYPE_NAME (java_primitive_type (signature[0]));
+ ptr = java_primitive_type_name (signature[0]);
i = strlen (ptr);
strcpy (result, ptr);
ptr = result + i;
@@ -768,37 +855,22 @@ java_demangle_type_signature (char *signature)
{
int length = java_demangled_signature_length (signature);
char *result = xmalloc (length + 1);
+
java_demangled_signature_copy (result, signature);
result[length] = '\0';
return result;
}
-struct type *
-java_lookup_type (char *signature)
-{
- switch (signature[0])
- {
- case 'L':
- case '[':
- error ("java_lookup_type not fully implemented");
- default:
- return java_primitive_type (signature[0]);
- }
-}
-
/* Return the type of TYPE followed by DIMS pairs of [ ].
If DIMS == 0, TYPE is returned. */
struct type *
java_array_type (struct type *type, int dims)
{
- struct type *range_type;
-
while (dims-- > 0)
{
- range_type = create_range_type (NULL, builtin_type_int, 0, 0);
/* FIXME This is bogus! Java arrays are not gdb arrays! */
- type = create_array_type (NULL, type, range_type);
+ type = lookup_array_range_type (type, 0, 0);
}
return type;
@@ -809,7 +881,7 @@ java_array_type (struct type *type, int dims)
static struct value *
java_value_string (char *ptr, int len)
{
- error ("not implemented - java_value_string"); /* FIXME */
+ error (_("not implemented - java_value_string")); /* FIXME */
}
/* Print the character C on STREAM as part of the contents of a literal
@@ -817,7 +889,7 @@ java_value_string (char *ptr, int len)
characters and strings is language specific. */
static void
-java_emit_char (int c, struct ui_file *stream, int quoter)
+java_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
{
switch (c)
{
@@ -860,6 +932,7 @@ evaluate_subexp_java (struct type *expect_type, struct expression *exp,
struct value *arg1;
struct value *arg2;
struct type *type;
+
switch (op)
{
case UNOP_IND:
@@ -867,11 +940,11 @@ evaluate_subexp_java (struct type *expect_type, struct expression *exp,
goto standard;
(*pos)++;
arg1 = evaluate_subexp_java (NULL_TYPE, exp, pos, EVAL_NORMAL);
- if (is_object_type (VALUE_TYPE (arg1)))
+ if (is_object_type (value_type (arg1)))
{
struct type *type;
- type = type_from_class (java_class_from_object (arg1));
+ type = type_from_class (exp->gdbarch, java_class_from_object (arg1));
arg1 = value_cast (lookup_pointer_type (type), arg1);
}
if (noside == EVAL_SKIP)
@@ -888,8 +961,8 @@ evaluate_subexp_java (struct type *expect_type, struct expression *exp,
array or pointer type (like a plain int variable for example),
then report this as an error. */
- COERCE_REF (arg1);
- type = check_typedef (VALUE_TYPE (arg1));
+ arg1 = coerce_ref (arg1);
+ type = check_typedef (value_type (arg1));
if (TYPE_CODE (type) == TYPE_CODE_PTR)
type = check_typedef (TYPE_TARGET_TYPE (type));
name = TYPE_NAME (type);
@@ -899,45 +972,46 @@ evaluate_subexp_java (struct type *expect_type, struct expression *exp,
if (TYPE_CODE (type) == TYPE_CODE_STRUCT
&& i > 2 && name[i - 1] == ']')
{
+ enum bfd_endian byte_order = gdbarch_byte_order (exp->gdbarch);
CORE_ADDR address;
long length, index;
struct type *el_type;
- char buf4[4];
+ gdb_byte buf4[4];
struct value *clas = java_class_from_object (arg1);
struct value *temp = clas;
/* Get CLASS_ELEMENT_TYPE of the array type. */
temp = value_struct_elt (&temp, NULL, "methods",
NULL, "structure");
- VALUE_TYPE (temp) = VALUE_TYPE (clas);
- el_type = type_from_class (temp);
+ deprecated_set_value_type (temp, value_type (clas));
+ el_type = type_from_class (exp->gdbarch, temp);
if (TYPE_CODE (el_type) == TYPE_CODE_STRUCT)
el_type = lookup_pointer_type (el_type);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (el_type, VALUE_LVAL (arg1));
address = value_as_address (arg1);
- address += JAVA_OBJECT_SIZE;
+ address += get_java_object_header_size (exp->gdbarch);
read_memory (address, buf4, 4);
- length = (long) extract_signed_integer (buf4, 4);
+ length = (long) extract_signed_integer (buf4, 4, byte_order);
index = (long) value_as_long (arg2);
if (index >= length || index < 0)
- error ("array index (%ld) out of bounds (length: %ld)",
+ error (_("array index (%ld) out of bounds (length: %ld)"),
index, length);
address = (address + 4) + index * TYPE_LENGTH (el_type);
- return value_at (el_type, address, NULL);
+ return value_at (el_type, address);
}
else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
{
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (TYPE_TARGET_TYPE (type), VALUE_LVAL (arg1));
else
- return value_subscript (arg1, arg2);
+ return value_subscript (arg1, value_as_long (arg2));
}
if (name)
- error ("cannot subscript something of type `%s'", name);
+ error (_("cannot subscript something of type `%s'"), name);
else
- error ("cannot subscript requested type");
+ error (_("cannot subscript requested type"));
case OP_STRING:
(*pos)++;
@@ -947,10 +1021,10 @@ evaluate_subexp_java (struct type *expect_type, struct expression *exp,
goto nosideret;
return java_value_string (&exp->elts[pc + 2].string, i);
- case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
/* Convert object field (such as TYPE.class) to reference. */
- if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT)
+ if (TYPE_CODE (value_type (arg1)) == TYPE_CODE_STRUCT)
arg1 = value_addr (arg1);
return arg1;
default:
@@ -959,45 +1033,66 @@ evaluate_subexp_java (struct type *expect_type, struct expression *exp,
standard:
return evaluate_subexp_standard (expect_type, exp, pos, noside);
nosideret:
- return value_from_longest (builtin_type_long, (LONGEST) 1);
+ return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1);
}
-static struct type *
-java_create_fundamental_type (struct objfile *objfile, int typeid)
+static char *java_demangle (const char *mangled, int options)
{
- switch (typeid)
- {
- case FT_VOID:
- return java_void_type;
- case FT_BOOLEAN:
- return java_boolean_type;
- case FT_CHAR:
- return java_char_type;
- case FT_FLOAT:
- return java_float_type;
- case FT_DBL_PREC_FLOAT:
- return java_double_type;
- case FT_BYTE:
- case FT_SIGNED_CHAR:
- return java_byte_type;
- case FT_SHORT:
- case FT_SIGNED_SHORT:
- return java_short_type;
- case FT_INTEGER:
- case FT_SIGNED_INTEGER:
- return java_int_type;
- case FT_LONG:
- case FT_SIGNED_LONG:
- return java_long_type;
- }
- return c_create_fundamental_type (objfile, typeid);
+ return cplus_demangle (mangled, options | DMGL_JAVA);
}
-static char *java_demangle (const char *mangled, int options)
+/* Find the member function name of the demangled name NAME. NAME
+ must be a method name including arguments, in order to correctly
+ locate the last component.
+
+ This function return a pointer to the first dot before the
+ member function name, or NULL if the name was not of the
+ expected form. */
+
+static const char *
+java_find_last_component (const char *name)
{
- return cplus_demangle (mangled, options | DMGL_JAVA);
+ const char *p;
+
+ /* Find argument list. */
+ p = strchr (name, '(');
+
+ if (p == NULL)
+ return NULL;
+
+ /* Back up and find first dot prior to argument list. */
+ while (p > name && *p != '.')
+ p--;
+
+ if (p == name)
+ return NULL;
+
+ return p;
}
+/* Return the name of the class containing method PHYSNAME. */
+
+static char *
+java_class_name_from_physname (const char *physname)
+{
+ char *ret = NULL;
+ const char *end;
+ char *demangled_name = java_demangle (physname, DMGL_PARAMS | DMGL_ANSI);
+
+ if (demangled_name == NULL)
+ return NULL;
+
+ end = java_find_last_component (demangled_name);
+ if (end != NULL)
+ {
+ ret = xmalloc (end - demangled_name + 1);
+ memcpy (ret, demangled_name, end - demangled_name);
+ ret[end - demangled_name] = '\0';
+ }
+
+ xfree (demangled_name);
+ return ret;
+}
/* Table mapping opcodes into strings for printing operators
and precedences of the operators. */
@@ -1039,74 +1134,146 @@ const struct op_print java_op_print_tab[] =
{NULL, 0, 0, 0}
};
+enum java_primitive_types
+{
+ java_primitive_type_int,
+ java_primitive_type_short,
+ java_primitive_type_long,
+ java_primitive_type_byte,
+ java_primitive_type_boolean,
+ java_primitive_type_char,
+ java_primitive_type_float,
+ java_primitive_type_double,
+ java_primitive_type_void,
+ nr_java_primitive_types
+};
+
+static void
+java_language_arch_info (struct gdbarch *gdbarch,
+ struct language_arch_info *lai)
+{
+ const struct builtin_java_type *builtin = builtin_java_type (gdbarch);
+
+ lai->string_char_type = builtin->builtin_char;
+ lai->primitive_type_vector
+ = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_java_primitive_types + 1,
+ struct type *);
+ lai->primitive_type_vector [java_primitive_type_int]
+ = builtin->builtin_int;
+ lai->primitive_type_vector [java_primitive_type_short]
+ = builtin->builtin_short;
+ lai->primitive_type_vector [java_primitive_type_long]
+ = builtin->builtin_long;
+ lai->primitive_type_vector [java_primitive_type_byte]
+ = builtin->builtin_byte;
+ lai->primitive_type_vector [java_primitive_type_boolean]
+ = builtin->builtin_boolean;
+ lai->primitive_type_vector [java_primitive_type_char]
+ = builtin->builtin_char;
+ lai->primitive_type_vector [java_primitive_type_float]
+ = builtin->builtin_float;
+ lai->primitive_type_vector [java_primitive_type_double]
+ = builtin->builtin_double;
+ lai->primitive_type_vector [java_primitive_type_void]
+ = builtin->builtin_void;
+
+ lai->bool_type_symbol = "boolean";
+ lai->bool_type_default = builtin->builtin_boolean;
+}
+
+const struct exp_descriptor exp_descriptor_java =
+{
+ print_subexp_standard,
+ operator_length_standard,
+ operator_check_standard,
+ op_name_standard,
+ dump_subexp_body_standard,
+ evaluate_subexp_java
+};
+
const struct language_defn java_language_defn =
{
"java", /* Language name */
language_java,
- c_builtin_types,
range_check_off,
type_check_off,
case_sensitive_on,
+ array_row_major,
+ macro_expansion_no,
+ &exp_descriptor_java,
java_parse,
java_error,
- evaluate_subexp_java,
+ null_post_parser,
c_printchar, /* Print a character constant */
c_printstr, /* Function to print string constant */
java_emit_char, /* Function to print a single character */
- java_create_fundamental_type, /* Create fundamental type in this language */
java_print_type, /* Print a type using appropriate syntax */
+ default_print_typedef, /* Print a typedef using appropriate syntax */
java_val_print, /* Print a value using appropriate syntax */
java_value_print, /* Print a top-level value */
NULL, /* Language specific skip_trampoline */
- value_of_this, /* value_of_this */
+ "this", /* name_of_this */
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
+ basic_lookup_transparent_type,/* lookup_transparent_type */
java_demangle, /* Language specific symbol demangler */
- {"", "", "", ""}, /* Binary format info */
- {"0%lo", "0", "o", ""}, /* Octal format info */
- {"%ld", "", "d", ""}, /* Decimal format info */
- {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ java_class_name_from_physname,/* Language specific class name */
java_op_print_tab, /* expression operators for printing */
0, /* not c-style arrays */
0, /* String lower bound */
- &builtin_type_char, /* Type of string elements */
+ default_word_break_characters,
+ default_make_symbol_completion_list,
+ java_language_arch_info,
+ default_print_array_index,
+ default_pass_by_reference,
+ default_get_string,
LANG_MAGIC
};
-void
-_initialize_java_language (void)
+static void *
+build_java_types (struct gdbarch *gdbarch)
{
+ struct builtin_java_type *builtin_java_type
+ = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_java_type);
+
+ builtin_java_type->builtin_int
+ = arch_integer_type (gdbarch, 32, 0, "int");
+ builtin_java_type->builtin_short
+ = arch_integer_type (gdbarch, 16, 0, "short");
+ builtin_java_type->builtin_long
+ = arch_integer_type (gdbarch, 64, 0, "long");
+ builtin_java_type->builtin_byte
+ = arch_integer_type (gdbarch, 8, 0, "byte");
+ builtin_java_type->builtin_boolean
+ = arch_boolean_type (gdbarch, 8, 0, "boolean");
+ builtin_java_type->builtin_char
+ = arch_character_type (gdbarch, 16, 1, "char");
+ builtin_java_type->builtin_float
+ = arch_float_type (gdbarch, 32, "float", NULL);
+ builtin_java_type->builtin_double
+ = arch_float_type (gdbarch, 64, "double", NULL);
+ builtin_java_type->builtin_void
+ = arch_type (gdbarch, TYPE_CODE_VOID, 1, "void");
+
+ return builtin_java_type;
+}
- java_int_type = init_type (TYPE_CODE_INT, 4, 0, "int", NULL);
- java_short_type = init_type (TYPE_CODE_INT, 2, 0, "short", NULL);
- java_long_type = init_type (TYPE_CODE_INT, 8, 0, "long", NULL);
- java_byte_type = init_type (TYPE_CODE_INT, 1, 0, "byte", NULL);
- java_boolean_type = init_type (TYPE_CODE_BOOL, 1, 0, "boolean", NULL);
- java_char_type = init_type (TYPE_CODE_CHAR, 2, TYPE_FLAG_UNSIGNED, "char", NULL);
- java_float_type = init_type (TYPE_CODE_FLT, 4, 0, "float", NULL);
- java_double_type = init_type (TYPE_CODE_FLT, 8, 0, "double", NULL);
- java_void_type = init_type (TYPE_CODE_VOID, 1, 0, "void", NULL);
+static struct gdbarch_data *java_type_data;
- add_language (&java_language_defn);
+const struct builtin_java_type *
+builtin_java_type (struct gdbarch *gdbarch)
+{
+ return gdbarch_data (gdbarch, java_type_data);
}
-/* Cleanup code that should be run on every "run".
- We should use make_run_cleanup to have this be called.
- But will that mess up values in value histry? FIXME */
-
-extern void java_rerun_cleanup (void);
void
-java_rerun_cleanup (void)
+_initialize_java_language (void)
{
- if (class_symtab != NULL)
- {
- free_symtab (class_symtab); /* ??? */
- class_symtab = NULL;
- }
- if (dynamics_objfile != NULL)
- {
- free_objfile (dynamics_objfile);
- dynamics_objfile = NULL;
- }
+ jv_dynamics_objfile_data_key
+ = register_objfile_data_with_cleanup (NULL, jv_per_objfile_free);
+ jv_type_objfile_data_key
+ = register_objfile_data_with_cleanup (NULL, jv_clear_object_type);
- java_object_type = NULL;
+ java_type_data = gdbarch_data_register_post_init (build_java_types);
+
+ add_language (&java_language_defn);
}