mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-24 19:33:59 +08:00
defineclass.cc (_Jv_ClassReader::read_one_code_attribute): Added LocalVariableTable attribute handling.
2007-02-15 Kyle Galloway <kgallowa@redhat.com> * defineclass.cc (_Jv_ClassReader::read_one_code_attribute): Added LocalVariableTable attribute handling. (_Jv_ClassReader::pool_Utf8_to_char_arr): New method. * jvmti.cc (_Jv_JVMTI_GetLocalVariableTable): New method. * include/java-interp.h: Added local_var_table and local_var_table_len fields to _Jv_InterpMethod. (_Jv_InterpMethod::get_local_var_table): New method. * testsuite/libjava.jvmti/interp/getlocalvartable.java: New test. * testsuite/libjava.jvmti/interp/getlocalvartable.jar: New test. * testsuite/libjava.jvmti/interp/getlocalvartable.out: Output for new test. * testsuite/libjava.jvmti/interp/getlocalvartable.h: New test. * testsuite/libjava.jvmti/interp/natgetlocalvartable.cc: New test. From-SVN: r121999
This commit is contained in:
parent
ed765125f2
commit
fe60528edc
@ -1,3 +1,21 @@
|
||||
2007-02-15 Kyle Galloway <kgallowa@redhat.com>
|
||||
|
||||
* defineclass.cc (_Jv_ClassReader::read_one_code_attribute):
|
||||
Added LocalVariableTable attribute handling.
|
||||
(_Jv_ClassReader::pool_Utf8_to_char_arr): New method.
|
||||
* jvmti.cc (_Jv_JVMTI_GetLocalVariableTable): New method.
|
||||
* include/java-interp.h: Added local_var_table and
|
||||
local_var_table_len fields to _Jv_InterpMethod.
|
||||
(_Jv_InterpMethod::get_local_var_table): New method.
|
||||
* testsuite/libjava.jvmti/interp/getlocalvartable.java: New
|
||||
test.
|
||||
* testsuite/libjava.jvmti/interp/getlocalvartable.jar: New test.
|
||||
* testsuite/libjava.jvmti/interp/getlocalvartable.out: Output
|
||||
for new test.
|
||||
* testsuite/libjava.jvmti/interp/getlocalvartable.h: New test.
|
||||
* testsuite/libjava.jvmti/interp/natgetlocalvartable.cc: New
|
||||
test.
|
||||
|
||||
2007-02-15 Kyle Galloway <kgallowa@redhat.com>
|
||||
|
||||
* gnu/classpath/jdwp/natVMVirtualMachine (getFrames): Implement.
|
||||
|
@ -299,6 +299,9 @@ struct _Jv_ClassReader
|
||||
|
||||
/** check an utf8 entry, without creating a Utf8Const object */
|
||||
bool is_attribute_name (int index, const char *name);
|
||||
|
||||
/** return the value of a utf8 entry in the passed array */
|
||||
int pool_Utf8_to_char_arr (int index, char **entry);
|
||||
|
||||
/** here goes the class-loader members defined out-of-line */
|
||||
void handleConstantPool ();
|
||||
@ -784,6 +787,18 @@ _Jv_ClassReader::is_attribute_name (int index, const char *name)
|
||||
return !memcmp (bytes+offsets[index]+2, name, len);
|
||||
}
|
||||
|
||||
// Get a UTF8 value from the constant pool and turn it into a garbage
|
||||
// collected char array.
|
||||
int _Jv_ClassReader::pool_Utf8_to_char_arr (int index, char** entry)
|
||||
{
|
||||
check_tag (index, JV_CONSTANT_Utf8);
|
||||
int len = get2u (bytes + offsets[index]);
|
||||
*entry = reinterpret_cast<char *> (_Jv_AllocBytes (len + 1));
|
||||
(*entry)[len] = '\0';
|
||||
memcpy (*entry, bytes + offsets[index] + 2, len);
|
||||
return len + 1;
|
||||
}
|
||||
|
||||
void _Jv_ClassReader::read_one_field_attribute (int field_index,
|
||||
bool *found_value)
|
||||
{
|
||||
@ -979,6 +994,34 @@ void _Jv_ClassReader::read_one_code_attribute (int method_index)
|
||||
method->line_table_len = table_len;
|
||||
method->line_table = table;
|
||||
}
|
||||
else if (is_attribute_name (name, "LocalVariableTable"))
|
||||
{
|
||||
_Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
|
||||
(def_interp->interpreted_methods[method_index]);
|
||||
if (method->local_var_table != NULL)
|
||||
throw_class_format_error ("Method already has LocalVariableTable");
|
||||
|
||||
int table_len = read2u ();
|
||||
_Jv_LocalVarTableEntry *table
|
||||
= reinterpret_cast<_Jv_LocalVarTableEntry *>
|
||||
(_Jv_AllocRawObj (table_len * sizeof (_Jv_LocalVarTableEntry)));
|
||||
|
||||
for (int i = 0; i < table_len; i++)
|
||||
{
|
||||
table[i].bytecode_start_pc = read2u ();
|
||||
table[i].length = read2u ();
|
||||
int len;
|
||||
len = pool_Utf8_to_char_arr (read2u (), &table[i].name);
|
||||
len = pool_Utf8_to_char_arr (read2u (), &table[i].descriptor);
|
||||
table[i].slot = read2u ();
|
||||
|
||||
if (table[i].slot > method->max_locals || table[i].slot < 0)
|
||||
throw_class_format_error ("Malformed Local Variable Table: Invalid Slot");
|
||||
}
|
||||
|
||||
method->local_var_table_len = table_len;
|
||||
method->local_var_table = table;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ignore unknown code attributes */
|
||||
|
@ -137,6 +137,21 @@ struct _Jv_LineTableEntry
|
||||
int line;
|
||||
};
|
||||
|
||||
// This structure holds local variable information.
|
||||
// The pc value is the first pc where the variable must have a value and it
|
||||
// must continue to have a value until (start_pc + length).
|
||||
// The name is the variable name, and the descriptor contains type information.
|
||||
// The slot is the index in the local variable array of this method, long and
|
||||
// double occupy slot and slot+1.
|
||||
struct _Jv_LocalVarTableEntry
|
||||
{
|
||||
int bytecode_start_pc;
|
||||
int length;
|
||||
char *name;
|
||||
char *descriptor;
|
||||
int slot;
|
||||
};
|
||||
|
||||
class _Jv_InterpMethod : public _Jv_MethodBase
|
||||
{
|
||||
// Breakpoint instruction
|
||||
@ -157,6 +172,10 @@ class _Jv_InterpMethod : public _Jv_MethodBase
|
||||
// Length of the line_table - when this is zero then line_table is NULL.
|
||||
int line_table_len;
|
||||
_Jv_LineTableEntry *line_table;
|
||||
|
||||
// The local variable table length and the table itself
|
||||
int local_var_table_len;
|
||||
_Jv_LocalVarTableEntry *local_var_table;
|
||||
|
||||
pc_t prepared;
|
||||
int number_insn_slots;
|
||||
@ -224,6 +243,20 @@ class _Jv_InterpMethod : public _Jv_MethodBase
|
||||
{
|
||||
return static_cast<int> (max_locals);
|
||||
}
|
||||
|
||||
/* Get info for a local variable of this method.
|
||||
* If there is no loca_var_table for this method it will return -1.
|
||||
* table_slot indicates which slot in the local_var_table to get, if there is
|
||||
* no variable at this location it will return 0.
|
||||
* Otherwise, it will return the number of table slots after the selected
|
||||
* slot, indexed from 0.
|
||||
*
|
||||
* Example: there are 5 slots in the table, you request slot 0 so it will
|
||||
* return 4.
|
||||
*/
|
||||
int get_local_var_table (char **name, char **sig, char **generic_sig,
|
||||
jlong *startloc, jint *length, jint *slot,
|
||||
int table_slot);
|
||||
|
||||
/* Installs a break instruction at the given code index. Returns
|
||||
the pc_t of the breakpoint or NULL if index is invalid. */
|
||||
|
@ -1414,6 +1414,30 @@ _Jv_InterpMethod::get_line_table (jlong& start, jlong& end,
|
||||
#endif // !DIRECT_THREADED
|
||||
}
|
||||
|
||||
int
|
||||
_Jv_InterpMethod::get_local_var_table (char **name, char **sig,
|
||||
char **generic_sig, jlong *startloc,
|
||||
jint *length, jint *slot,
|
||||
int table_slot)
|
||||
{
|
||||
if (local_var_table == NULL)
|
||||
return -2;
|
||||
if (table_slot >= local_var_table_len)
|
||||
return -1;
|
||||
else
|
||||
{
|
||||
*name = local_var_table[table_slot].name;
|
||||
*sig = local_var_table[table_slot].descriptor;
|
||||
*generic_sig = local_var_table[table_slot].descriptor;
|
||||
|
||||
*startloc = static_cast<jlong>
|
||||
(local_var_table[table_slot].bytecode_start_pc);
|
||||
*length = static_cast<jint> (local_var_table[table_slot].length);
|
||||
*slot = static_cast<jint> (local_var_table[table_slot].slot);
|
||||
}
|
||||
return local_var_table_len - table_slot -1;
|
||||
}
|
||||
|
||||
pc_t
|
||||
_Jv_InterpMethod::install_break (jlong index)
|
||||
{
|
||||
|
@ -703,6 +703,88 @@ _Jv_JVMTI_GetLineNumberTable (jvmtiEnv *env, jmethodID method,
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
static jvmtiError JNICALL
|
||||
_Jv_JVMTI_GetLocalVariableTable (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
|
||||
jint *num_locals,
|
||||
jvmtiLocalVariableEntry **locals)
|
||||
{
|
||||
REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
|
||||
NULL_CHECK (num_locals);
|
||||
NULL_CHECK (locals);
|
||||
|
||||
CHECK_FOR_NATIVE_METHOD(method);
|
||||
|
||||
jclass klass;
|
||||
jvmtiError jerr = env->GetMethodDeclaringClass (method, &klass);
|
||||
if (jerr != JVMTI_ERROR_NONE)
|
||||
return jerr;
|
||||
|
||||
_Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *>
|
||||
(_Jv_FindInterpreterMethod (klass, method));
|
||||
|
||||
if (imeth == NULL)
|
||||
return JVMTI_ERROR_INVALID_METHODID;
|
||||
|
||||
jerr = env->GetMaxLocals (method, num_locals);
|
||||
if (jerr != JVMTI_ERROR_NONE)
|
||||
return jerr;
|
||||
|
||||
jerr = env->Allocate (static_cast<jlong>
|
||||
((*num_locals) * sizeof (jvmtiLocalVariableEntry)),
|
||||
reinterpret_cast<unsigned char **> (locals));
|
||||
|
||||
if (jerr != JVMTI_ERROR_NONE)
|
||||
return jerr;
|
||||
|
||||
//the slot in the methods local_var_table to get
|
||||
int table_slot = 0;
|
||||
char *name;
|
||||
char *sig;
|
||||
char *generic_sig;
|
||||
|
||||
while (table_slot < *num_locals
|
||||
&& imeth->get_local_var_table (&name, &sig, &generic_sig,
|
||||
&((((*locals)[table_slot].start_location))),
|
||||
&((*locals)[table_slot].length),
|
||||
&((*locals)[table_slot].slot),
|
||||
table_slot)
|
||||
>= 0)
|
||||
{
|
||||
jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1),
|
||||
reinterpret_cast<unsigned char **>
|
||||
(&(*locals)[table_slot].name));
|
||||
if (jerr != JVMTI_ERROR_NONE)
|
||||
return jerr;
|
||||
strcpy ((*locals)[table_slot].name, name);
|
||||
|
||||
jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1),
|
||||
reinterpret_cast<unsigned char **>
|
||||
(&(*locals)[table_slot].signature));
|
||||
if (jerr != JVMTI_ERROR_NONE)
|
||||
return jerr;
|
||||
strcpy ((*locals)[table_slot].signature, sig);
|
||||
|
||||
jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1),
|
||||
reinterpret_cast<unsigned char **>
|
||||
(&(*locals)[table_slot].generic_signature));
|
||||
if (jerr != JVMTI_ERROR_NONE)
|
||||
return jerr;
|
||||
strcpy ((*locals)[table_slot].generic_signature, generic_sig);
|
||||
|
||||
table_slot++;
|
||||
}
|
||||
|
||||
if (table_slot == 0)
|
||||
return JVMTI_ERROR_ABSENT_INFORMATION;
|
||||
|
||||
// If there are double or long variables in the table, the the table will be
|
||||
// smaller than the max number of slots, so correct for this here.
|
||||
if ((table_slot) < *num_locals)
|
||||
*num_locals = table_slot;
|
||||
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
static jvmtiError JNICALL
|
||||
_Jv_JVMTI_IsMethodNative (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
|
||||
jboolean *result)
|
||||
@ -733,8 +815,7 @@ _Jv_JVMTI_IsMethodSynthetic (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
|
||||
}
|
||||
|
||||
static jvmtiError JNICALL
|
||||
_Jv_JVMTI_GetMaxLocals (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
|
||||
jint *max_locals)
|
||||
_Jv_JVMTI_GetMaxLocals (jvmtiEnv *env, jmethodID method, jint *max_locals)
|
||||
{
|
||||
REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
|
||||
NULL_CHECK (max_locals);
|
||||
@ -1686,7 +1767,7 @@ struct _Jv_jvmtiEnv _Jv_JVMTI_Interface =
|
||||
UNIMPLEMENTED, // GetArgumentsSize
|
||||
_Jv_JVMTI_GetLineNumberTable, // GetLineNumberTable
|
||||
UNIMPLEMENTED, // GetMethodLocation
|
||||
UNIMPLEMENTED, // GetLocalVariableTable
|
||||
_Jv_JVMTI_GetLocalVariableTable, // GetLocalVariableTable
|
||||
RESERVED, // reserved73
|
||||
RESERVED, // reserved74
|
||||
UNIMPLEMENTED, // GetBytecodes
|
||||
|
Loading…
Reference in New Issue
Block a user