2004-07-27 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / gdb / jv-lang.c
index 37fab62cd255b1b02d4b1d63eab25f949709b27d..3f68ec4051ffeba1d3cf079236fec9410c0db595 100644 (file)
@@ -1,5 +1,5 @@
 /* Java language support routines for GDB, the GNU debugger.
-   Copyright 1997, 1998, 1999-2000 Free Software Foundation, Inc.
+   Copyright 1997, 1998, 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -33,6 +33,9 @@
 #include "c-lang.h"
 #include "jv-lang.h"
 #include "gdbcore.h"
+#include "block.h"
+#include "demangle.h"
+#include "dictionary.h"
 #include <ctype.h>
 
 struct type *java_int_type;
@@ -53,20 +56,27 @@ static int java_demangled_signature_length (char *);
 static void java_demangled_signature_copy (char *, char *);
 
 static struct symtab *get_java_class_symtab (void);
-static char *get_java_utf8_name (struct obstack *obstack, value_ptr name);
-static int java_class_is_primitive (value_ptr clas);
-static struct type *java_lookup_type (char *signature);
-static value_ptr java_value_string (char *ptr, int len);
+static char *get_java_utf8_name (struct obstack *obstack, struct value *name);
+static int java_class_is_primitive (struct value *clas);
+static struct value *java_value_string (char *ptr, int len);
 
 static void java_emit_char (int c, struct ui_file * stream, int quoter);
 
+static char *java_class_name_from_physname (const char *physname);
+
 /* This objfile contains symtabs that have been dynamically created
    to record dynamically loaded Java classes and dynamically
    compiled java methods. */
 
 static struct objfile *dynamics_objfile = NULL;
 
-static struct type *java_link_class_type (struct type *, value_ptr);
+static struct type *java_link_class_type (struct type *, struct value *);
+
+/* FIXME: carlton/2003-02-04: This is the main or only caller of
+   allocate_objfile with first argument NULL; as a result, this code
+   breaks every so often.  Somebody should write a test case that
+   exercises GDB in various ways (e.g. something involving loading a
+   dynamic library) after this code has been called.  */
 
 static struct objfile *
 get_dynamics_objfile (void)
@@ -83,9 +93,7 @@ get_dynamics_objfile (void)
 
 static struct symtab *class_symtab = NULL;
 
-/* Maximum number of class in class_symtab before relocation is needed. */
-
-static int class_symtab_space;
+static void free_class_block (struct symtab *symtab);
 
 static struct symtab *
 get_java_class_symtab (void)
@@ -98,30 +106,22 @@ get_java_class_symtab (void)
       class_symtab = allocate_symtab ("<java-classes>", objfile);
       class_symtab->language = language_java;
       bv = (struct blockvector *)
-       obstack_alloc (&objfile->symbol_obstack, sizeof (struct blockvector));
+       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_NSYMS (bl) = 0;
-      BLOCK_START (bl) = 0;
-      BLOCK_END (bl) = 0;
-      BLOCK_FUNCTION (bl) = NULL;
-      BLOCK_SUPERBLOCK (bl) = NULL;
-      BLOCK_GCC_COMPILED (bl) = 0;
+      bl = allocate_block (&objfile->objfile_obstack);
+      BLOCK_DICT (bl) = dict_create_linear (&objfile->objfile_obstack,
+                                           NULL);
       BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
 
-      /* Allocate GLOBAL_BLOCK.  This has to be relocatable. */
-      class_symtab_space = 128;
-      bl = (struct block *)
-       mmalloc (objfile->md,
-                sizeof (struct block)
-                + ((class_symtab_space - 1) * sizeof (struct symbol *)));
-      *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_ptr = (char *) bl;
+      class_symtab->free_func = free_class_block;
     }
   return class_symtab;
 }
@@ -131,21 +131,7 @@ add_class_symtab_symbol (struct symbol *sym)
 {
   struct symtab *symtab = get_java_class_symtab ();
   struct blockvector *bv = BLOCKVECTOR (symtab);
-  struct block *bl = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-  if (BLOCK_NSYMS (bl) >= class_symtab_space)
-    {
-      /* Need to re-allocate. */
-      class_symtab_space *= 2;
-      bl = (struct block *)
-       mrealloc (symtab->objfile->md, bl,
-                 sizeof (struct block)
-                 + ((class_symtab_space - 1) * sizeof (struct symbol *)));
-      class_symtab->free_ptr = (char *) bl;
-      BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
-    }
-
-  BLOCK_SYM (bl, BLOCK_NSYMS (bl)) = sym;
-  BLOCK_NSYMS (bl) = BLOCK_NSYMS (bl) + 1;
+  dict_add_symbol (BLOCK_DICT (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)), sym);
 }
 
 static struct symbol *add_class_symbol (struct type *type, CORE_ADDR addr);
@@ -155,24 +141,34 @@ 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;
-  SYMBOL_NAME (sym) = TYPE_TAG_NAME (type);
+  DEPRECATED_SYMBOL_NAME (sym) = TYPE_TAG_NAME (type);
   SYMBOL_CLASS (sym) = LOC_TYPEDEF;
   /*  SYMBOL_VALUE (sym) = valu; */
   SYMBOL_TYPE (sym) = type;
-  SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+  SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
   SYMBOL_VALUE_ADDRESS (sym) = addr;
   return sym;
 }
+
+/* Free the dynamic symbols block.  */
+static void
+free_class_block (struct symtab *symtab)
+{
+  struct blockvector *bv = BLOCKVECTOR (symtab);
+  struct block *bl = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+
+  dict_free (BLOCK_DICT (bl));
+}
 #endif
 
 struct type *
 java_lookup_class (char *name)
 {
   struct symbol *sym;
-  sym = lookup_symbol (name, expression_context_block, STRUCT_NAMESPACE,
+  sym = lookup_symbol (name, expression_context_block, STRUCT_DOMAIN,
                       (int *) 0, (struct symtab **) NULL);
   if (sym != NULL)
     return SYMBOL_TYPE (sym);
@@ -192,7 +188,7 @@ java_lookup_class (char *name)
   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_TAG_NAME (type) = obsavestring (name, strlen (name), &objfile->objfile_obstack);
   TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
   TYPE ? = addr;
   return type;
@@ -206,10 +202,10 @@ java_lookup_class (char *name)
    a name given by NAME (which has type Utf8Const*). */
 
 char *
-get_java_utf8_name (struct obstack *obstack, value_ptr name)
+get_java_utf8_name (struct obstack *obstack, struct value *name)
 {
   char *chrs;
-  value_ptr temp = name;
+  struct value *temp = name;
   int name_length;
   CORE_ADDR data_addr;
   temp = value_struct_elt (&temp, NULL, "length", NULL, "structure");
@@ -222,17 +218,17 @@ get_java_utf8_name (struct obstack *obstack, value_ptr name)
   return chrs;
 }
 
-value_ptr
-java_class_from_object (value_ptr obj_val)
+struct value *
+java_class_from_object (struct value *obj_val)
 {
   /* This is all rather inefficient, since the offsets of vtable and
      class are fixed.  FIXME */
-  value_ptr vtable_val;
+  struct value *vtable_val;
 
   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_pointer (obj_val), NULL);
+                       value_as_address (obj_val), NULL);
 
   vtable_val = value_struct_elt (&obj_val, NULL, "vtable", NULL, "structure");
   return value_struct_elt (&vtable_val, NULL, "class", NULL, "structure");
@@ -240,27 +236,27 @@ java_class_from_object (value_ptr obj_val)
 
 /* Check if CLASS_IS_PRIMITIVE(value of clas): */
 static int
-java_class_is_primitive (value_ptr clas)
+java_class_is_primitive (struct value *clas)
 {
-  value_ptr vtable = value_struct_elt (&clas, NULL, "vtable", NULL, "struct");
-  CORE_ADDR i = value_as_pointer (vtable);
+  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 (value_ptr clas)
+type_from_class (struct value *clas)
 {
   struct type *type;
   char *name;
-  value_ptr temp;
+  struct value *temp;
   struct objfile *objfile;
-  value_ptr utf8_name;
+  struct value *utf8_name;
   char *nptr;
   CORE_ADDR addr;
   struct block *bl;
-  int i;
+  struct dict_iterator iter;
   int is_array = 0;
 
   type = check_typedef (VALUE_TYPE (clas));
@@ -275,9 +271,8 @@ type_from_class (value_ptr clas)
 #if 0
   get_java_class_symtab ();
   bl = BLOCKVECTOR_BLOCK (BLOCKVECTOR (class_symtab), GLOBAL_BLOCK);
-  for (i = BLOCK_NSYMS (bl); --i >= 0;)
+  ALL_BLOCK_SYMBOLS (block, iter, sym)
     {
-      struct symbol *sym = BLOCK_SYM (bl, i);
       if (SYMBOL_VALUE_ADDRESS (sym) == addr)
        return SYMBOL_TYPE (sym);
     }
@@ -286,7 +281,7 @@ type_from_class (value_ptr clas)
   objfile = get_dynamics_objfile ();
   if (java_class_is_primitive (clas))
     {
-      value_ptr sig;
+      struct value *sig;
       temp = clas;
       sig = value_struct_elt (&temp, NULL, "method_count", NULL, "structure");
       return java_primitive_type (value_as_long (sig));
@@ -296,7 +291,7 @@ type_from_class (value_ptr clas)
   /* 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 == '/')
@@ -316,7 +311,7 @@ type_from_class (value_ptr 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;
@@ -337,16 +332,19 @@ type_from_class (value_ptr clas)
 /* Fill in class TYPE with data from the CLAS value. */
 
 struct type *
-java_link_class_type (struct type *type, value_ptr clas)
+java_link_class_type (struct type *type, struct value *clas)
 {
-  value_ptr temp;
+  struct value *temp;
   char *unqualified_name;
   char *name = TYPE_TAG_NAME (type);
   int ninterfaces, nfields, nmethods;
   int type_is_object = 0;
   struct fn_field *fn_fields;
   struct fn_fieldlist *fn_fieldlists;
-  value_ptr fields, field, method, methods;
+  struct value *fields;
+  struct value *methods;
+  struct value *method = NULL;
+  struct value *field = NULL;
   int i, j;
   struct objfile *objfile = get_dynamics_objfile ();
   struct type *tsuper;
@@ -446,7 +444,7 @@ java_link_class_type (struct type *type, value_ptr clas)
       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"));
@@ -492,7 +490,7 @@ java_link_class_type (struct type *type, value_ptr 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));
@@ -517,7 +515,7 @@ java_link_class_type (struct type *type, value_ptr clas)
       /* 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, "<init>") == 0)
        mname = unqualified_name;
 
@@ -542,7 +540,7 @@ java_link_class_type (struct type *type, value_ptr clas)
            {                   /* 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,7 +561,7 @@ java_link_class_type (struct type *type, value_ptr clas)
 
   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,7 +575,7 @@ get_java_object_type (void)
   if (java_object_type == NULL)
     {
       struct symbol *sym;
-      sym = lookup_symbol ("java.lang.Object", NULL, STRUCT_NAMESPACE,
+      sym = lookup_symbol ("java.lang.Object", NULL, STRUCT_DOMAIN,
                           (int *) 0, (struct symtab **) NULL);
       if (sym == NULL)
        error ("cannot find java.lang.Object");
@@ -767,19 +765,6 @@ java_demangle_type_signature (char *signature)
   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. */
 
@@ -800,7 +785,7 @@ java_array_type (struct type *type, int dims)
 
 /* Create a Java string in the inferior from a (Utf8) literal. */
 
-static value_ptr
+static struct value *
 java_value_string (char *ptr, int len)
 {
   error ("not implemented - java_value_string");       /* FIXME */
@@ -843,15 +828,16 @@ java_emit_char (int c, struct ui_file *stream, int quoter)
     }
 }
 
-static value_ptr
-evaluate_subexp_java (struct type *expect_type, register struct expression *exp,
-                     register int *pos, enum noside noside)
+static struct value *
+evaluate_subexp_java (struct type *expect_type, struct expression *exp,
+                     int *pos, enum noside noside)
 {
   int pc = *pos;
   int i;
   char *name;
   enum exp_opcode op = exp->elts[*pos].opcode;
-  value_ptr arg1, arg2;
+  struct value *arg1;
+  struct value *arg2;
   struct type *type;
   switch (op)
     {
@@ -897,8 +883,8 @@ evaluate_subexp_java (struct type *expect_type, register struct expression *exp,
          struct type *el_type;
          char buf4[4];
 
-         value_ptr clas = java_class_from_object (arg1);
-         value_ptr temp = clas;
+         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");
@@ -909,7 +895,7 @@ evaluate_subexp_java (struct type *expect_type, register struct expression *exp,
 
          if (noside == EVAL_AVOID_SIDE_EFFECTS)
            return value_zero (el_type, VALUE_LVAL (arg1));
-         address = value_as_pointer (arg1);
+         address = value_as_address (arg1);
          address += JAVA_OBJECT_SIZE;
          read_memory (address, buf4, 4);
          length = (long) extract_signed_integer (buf4, 4);
@@ -986,6 +972,65 @@ java_create_fundamental_type (struct objfile *objfile, int typeid)
   return c_create_fundamental_type (objfile, typeid);
 }
 
+static char *java_demangle (const char *mangled, int options)
+{
+  return cplus_demangle (mangled, options | DMGL_JAVA);
+}
+
+/* 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)
+{
+  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;
+  int depth = 0;
+  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.  */
 
@@ -1026,6 +1071,15 @@ const struct op_print java_op_print_tab[] =
   {NULL, 0, 0, 0}
 };
 
+const struct exp_descriptor exp_descriptor_java = 
+{
+  print_subexp_standard,
+  operator_length_standard,
+  op_name_standard,
+  dump_subexp_body_standard,
+  evaluate_subexp_java
+};
+
 const struct language_defn java_language_defn =
 {
   "java",                      /* Language name */
@@ -1034,9 +1088,10 @@ const struct language_defn java_language_defn =
   range_check_off,
   type_check_off,
   case_sensitive_on,
+  &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 */
@@ -1044,6 +1099,12 @@ const struct language_defn java_language_defn =
   java_print_type,             /* Print a type 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 */
+  basic_lookup_symbol_nonlocal,        /* lookup_symbol_nonlocal */
+  basic_lookup_transparent_type,/* lookup_transparent_type */
+  java_demangle,               /* Language specific symbol demangler */
+  java_class_name_from_physname,/* Language specific class name */
   {"", "", "", ""},            /* Binary format info */
   {"0%lo", "0", "o", ""},      /* Octal format info */
   {"%ld", "", "d", ""},                /* Decimal format info */
@@ -1052,6 +1113,8 @@ const struct language_defn java_language_defn =
   0,                           /* not c-style arrays */
   0,                           /* String lower bound */
   &builtin_type_char,          /* Type of string elements */
+  default_word_break_characters,
+  NULL, /* FIXME: la_language_arch_info.  */
   LANG_MAGIC
 };
 
This page took 0.038315 seconds and 4 git commands to generate.