static struct value * evaluate_subexp_java (struct type *expect_type, struct expression *exp, int *pos, enum noside noside) { int pc = *pos; int i; const char *name; enum exp_opcode op = exp->elts[*pos].opcode; struct value *arg1; struct value *arg2; struct type *type; switch (op) { case UNOP_IND: if (noside == EVAL_SKIP) goto standard; (*pos)++; arg1 = evaluate_subexp_java (NULL_TYPE, exp, pos, EVAL_NORMAL); if (is_object_type (value_type (arg1))) { struct type *type; type = type_from_class (exp->gdbarch, java_class_from_object (arg1)); arg1 = value_cast (lookup_pointer_type (type), arg1); } return value_ind (arg1); case BINOP_SUBSCRIPT: (*pos)++; arg1 = evaluate_subexp_with_coercion (exp, pos, noside); arg2 = evaluate_subexp_with_coercion (exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; /* If the user attempts to subscript something that is not an array or pointer type (like a plain int variable for example), then report this as an error. */ 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); if (name == NULL) name = TYPE_TAG_NAME (type); i = name == NULL ? 0 : strlen (name); 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; 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"); 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 += get_java_object_header_size (exp->gdbarch); read_memory (address, 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)"), index, length); address = (address + 4) + index * TYPE_LENGTH (el_type); 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, value_as_long (arg2)); } if (name) error (_("cannot subscript something of type `%s'"), name); else error (_("cannot subscript requested type")); case OP_STRING: (*pos)++; i = longest_to_int (exp->elts[pc + 1].longconst); (*pos) += 3 + BYTES_TO_EXP_ELEM (i + 1); if (noside == EVAL_SKIP) goto nosideret; return java_value_string (&exp->elts[pc + 2].string, i); 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) arg1 = value_addr (arg1); return arg1; default: break; } standard: return evaluate_subexp_standard (expect_type, exp, pos, noside); nosideret: return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1); }
static struct type * java_link_class_type (struct gdbarch *gdbarch, struct type *type, struct value *clas) { struct value *temp; const char *unqualified_name; const 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; struct value *fields; struct value *methods; struct value *method = NULL; struct value *field = NULL; int i, j; 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 (strcmp (name, "java.lang.Object") == 0) { tsuper = get_java_object_type (); if (tsuper && TYPE_CODE (tsuper) == TYPE_CODE_PTR) tsuper = TYPE_TARGET_TYPE (tsuper); type_is_object = 1; } else tsuper = type_from_class (gdbarch, temp); #if 1 ninterfaces = 0; #else temp = clas; ninterfaces = value_as_long (value_struct_elt (&temp, NULL, "interface_len", NULL, "structure")); #endif TYPE_N_BASECLASSES (type) = (tsuper == NULL ? 0 : 1) + ninterfaces; temp = clas; nfields = value_as_long (value_struct_elt (&temp, NULL, "field_count", NULL, "structure")); nfields += TYPE_N_BASECLASSES (type); nfields++; /* Add one for dummy "class" field. */ TYPE_NFIELDS (type) = nfields; TYPE_FIELDS (type) = (struct field *) TYPE_ALLOC (type, sizeof (struct field) * nfields); memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields); TYPE_FIELD_PRIVATE_BITS (type) = (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields); TYPE_FIELD_PROTECTED_BITS (type) = (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields); TYPE_FIELD_IGNORE_BITS (type) = (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields)); B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields); TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) TYPE_ALLOC (type, B_BYTES (TYPE_N_BASECLASSES (type))); B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type)); if (tsuper != NULL) { TYPE_BASECLASS (type, 0) = tsuper; if (type_is_object) SET_TYPE_FIELD_PRIVATE (type, 0); } i = strlen (name); if (i > 2 && name[i - 1] == ']' && tsuper != NULL) { /* FIXME */ TYPE_LENGTH (type) = TYPE_LENGTH (tsuper) + 4; /* size with "length" */ } else { temp = clas; temp = value_struct_elt (&temp, NULL, "size_in_bytes", NULL, "structure"); TYPE_LENGTH (type) = value_as_long (temp); } fields = NULL; nfields--; /* First set up dummy "class" field. */ SET_FIELD_PHYSADDR (TYPE_FIELD (type, nfields), value_address (clas)); TYPE_FIELD_NAME (type, nfields) = "class"; 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; fields = value_struct_elt (&temp, NULL, "fields", NULL, "structure"); field = value_ind (fields); } else { /* Re-use field value for next field. */ 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->objfile_obstack, temp); temp = field; accflags = value_as_long (value_struct_elt (&temp, NULL, "accflags", NULL, "structure")); temp = field; temp = value_struct_elt (&temp, NULL, "info", NULL, "structure"); boffset = value_as_long (value_struct_elt (&temp, NULL, "boffset", NULL, "structure")); if (accflags & 0x0001) /* public access */ { /* ??? */ } if (accflags & 0x0002) /* private access */ { SET_TYPE_FIELD_PRIVATE (type, i); } if (accflags & 0x0004) /* protected access */ { SET_TYPE_FIELD_PROTECTED (type, i); } if (accflags & 0x0008) /* ACC_STATIC */ SET_FIELD_PHYSADDR (TYPE_FIELD (type, i), boffset); else SET_FIELD_BITPOS (TYPE_FIELD (type, i), 8 * boffset); if (accflags & 0x8000) /* FIELD_UNRESOLVED_FLAG */ { TYPE_FIELD_TYPE (type, i) = get_java_object_type (); /* FIXME */ } else { struct type *ftype; temp = field; temp = value_struct_elt (&temp, NULL, "type", NULL, "structure"); ftype = type_from_class (gdbarch, temp); if (TYPE_CODE (ftype) == TYPE_CODE_STRUCT) ftype = lookup_pointer_type (ftype); TYPE_FIELD_TYPE (type, i) = ftype; } } temp = clas; nmethods = value_as_long (value_struct_elt (&temp, NULL, "method_count", NULL, "structure")); j = nmethods * sizeof (struct fn_field); fn_fields = (struct fn_field *) obstack_alloc (&objfile->objfile_obstack, j); memset (fn_fields, 0, j); fn_fieldlists = (struct fn_fieldlist *) alloca (nmethods * sizeof (struct fn_fieldlist)); methods = NULL; for (i = 0; i < nmethods; i++) { const char *mname; int k; if (methods == NULL) { temp = clas; methods = value_struct_elt (&temp, NULL, "methods", NULL, "structure"); method = value_ind (methods); } else { /* Re-use method value for next method. */ 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->objfile_obstack, temp); if (strcmp (mname, "<init>") == 0) mname = unqualified_name; /* Check for an existing method with the same name. * This makes building the fn_fieldslists an O(nmethods**2) * operation. That could be using hashing, but I doubt it * is worth it. Note that we do maintain the order of methods * in the inferior's Method table (as long as that is grouped * by method name), which I think is desirable. --PB */ for (k = 0, j = TYPE_NFN_FIELDS (type);;) { if (--j < 0) { /* No match - new method name. */ j = TYPE_NFN_FIELDS (type)++; fn_fieldlists[j].name = mname; fn_fieldlists[j].length = 1; fn_fieldlists[j].fn_fields = &fn_fields[i]; k = i; break; } 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->objfile_obstack, mname); mname = fn_fieldlists[j].name; fn_fieldlists[j].length++; k = i - k; /* Index of new slot. */ /* Shift intervening fn_fields (between k and i) down. */ for (l = i; l > k; l--) fn_fields[l] = fn_fields[l - 1]; for (l = TYPE_NFN_FIELDS (type); --l > j;) fn_fieldlists[l].fn_fields++; break; } k += fn_fieldlists[j].length; } fn_fields[k].physname = ""; fn_fields[k].is_stub = 1; /* 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 (&objfile->objfile_obstack, j); memcpy (TYPE_FN_FIELDLISTS (type), fn_fieldlists, j); return type; }
int java_value_print (struct value *val, struct ui_file *stream, const struct value_print_options *options) { struct gdbarch *gdbarch = get_type_arch (value_type (val)); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct type *type; CORE_ADDR address; int i; char *name; struct value_print_options opts; type = value_type (val); address = value_address (val); if (is_object_type (type)) { CORE_ADDR obj_addr; /* Get the run-time type, and cast the object into that */ obj_addr = unpack_pointer (type, value_contents (val)); if (obj_addr != 0) { type = type_from_class (gdbarch, java_class_from_object (val)); type = lookup_pointer_type (type); val = value_at (type, address); } } if (TYPE_CODE (type) == TYPE_CODE_PTR && !value_logical_not (val)) type_print (TYPE_TARGET_TYPE (type), "", stream, -1); name = TYPE_TAG_NAME (type); if (TYPE_CODE (type) == TYPE_CODE_STRUCT && name != NULL && (i = strlen (name), name[i - 1] == ']')) { gdb_byte buf4[4]; long length; unsigned int things_printed = 0; int reps; struct type *el_type = java_primitive_type_from_name (gdbarch, name, i - 2); i = 0; read_memory (address + get_java_object_header_size (gdbarch), buf4, 4); length = (long) extract_signed_integer (buf4, 4, byte_order); fprintf_filtered (stream, "{length: %ld", length); if (el_type == NULL) { CORE_ADDR element; CORE_ADDR next_element = -1; /* dummy initial value */ /* Skip object header and length. */ address += get_java_object_header_size (gdbarch) + 4; while (i < length && things_printed < options->print_max) { gdb_byte *buf; buf = alloca (gdbarch_ptr_bit (gdbarch) / HOST_CHAR_BIT); fputs_filtered (", ", stream); wrap_here (n_spaces (2)); if (i > 0) element = next_element; else { read_memory (address, buf, sizeof (buf)); address += gdbarch_ptr_bit (gdbarch) / HOST_CHAR_BIT; /* FIXME: cagney/2003-05-24: Bogus or what. It pulls a host sized pointer out of the target and then extracts that as an address (while assuming that the address is unsigned)! */ element = extract_unsigned_integer (buf, sizeof (buf), byte_order); } for (reps = 1; i + reps < length; reps++) { read_memory (address, buf, sizeof (buf)); address += gdbarch_ptr_bit (gdbarch) / HOST_CHAR_BIT; /* FIXME: cagney/2003-05-24: Bogus or what. It pulls a host sized pointer out of the target and then extracts that as an address (while assuming that the address is unsigned)! */ next_element = extract_unsigned_integer (buf, sizeof (buf), byte_order); if (next_element != element) break; } if (reps == 1) fprintf_filtered (stream, "%d: ", i); else fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1); if (element == 0) fprintf_filtered (stream, "null"); else fprintf_filtered (stream, "@%s", paddress (gdbarch, element)); things_printed++; i += reps; } } else { struct value *v = allocate_value (el_type); struct value *next_v = allocate_value (el_type); set_value_address (v, (address + get_java_object_header_size (gdbarch) + 4)); set_value_address (next_v, value_raw_address (v)); while (i < length && things_printed < options->print_max) { fputs_filtered (", ", stream); wrap_here (n_spaces (2)); if (i > 0) { struct value *tmp; tmp = next_v; next_v = v; v = tmp; } else { set_value_lazy (v, 1); set_value_offset (v, 0); } set_value_offset (next_v, value_offset (v)); for (reps = 1; i + reps < length; reps++) { set_value_lazy (next_v, 1); set_value_offset (next_v, value_offset (next_v) + TYPE_LENGTH (el_type)); if (memcmp (value_contents (v), value_contents (next_v), TYPE_LENGTH (el_type)) != 0) break; } if (reps == 1) fprintf_filtered (stream, "%d: ", i); else fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1); opts = *options; opts.deref_ref = 1; common_val_print (v, stream, 1, &opts, current_language); things_printed++; i += reps; } } if (i < length) fprintf_filtered (stream, "..."); fprintf_filtered (stream, "}"); return 0; } /* If it's type String, print it */ if (TYPE_CODE (type) == TYPE_CODE_PTR && TYPE_TARGET_TYPE (type) && TYPE_TAG_NAME (TYPE_TARGET_TYPE (type)) && strcmp (TYPE_TAG_NAME (TYPE_TARGET_TYPE (type)), "java.lang.String") == 0 && (options->format == 0 || options->format == 's') && address != 0 && value_as_address (val) != 0) { struct type *char_type; struct value *data_val; CORE_ADDR data; struct value *boffset_val; unsigned long boffset; struct value *count_val; unsigned long count; struct value *mark; mark = value_mark (); /* Remember start of new values */ data_val = value_struct_elt (&val, NULL, "data", NULL, NULL); data = value_as_address (data_val); boffset_val = value_struct_elt (&val, NULL, "boffset", NULL, NULL); boffset = value_as_address (boffset_val); count_val = value_struct_elt (&val, NULL, "count", NULL, NULL); count = value_as_address (count_val); value_free_to_mark (mark); /* Release unnecessary values */ char_type = builtin_java_type (gdbarch)->builtin_char; val_print_string (char_type, data + boffset, count, stream, options); return 0; } opts = *options; opts.deref_ref = 1; return common_val_print (val, stream, 0, &opts, current_language); }
struct type * type_from_class (struct gdbarch *gdbarch, struct value *clas) { struct type *type; char *name; struct value *temp; struct objfile *objfile; struct value *utf8_name; char *nptr; CORE_ADDR addr; 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); 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 (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->objfile_obstack, utf8_name); for (nptr = name; *nptr != 0; nptr++) { if (*nptr == '/') *nptr = '.'; } type = java_lookup_class (name); if (type != NULL) return type; type = alloc_type (objfile); TYPE_CODE (type) = TYPE_CODE_STRUCT; INIT_CPLUS_SPECIFIC (type); if (name[0] == '[') { char *signature = name; int namelen = java_demangled_signature_length (signature); if (namelen > strlen (name)) name = obstack_alloc (&objfile->objfile_obstack, namelen + 1); java_demangled_signature_copy (name, signature); name[namelen] = '\0'; temp = clas; /* Set array element type. */ temp = value_struct_elt (&temp, NULL, "methods", NULL, "structure"); 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 (gdbarch, type, clas); }
int java_value_print (struct value *val, struct ui_file *stream, int format, enum val_prettyprint pretty) { struct type *type; CORE_ADDR address; int i; char *name; type = VALUE_TYPE (val); address = VALUE_ADDRESS (val) + VALUE_OFFSET (val); if (is_object_type (type)) { CORE_ADDR obj_addr; /* Get the run-time type, and cast the object into that */ obj_addr = unpack_pointer (type, VALUE_CONTENTS (val)); if (obj_addr != 0) { type = type_from_class (java_class_from_object (val)); type = lookup_pointer_type (type); val = value_at (type, address, NULL); } } if (TYPE_CODE (type) == TYPE_CODE_PTR && !value_logical_not (val)) type_print (TYPE_TARGET_TYPE (type), "", stream, -1); name = TYPE_TAG_NAME (type); if (TYPE_CODE (type) == TYPE_CODE_STRUCT && name != NULL && (i = strlen (name), name[i - 1] == ']')) { char buf4[4]; long length; unsigned int things_printed = 0; int reps; struct type *el_type = java_primitive_type_from_name (name, i - 2); i = 0; read_memory (address + JAVA_OBJECT_SIZE, buf4, 4); length = (long) extract_signed_integer (buf4, 4); fprintf_filtered (stream, "{length: %ld", length); if (el_type == NULL) { CORE_ADDR element; CORE_ADDR next_element = -1; /* dummy initial value */ address += JAVA_OBJECT_SIZE + 4; /* Skip object header and length. */ while (i < length && things_printed < print_max) { char *buf; buf = alloca (TARGET_PTR_BIT / HOST_CHAR_BIT); fputs_filtered (", ", stream); wrap_here (n_spaces (2)); if (i > 0) element = next_element; else { read_memory (address, buf, sizeof (buf)); address += TARGET_PTR_BIT / HOST_CHAR_BIT; element = extract_address (buf, sizeof (buf)); } for (reps = 1; i + reps < length; reps++) { read_memory (address, buf, sizeof (buf)); address += TARGET_PTR_BIT / HOST_CHAR_BIT; next_element = extract_address (buf, sizeof (buf)); if (next_element != element) break; } if (reps == 1) fprintf_filtered (stream, "%d: ", i); else fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1); if (element == 0) fprintf_filtered (stream, "null"); else fprintf_filtered (stream, "@%s", paddr_nz (element)); things_printed++; i += reps; } } else { struct value *v = allocate_value (el_type); struct value *next_v = allocate_value (el_type); VALUE_ADDRESS (v) = address + JAVA_OBJECT_SIZE + 4; VALUE_ADDRESS (next_v) = VALUE_ADDRESS (v); while (i < length && things_printed < print_max) { fputs_filtered (", ", stream); wrap_here (n_spaces (2)); if (i > 0) { struct value *tmp; tmp = next_v; next_v = v; v = tmp; } else { VALUE_LAZY (v) = 1; VALUE_OFFSET (v) = 0; } VALUE_OFFSET (next_v) = VALUE_OFFSET (v); for (reps = 1; i + reps < length; reps++) { VALUE_LAZY (next_v) = 1; VALUE_OFFSET (next_v) += TYPE_LENGTH (el_type); if (memcmp (VALUE_CONTENTS (v), VALUE_CONTENTS (next_v), TYPE_LENGTH (el_type)) != 0) break; } if (reps == 1) fprintf_filtered (stream, "%d: ", i); else fprintf_filtered (stream, "%d..%d: ", i, i + reps - 1); val_print (VALUE_TYPE (v), VALUE_CONTENTS (v), 0, 0, stream, format, 2, 1, pretty); things_printed++; i += reps; } } if (i < length) fprintf_filtered (stream, "..."); fprintf_filtered (stream, "}"); return 0; } /* If it's type String, print it */ if (TYPE_CODE (type) == TYPE_CODE_PTR && TYPE_TARGET_TYPE (type) && TYPE_NAME (TYPE_TARGET_TYPE (type)) && strcmp (TYPE_NAME (TYPE_TARGET_TYPE (type)), "java.lang.String") == 0 && (format == 0 || format == 's') && address != 0 && value_as_address (val) != 0) { struct value *data_val; CORE_ADDR data; struct value *boffset_val; unsigned long boffset; struct value *count_val; unsigned long count; struct value *mark; mark = value_mark (); /* Remember start of new values */ data_val = value_struct_elt (&val, NULL, "data", NULL, NULL); data = value_as_address (data_val); boffset_val = value_struct_elt (&val, NULL, "boffset", NULL, NULL); boffset = value_as_address (boffset_val); count_val = value_struct_elt (&val, NULL, "count", NULL, NULL); count = value_as_address (count_val); value_free_to_mark (mark); /* Release unnecessary values */ val_print_string (data + boffset, count, 2, stream); return 0; } return (val_print (type, VALUE_CONTENTS (val), 0, address, stream, format, 1, 0, pretty)); }