This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[gcjx] Patch: FYI: first work on verifier merge
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: 26 Mar 2005 19:40:31 -0700
- Subject: [gcjx] Patch: FYI: first work on verifier merge
- Reply-to: tromey at redhat dot com
I'm checking this in on the gcjx branch.
This is the first work toward having a single 'verify.cc' in the tree.
This removes the uses of std::string from the gcjx verifier, and it
includes an initial (and completely untested) verify.h for libjava.
Tom
Index: libjava/ChangeLog
from Tom Tromey <tromey@redhat.com>
* include/verify.h: New file.
Index: gcjx/ChangeLog
from Tom Tromey <tromey@redhat.com>
* bytecode/verify.cc (verify_fail): Take 'char*' argument.
(get_type_val_for_signature): Don't use std::string.
(verify_dimensions): Likewise.
(state::merge): Likewise.
(state::state_mergeable_p): Likewise.
(push_type): Likewise.
(compute_jump): Likewise.
(note_branch_target): Likewise.
(skip_padding): Likewise.
(branch_prepass): Likewise.
(check_pool_index): Likewise.
(verify_instructions_0): Likewise.
* verify.h (vfy_get_interface_count): Removed.
Index: gcjx/verify.h
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/Attic/verify.h,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 verify.h
--- gcjx/verify.h 27 Mar 2005 02:38:14 -0000 1.1.2.2
+++ gcjx/verify.h 27 Mar 2005 02:42:25 -0000
@@ -242,11 +242,6 @@
return iter == assert_cast<model_class *> (klass)->get_interfaces ().end ();
}
-inline int vfy_get_interface_count (vfy_jclass klass)
-{
- return assert_cast<model_class *> (klass)->get_interfaces ().size ();
-}
-
inline vfy_jclass vfy_get_interface (vfy_jclass, vfy_iface_iterator &iter)
{
return (*iter)->type ();
Index: gcjx/bytecode/verify.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/bytecode/Attic/verify.cc,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 verify.cc
--- gcjx/bytecode/verify.cc 27 Mar 2005 02:38:15 -0000 1.1.2.2
+++ gcjx/bytecode/verify.cc 27 Mar 2005 02:42:28 -0000
@@ -204,12 +204,11 @@
return val;
}
- __attribute__ ((__noreturn__)) void verify_fail (const std::string &s,
- jint pc = -1)
+ __attribute__ ((__noreturn__)) void verify_fail (const char *s, jint pc = -1)
{
if (pc == -1)
pc = start_PC;
- vfy_fail (s.c_str (), pc, current_class, current_method);
+ vfy_fail (s, pc, current_class, current_method);
}
// This enum holds a list of tags for all the different types we
@@ -483,8 +482,11 @@
rt = void_type;
break;
default:
- verify_fail (std::string () +
- "invalid character '" + sig + "' in signature");
+ {
+ char buf[50];
+ sprintf (buf, "invalid character '%c' in signature", char (sig));
+ verify_fail (buf);
+ }
}
return rt;
}
@@ -857,9 +859,13 @@
verifier->verify_fail ("internal error in type::verify_dimensions ()");
if (klass->count_dimensions () < ndims)
- verifier->verify_fail (std::string () + "array type has fewer "
- + "dimensions (" + klass->count_dimensions ()
- + ") than required (" + ndims + ")");
+ {
+ char buf[100];
+ sprintf (buf, "array type has fewer dimensions (%d) than "
+ "required (%d)", klass->count_dimensions (),
+ ndims);
+ verifier->verify_fail (buf);
+ }
}
// Merge OLD_TYPE into this. On error throw exception. Return
@@ -1090,8 +1096,12 @@
// Merge stacks.
if (state_old->stacktop != stacktop) // FIXME stackdepth instead?
- verifier->verify_fail (std::string () + "stack sizes differ: "
- + state_old->stacktop + " and " + stacktop);
+ {
+ char buf[30];
+ sprintf (buf, "stack sizes differ: %d and %d", state_old->stacktop,
+ stacktop);
+ verifier->verify_fail (buf);
+ }
for (int i = 0; i < state_old->stacktop; ++i)
{
if (stack[i].merge (state_old->stack[i], false, verifier))
@@ -1144,8 +1154,12 @@
// we've found two execution paths that reach a branch target
// with different stack depths. FIXME stackdepth instead?
if (stacktop != other->stacktop)
- verifier->verify_fail (std::string () + "stack sizes differ: "
- + stacktop + " and " + other->stacktop);
+ {
+ char buf[50];
+ sprintf (buf, "stack sizes differ: %d and %d", stacktop,
+ other->stacktop);
+ verifier->verify_fail (buf);
+ }
for (int i = 0; i < stacktop; ++i)
if (! stack[i].state_mergeable_p (other->stack[i]))
@@ -1244,10 +1258,13 @@
int depth = t.depth ();
if (current_state->stackdepth + depth > current_method->max_stack)
- verify_fail (std::string () + "stack overflow; "
- + "current depth=" +current_state->stackdepth + ", "
- + "max_stack=" + current_method->max_stack + ", "
- + "pushing " + depth);
+ {
+ char buf[100];
+ sprintf (buf, "stack overflow; current depth=%d, max_stack=%d, "
+ "pushing %d", current_state->stackdepth,
+ current_method->max_stack, depth);
+ verify_fail (buf);
+ }
current_state->stack[current_state->stacktop++] = t;
current_state->stackdepth += depth;
}
@@ -1351,9 +1368,12 @@
{
int npc = start_PC + offset;
if (npc < 0 || npc >= current_method->code_length)
- verify_fail (std::string () + "branch out of range: "
- + "destination=" + npc + ", "
- + "code_length=" + current_method->code_length, start_PC);
+ {
+ char buf[100];
+ sprintf (buf, "branch out of range: destination=%d, code_length=%d",
+ npc, current_method->code_length);
+ verify_fail (buf, start_PC);
+ }
return npc;
}
@@ -1473,9 +1493,11 @@
// fetching the target and we haven't yet checked the next
// instruction.
if (pc < PC && ! (flags[pc] & FLAG_INSN_START))
- verify_fail (std::string () + "branch to " + pc
- + " not to instruction start",
- start_PC);
+ {
+ char buf[30];
+ sprintf (buf, "branch to %d not to instruction start", pc);
+ verify_fail (buf, start_PC);
+ }
flags[pc] |= FLAG_BRANCH_TARGET;
}
@@ -1485,7 +1507,11 @@
{
jint b = get_byte ();
if (b != 0)
- verify_fail (std::string () + "found nonzero padding byte " + b);
+ {
+ char buf[30];
+ sprintf (buf, "found nonzero padding byte %d", b);
+ verify_fail (buf);
+ }
}
}
@@ -1801,10 +1827,12 @@
jint low = get_int ();
jint high = get_int ();
if (low > high)
- verify_fail (std::string ()
- + "invalid tableswitch: low=" + low + ", "
- + "high=" + high,
- start_PC);
+ {
+ char buf[50];
+ sprintf (buf, "invalid tableswitch: low=%d, high=%d",
+ low, high);
+ verify_fail (buf, start_PC);
+ }
for (int i = low; i <= high; ++i)
note_branch_target (compute_jump (get_int ()));
}
@@ -1908,8 +1936,11 @@
void check_pool_index (int index)
{
if (index < 0 || index >= vfy_get_constants_size (current_method))
- verify_fail (std::string () + "constant pool index "
- + index + " out of range", start_PC);
+ {
+ char buf[50];
+ sprintf (buf, "constant pool index %d out of range", index);
+ verify_fail (buf, start_PC);
+ }
}
type check_class_constant (int index)
@@ -2846,10 +2877,12 @@
nargs = get_byte ();
jint dummy_byte = get_byte ();
if (dummy_byte != 0)
- verify_fail (std::string ()
- + "invokeinterface dummy byte is "
- + dummy_byte
- + " instead of 0");
+ {
+ char buf[50];
+ sprintf (buf, "invokeinterface dummy byte is %d "
+ "instead of 0", dummy_byte);
+ verify_fail (buf);
+ }
}
bool is_init = false;
@@ -2905,9 +2938,14 @@
vfy_jclass klass = class_type.klass->getclass (this);
if (! vfy_has_method (klass, method_name, method_descriptor))
- verify_fail (std::string () + "method '" + method_name + "' "
- + "with descriptor '" + method_descriptor + "' "
- + "not found");
+ {
+ const char *mn = vfy_string_bytes (method_name);
+ const char *md = vfy_string_bytes (method_descriptor);
+ char buf[50 + strlen (mn) + strlen (md)];
+ sprintf (buf, "method '%s' with descriptor '%s' not found",
+ mn, md);
+ verify_fail (buf);
+ }
}
break;
@@ -3015,9 +3053,12 @@
type atype = check_class_constant (get_ushort ());
int dim = get_byte ();
if (dim < 1)
- verify_fail (std::string ()
- + "too few dimensions to multianewarray: " + dim,
- start_PC);
+ {
+ char buf[50];
+ sprintf (buf, "too few dimensions to multianewarray: %d",
+ dim);
+ verify_fail (buf, start_PC);
+ }
atype.verify_dimensions (dim, this);
for (int i = 0; i < dim; ++i)
pop_type (int_type);
Index: libjava/include/verify.h
===================================================================
RCS file: libjava/include/verify.h
diff -N libjava/include/verify.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libjava/include/verify.h 27 Mar 2005 02:42:32 -0000
@@ -0,0 +1,356 @@
+/* Declarations to interface libgcj with bytecode verifier.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+gcjx is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+gcjx 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with gcjx; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Java and all Java-based marks are trademarks or registered trademarks
+of Sun Microsystems, Inc. in the United States and other countries.
+The Free Software Foundation is independent of Sun Microsystems, Inc. */
+
+// This is glue between libjava and the verifier.
+
+#ifndef JV_VERIFY_H
+#define JV_VERIFY_H
+
+#include "java-cpool.h"
+#include "java/lang/Class.h"
+
+typedef _Jv_Constants *vfy_constants;
+
+typedef _Jv_Utf8Const *vfy_string;
+
+typedef jclass vfy_jclass;
+
+typedef jchar vfy_uint_16;
+
+typedef _Jv_InterpException vfy_exception;
+
+typedef _Jv_InterpMethod vfy_method;
+
+inline vfy_constants *vfy_get_constants (vfy_method *method)
+{
+ return &method->defining_class->constants;
+}
+
+inline void *vfy_alloc (size_t bytes)
+{
+ return _Jv_Malloc (bytes);
+}
+
+inline void vfy_free (void *mem)
+{
+ _Jv_Free (mem);
+}
+
+inline bool vfy_strings_equal (vfy_string one, vfy_string two)
+{
+ return _Jv_equalUtf8Consts (one, two);
+}
+
+inline const char *vfy_string_bytes (vfy_string str)
+{
+ return str->chars();
+}
+
+inline vfy_string vfy_init_name (void)
+{
+ return gcj::init_name;
+}
+
+inline vfy_string vfy_clinit_name (void)
+{
+ return gcj:clinit_name;
+}
+
+int vfy_count_arguments (vfy_string signature)
+{
+ return _Jv_count_arguments (signature, false);
+}
+
+inline vfy_string vfy_get_signature (vfy_method *method)
+{
+ return method->self->signature;
+}
+
+inline vfy_string vfy_get_method_name (vfy_method *method)
+{
+ return method->self->name;
+}
+
+inline bool vfy_is_static (vfy_method *method)
+{
+ return (method->self->accflags & ACC_STATIC) != 0;
+}
+
+inline const unsigned char *vfy_get_bytecode (vfy_method *method)
+{
+ return method->bytecode ();
+}
+
+inline vfy_exception *vfy_get_exceptions (vfy_method *method)
+{
+ return method->block->get_exceptions ();
+}
+
+inline void vfy_get_exception (vfy_exception *table, int index, int *handler,
+ int *start, int *end, int *handler_type)
+{
+ *handler = table[index].handler_pc.i;
+ *start = table[index].start_pc.i;
+ *end = table[index].end_pc.i;
+ *handler_type = table[index].handler_type.i;
+}
+
+inline int vfy_tag (vfy_constants *pool, int index)
+{
+ return pool->tag[index];
+}
+
+inline void vfy_load_indexes (vfy_constants *pool, int index,
+ vfy_uint_16 *index0, vfy_uint_16 *index1)
+{
+ _Jv_loadIndexes (pool->data, *index0, *index1);
+}
+
+inline int vfy_get_constants_size (vfy_method *method)
+{
+ return method->defining_class->constants.size;
+}
+
+inline vfy_string vfy_get_pool_string (vfy_constants *pool, int index)
+{
+ return pool->data[index].utf8;
+}
+
+inline vfy_jclass vfy_find_class (vfy_method *method, vfy_jclass context,
+ vfy_string name)
+{
+ using namespace java::lang;
+ ClassLoader *loader = context->getClassLoaderInternal();
+ // We might see either kind of name. Sigh.
+ vfy_jclass klass;
+ if (name->first() == 'L' && name->limit()[-1] == ';')
+ klass = _Jv_FindClassFromSignature (name->chars(), loader);
+ else
+ klass = Class::forName (_Jv_NewStringUtf8Const (name), false, loader);
+ return klass;
+}
+
+/**
+ * Tests whether class k has a method with a given name and descriptor. Most
+ * verifiers don't check this, so implementations are free to simply return
+ * true regardless, and report the problem later with a NoSuchMethodException
+ * at runtime or whatever. gjcx can use this to check the bytecode it emits.
+ */
+inline bool vfy_has_method (vfy_jclass k, vfy_string method_name,
+ vfy_string method_descriptor)
+{
+ for (int i = 0; i < k->method_count; ++i)
+ {
+ if (_Jv_equalUtf8Consts (k->methods[i].name, method_name)
+ && _Jv_equalUtf8Consts (k->methods[i].signature, method_descriptor))
+ return true;
+ }
+ return false;
+}
+
+inline vfy_jclass vfy_get_pool_resolved_class (vfy_method *method,
+ vfy_constants *pool,
+ int index)
+{
+ return vfy_find_class (method, method->declaring_class,
+ pool->data[index].utf8);
+}
+
+inline vfy_string vfy_get_pool_class (vfy_method *method, vfy_constants *pool,
+ int index)
+{
+ // FIXME: is pool linked at this point?
+ return pool->data[index].utf8;
+}
+
+// Return true if the class declares a field with the given name. The
+// type of the field doesn't matter.
+inline bool vfy_class_has_field_p (vfy_jclass type, vfy_string name)
+{
+ for (int i = 0; i < type->field_count; ++i)
+ {
+ if (_Jv_equalUtf8Consts (type->fields[i].name, name))
+ return true;
+ }
+ return false;
+}
+
+inline vfy_string vfy_make_string (const char *s, int len)
+{
+ return _Jv_makeUtf8Const (s, len);
+}
+
+inline vfy_string vfy_get_class_name (vfy_jclass klass)
+{
+ return klass->name;
+}
+
+inline char vfy_get_primitive_char (vfy_jclass klass)
+{
+ return char (klass->method_count);
+}
+
+
+typedef int vfy_iface_iterator;
+
+inline vfy_iface_iterator vfy_iface_iterator_begin (vfy_jclass klass)
+{
+ return 0;
+}
+
+inline bool vfy_iface_iterator_done (vfy_jclass klass, vfy_iface_iterator iter)
+{
+ return iter == klass->interface_count;
+}
+
+inline vfy_jclass vfy_get_interface (vfy_jclass klass, vfy_iface_iterator iter)
+{
+ return klass->interface_count;
+}
+
+inline bool vfy_is_array (vfy_jclass klass)
+{
+ return klass->isArray ();
+}
+
+inline bool vfy_is_interface (vfy_jclass klass)
+{
+ return klass->isInterface ();
+}
+
+// FIXME: what to do for void?
+inline bool vfy_is_primitive (vfy_jclass klass)
+{
+ return klass->isPrimitive ();
+}
+
+inline vfy_jclass vfy_get_superclass (vfy_jclass klass)
+{
+ return klass->getSuperclass ();
+}
+
+inline vfy_jclass vfy_get_array_class (vfy_jclass klass)
+{
+ return _Jv_GetArrayClass (klass, klass->getClassLoaderInternal ());
+}
+
+inline vfy_jclass vfy_get_component_type (vfy_jclass klass)
+{
+ return klass->getComponentType ();
+}
+
+inline bool vfy_is_abstract (vfy_jclass klass)
+{
+ return (klass->getModifiers () & ACC_ABSTRACT) != 0;
+}
+
+inline vfy_jclass vfy_object_type (void)
+{
+ return &java::lang::Object::class$
+}
+
+inline vfy_jclass vfy_string_type (void)
+{
+ return &java::lang::String::class$
+}
+
+inline vfy_jclass vfy_throwable_type (void)
+{
+ return &java::lang::Throwable::class$
+}
+
+inline vfy_jclass vfy_class_type (void)
+{
+ return &java::lang::Class::class$
+}
+
+__attribute__ ((__noreturn__))
+inline int vfy_fail (const char *message, int pc, vfy_jclass,
+ vfy_method *method)
+{
+ using namespace java::lang;
+ StringBuffer *buf = new StringBuffer ();
+
+ buf->append (JvNewStringLatin1 ("verification failed"));
+ if (pc != -1)
+ {
+ buf->append (JvNewStringLatin1 (" at PC "));
+ buf->append (pc);
+ }
+
+ buf->append (JvNewStringLatin1 (" in method "));
+ buf->append (current_class->getName());
+ buf->append ((jchar) '.');
+ buf->append (method->get_method()->name->toString());
+ buf->append ((jchar) '(');
+ buf->append (method->get_method()->signature->toString());
+ buf->append ((jchar) ')');
+
+ buf->append (JvNewStringLatin1 (": "));
+ buf->append (JvNewStringLatin1 (message));
+ throw new java::lang::VerifyError (buf->toString ());
+}
+
+inline void vfy_notify_verified (int pc)
+{
+ // In libgcj, do nothing.
+}
+
+// Return the primitive type corresponding to the argument to
+// `newarray'.
+inline vfy_jclass vfy_get_primitive_type (int type)
+{
+ switch (type)
+ {
+ case 4:
+ return JvPrimClass (boolean);
+ case 5:
+ return JvPrimClass (char);
+ case 6:
+ return JvPrimClass (float);
+ case 7:
+ return JvPrimClass (double);
+ case 8:
+ return JvPrimClass (byte);
+ case 9:
+ return JvPrimClass (short);
+ case 10:
+ return JvPrimClass (int);
+ case 11:
+ return JvPrimClass (long);
+ }
+ return NULL;
+}
+
+// Return true if this method comes from a 1.5 class file.
+inline bool vfy_is_15 (vfy_method *method)
+{
+ return false; /* FIXME */
+}
+
+#define VFY_PRIMITIVE_CLASS(name) JvPrimClass (name)
+
+extern void _Jv_VerifyMethod (vfy_method *meth);
+
+#endif // JV_VERIFY_H