backtrace / code_attribute / method_entry refactor
This commit is contained in:
parent
16db74a16a
commit
d101710e0f
13
.gitignore
vendored
13
.gitignore
vendored
@ -14,3 +14,16 @@ main
|
|||||||
print_class
|
print_class
|
||||||
__pycache__
|
__pycache__
|
||||||
classes.txt
|
classes.txt
|
||||||
|
*.4ct
|
||||||
|
*.dvi
|
||||||
|
*.lg
|
||||||
|
*.log
|
||||||
|
*.tmp
|
||||||
|
*.toc
|
||||||
|
*.xref
|
||||||
|
doc/*.pdf
|
||||||
|
doc/*.css
|
||||||
|
doc/*.html
|
||||||
|
*.idv
|
||||||
|
*.aux
|
||||||
|
*.4tc
|
||||||
|
36
c/backtrace.c
Normal file
36
c/backtrace.c
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#include "backtrace.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "find_attribute.h"
|
||||||
|
|
||||||
|
void backtrace_print(struct vm * vm)
|
||||||
|
{
|
||||||
|
for (int i = (vm->frame_stack.ix - 1); i >= 0; i--) {
|
||||||
|
printf("ix %d\n", i);
|
||||||
|
struct frame * frame = &vm->frame_stack.frame[i];
|
||||||
|
printf(" class: ");
|
||||||
|
print__class_entry__class_name(frame->class_entry);
|
||||||
|
printc('\n');
|
||||||
|
printf(" method: ");
|
||||||
|
print__method_info__method_name(frame->class_entry, frame->method_info);
|
||||||
|
printc('\n');
|
||||||
|
printf(" pc: %d\n", frame->pc);
|
||||||
|
|
||||||
|
int linenumbertable_name_index = find_linenumbertable_name_index(frame->class_entry->class_file);
|
||||||
|
struct attribute_info * attribute_info = find_attribute(linenumbertable_name_index,
|
||||||
|
frame->code_attribute->attributes_count,
|
||||||
|
frame->code_attribute->attributes);
|
||||||
|
assert(attribute_info != nullptr);
|
||||||
|
int line_number_table_length = attribute_info->line_number_table->line_number_table_length;
|
||||||
|
struct line_number_table * line_number_table = attribute_info->line_number_table->line_number_table;
|
||||||
|
int line_number = 0;
|
||||||
|
for (int i = 0; i < line_number_table_length; i++) {
|
||||||
|
if (frame->pc >= line_number_table[i].start_pc) {
|
||||||
|
line_number = line_number_table[i].line_number;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(" line_number: %d\n", line_number);
|
||||||
|
}
|
||||||
|
}
|
5
c/backtrace.h
Normal file
5
c/backtrace.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
void backtrace_print(struct vm * vm);
|
20
c/bytes.h
20
c/bytes.h
@ -69,7 +69,7 @@ static inline void * parse_bytes(const uint8_t ** buf, int length)
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool bytes_equal(int length, const uint8_t * a, const char * b)
|
static inline bool bytes_equal_string(int length, const uint8_t * a, const char * b)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
@ -78,3 +78,21 @@ static inline bool bytes_equal(int length, const uint8_t * a, const char * b)
|
|||||||
}
|
}
|
||||||
return b[i] == 0;
|
return b[i] == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool bytes_equal_bytes(const uint8_t * a, int a_length, const uint8_t * b, int b_length)
|
||||||
|
{
|
||||||
|
if (a_length != b_length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < a_length; i++) {
|
||||||
|
if ((a[i]) != (b[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool constant_equal(struct constant * constant, const char * s)
|
||||||
|
{
|
||||||
|
assert(constant->tag == CONSTANT_Utf8);
|
||||||
|
return bytes_equal_string(constant->utf8.length, constant->utf8.bytes, s);
|
||||||
|
}
|
||||||
|
@ -12,11 +12,11 @@ void * attribute_info_parse_info(const uint8_t * buf, struct attribute_info * at
|
|||||||
assert(attribute_name->tag == CONSTANT_Utf8);
|
assert(attribute_name->tag == CONSTANT_Utf8);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "ConstantValue")) {
|
if (constant_equal(attribute_name, "ConstantValue")) {
|
||||||
struct ConstantValue_attribute * constantvalue = malloc_class_arena((sizeof (struct ConstantValue_attribute)));
|
struct ConstantValue_attribute * constantvalue = malloc_class_arena((sizeof (struct ConstantValue_attribute)));
|
||||||
constantvalue->constantvalue_index = parse_u2(&buf);
|
constantvalue->constantvalue_index = parse_u2(&buf);
|
||||||
return constantvalue;
|
return constantvalue;
|
||||||
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "Code")) {
|
} else if (constant_equal(attribute_name, "Code")) {
|
||||||
// parse Code
|
// parse Code
|
||||||
struct Code_attribute * code = malloc_class_arena((sizeof (struct Code_attribute)));
|
struct Code_attribute * code = malloc_class_arena((sizeof (struct Code_attribute)));
|
||||||
|
|
||||||
@ -40,34 +40,33 @@ void * attribute_info_parse_info(const uint8_t * buf, struct attribute_info * at
|
|||||||
code->attributes = attribute_info_parse(&buf, code->attributes_count, constant_pool);
|
code->attributes = attribute_info_parse(&buf, code->attributes_count, constant_pool);
|
||||||
|
|
||||||
return code;
|
return code;
|
||||||
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "BootstrapMethods")) {
|
} else if (constant_equal(attribute_name, "BootstrapMethods")) {
|
||||||
// parse BootstrapMethods
|
// parse BootstrapMethods
|
||||||
struct BootstrapMethods_attribute * bootstrapmethods = malloc_class_arena((sizeof (struct BootstrapMethods_attribute)));
|
struct BootstrapMethods_attribute * bootstrap_methods = malloc_class_arena((sizeof (struct BootstrapMethods_attribute)));
|
||||||
|
|
||||||
bootstrapmethods->num_bootstrap_methods = parse_u2(&buf);
|
bootstrap_methods->num_bootstrap_methods = parse_u2(&buf);
|
||||||
|
|
||||||
uint32_t bootstrap_methods_size = (sizeof (struct bootstrap_method)) * bootstrapmethods->num_bootstrap_methods;
|
uint32_t bootstrap_methods_size = (sizeof (struct bootstrap_method)) * bootstrap_methods->num_bootstrap_methods;
|
||||||
bootstrapmethods->bootstrap_methods = malloc_class_arena(bootstrap_methods_size);
|
bootstrap_methods->bootstrap_methods = malloc_class_arena(bootstrap_methods_size);
|
||||||
|
|
||||||
for (int i = 0; i < bootstrapmethods->num_bootstrap_methods; i++) {
|
for (int i = 0; i < bootstrap_methods->num_bootstrap_methods; i++) {
|
||||||
bootstrapmethods->bootstrap_methods[i].bootstrap_method_ref = parse_u2(&buf);
|
bootstrap_methods->bootstrap_methods[i].bootstrap_method_ref = parse_u2(&buf);
|
||||||
bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments = parse_u2(&buf);
|
bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments = parse_u2(&buf);
|
||||||
|
|
||||||
uint32_t bootstrap_arguments_size = (sizeof (u2)) * bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments;
|
uint32_t bootstrap_arguments_size = (sizeof (u2)) * bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments;
|
||||||
bootstrapmethods->bootstrap_methods[i].bootstrap_arguments = malloc_class_arena(bootstrap_arguments_size);
|
bootstrap_methods->bootstrap_methods[i].bootstrap_arguments = malloc_class_arena(bootstrap_arguments_size);
|
||||||
for (int j = 0; j < bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments; j++) {
|
for (int j = 0; j < bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments; j++) {
|
||||||
bootstrapmethods->bootstrap_methods[i].bootstrap_arguments[j] = parse_u2(&buf);
|
bootstrap_methods->bootstrap_methods[i].bootstrap_arguments[j] = parse_u2(&buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bootstrapmethods;
|
return bootstrap_methods;
|
||||||
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "BootstrapMethods")) {
|
} else if (constant_equal(attribute_name, "NestHost")) {
|
||||||
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "NestHost")) {
|
|
||||||
struct NestHost_attribute * nesthost = malloc_class_arena((sizeof (struct NestHost_attribute)));
|
struct NestHost_attribute * nesthost = malloc_class_arena((sizeof (struct NestHost_attribute)));
|
||||||
nesthost->host_class_index = parse_u2(&buf);
|
nesthost->host_class_index = parse_u2(&buf);
|
||||||
|
|
||||||
return nesthost;
|
return nesthost;
|
||||||
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "NestMembers")) {
|
} else if (constant_equal(attribute_name, "NestMembers")) {
|
||||||
struct NestMembers_attribute * nestmembers = malloc_class_arena((sizeof (struct NestMembers_attribute)));
|
struct NestMembers_attribute * nestmembers = malloc_class_arena((sizeof (struct NestMembers_attribute)));
|
||||||
|
|
||||||
nestmembers->number_of_classes = parse_u2(&buf);
|
nestmembers->number_of_classes = parse_u2(&buf);
|
||||||
@ -79,6 +78,18 @@ void * attribute_info_parse_info(const uint8_t * buf, struct attribute_info * at
|
|||||||
}
|
}
|
||||||
|
|
||||||
return nestmembers;
|
return nestmembers;
|
||||||
|
} else if (constant_equal(attribute_name, "LineNumberTable")) {
|
||||||
|
struct LineNumberTable_attribute * line_number_table = malloc_class_arena((sizeof (struct LineNumberTable_attribute)));
|
||||||
|
line_number_table->line_number_table_length = parse_u2(&buf);
|
||||||
|
|
||||||
|
uint32_t line_number_table_size = (sizeof (struct line_number_table)) * line_number_table->line_number_table_length;
|
||||||
|
line_number_table->line_number_table = malloc_class_arena(line_number_table_size);
|
||||||
|
|
||||||
|
for (int i = 0; i < line_number_table->line_number_table_length; i++) {
|
||||||
|
line_number_table->line_number_table[i].start_pc = parse_u2(&buf);
|
||||||
|
line_number_table->line_number_table[i].line_number = parse_u2(&buf);
|
||||||
|
}
|
||||||
|
return line_number_table;
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,7 @@ struct BootstrapMethods_attribute;
|
|||||||
struct NestHost_attribute;
|
struct NestHost_attribute;
|
||||||
struct NestMembers_attribute;
|
struct NestMembers_attribute;
|
||||||
struct PermittedSubclasses_attribute;
|
struct PermittedSubclasses_attribute;
|
||||||
|
struct LineNumberTable_attribute;
|
||||||
|
|
||||||
struct attribute_info {
|
struct attribute_info {
|
||||||
u2 attribute_name_index;
|
u2 attribute_name_index;
|
||||||
@ -144,10 +145,11 @@ struct attribute_info {
|
|||||||
struct ConstantValue_attribute * constantvalue;
|
struct ConstantValue_attribute * constantvalue;
|
||||||
struct Code_attribute * code;
|
struct Code_attribute * code;
|
||||||
//struct StackMapTable_attribute * stackmaptable;
|
//struct StackMapTable_attribute * stackmaptable;
|
||||||
struct BootstrapMethods_attribute * bootstrapmethods;
|
struct BootstrapMethods_attribute * bootstrap_methods;
|
||||||
struct NestHost_attribute * nesthost;
|
struct NestHost_attribute * nesthost;
|
||||||
struct NestMembers_attribute * nestmembers;
|
struct NestMembers_attribute * nestmembers;
|
||||||
//struct PermittedSubclasses_attribute * permittedsubclasses;
|
//struct PermittedSubclasses_attribute * permittedsubclasses;
|
||||||
|
struct LineNumberTable_attribute * line_number_table;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -193,6 +195,16 @@ struct NestMembers_attribute {
|
|||||||
u2 * classes;
|
u2 * classes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct line_number_table {
|
||||||
|
u2 start_pc;
|
||||||
|
u2 line_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LineNumberTable_attribute {
|
||||||
|
u2 line_number_table_length;
|
||||||
|
struct line_number_table * line_number_table;
|
||||||
|
};
|
||||||
|
|
||||||
enum FIELD_ACC {
|
enum FIELD_ACC {
|
||||||
FIELD_ACC_PUBLIC = 0x0001, // Declared public; may be accessed from outside its package.
|
FIELD_ACC_PUBLIC = 0x0001, // Declared public; may be accessed from outside its package.
|
||||||
FIELD_ACC_PRIVATE = 0x0002, // Declared private; accessible only within the defining class and other classes belonging to the same nest (§5.4.4).
|
FIELD_ACC_PRIVATE = 0x0002, // Declared private; accessible only within the defining class and other classes belonging to the same nest (§5.4.4).
|
||||||
|
@ -6,13 +6,13 @@
|
|||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "class_resolver.h"
|
#include "class_resolver.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "debug_class_file.h"
|
|
||||||
#include "memory_allocator.h"
|
#include "memory_allocator.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "field_size.h"
|
#include "field_size.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "fatal.h"
|
#include "fatal.h"
|
||||||
#include "parse_type.h"
|
#include "parse_type.h"
|
||||||
|
#include "find_attribute.h"
|
||||||
|
|
||||||
static int field_info_field_size(struct class_file * class_file, struct field_info * field_info)
|
static int field_info_field_size(struct class_file * class_file, struct field_info * field_info)
|
||||||
{
|
{
|
||||||
@ -50,7 +50,7 @@ static int32_t count_superclass_instance_fields(int class_hash_table_length,
|
|||||||
struct constant * class_name_constant = &subclass_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &subclass_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
debugf("count_superclass_instance_fields: ");
|
debugf("count_superclass_instance_fields: ");
|
||||||
print_utf8_string(class_name_constant);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
debugf(": %d\n", instance_field_count);
|
debugf(": %d\n", instance_field_count);
|
||||||
|
|
||||||
return instance_field_count;
|
return instance_field_count;
|
||||||
@ -87,7 +87,7 @@ static int add_superclass_instance_fields(int class_hash_table_length,
|
|||||||
struct constant * name_constant = &class_entry->class_file->constant_pool[field_info->name_index - 1];
|
struct constant * name_constant = &class_entry->class_file->constant_pool[field_info->name_index - 1];
|
||||||
assert(name_constant->tag == CONSTANT_Utf8);
|
assert(name_constant->tag == CONSTANT_Utf8);
|
||||||
debugf("hash table entry for instance field: ");
|
debugf("hash table entry for instance field: ");
|
||||||
print_utf8_string(name_constant);
|
debug_print__constant__utf8_string(name_constant);
|
||||||
debugf(": %d %p\n", instance_index, field_entry);
|
debugf(": %d %p\n", instance_index, field_entry);
|
||||||
hash_table_add(fields_hash_table_length,
|
hash_table_add(fields_hash_table_length,
|
||||||
fields_hash_table,
|
fields_hash_table,
|
||||||
@ -106,10 +106,11 @@ static int32_t class_resolver_create_fields_hash_table(int class_hash_table_leng
|
|||||||
struct hash_table_entry * class_hash_table,
|
struct hash_table_entry * class_hash_table,
|
||||||
struct class_entry * class_entry)
|
struct class_entry * class_entry)
|
||||||
{
|
{
|
||||||
int total_fields_count = class_entry->class_file->fields_count + count_superclass_instance_fields(class_hash_table_length,
|
int total_fields_count = class_entry->class_file->fields_count
|
||||||
|
+ count_superclass_instance_fields(class_hash_table_length,
|
||||||
class_hash_table,
|
class_hash_table,
|
||||||
class_entry);
|
class_entry);
|
||||||
int fields_hash_table_length = hash_table_next_power_of_two(class_entry->class_file->fields_count * 2);
|
int fields_hash_table_length = hash_table_next_power_of_two(total_fields_count * 2);
|
||||||
uint32_t fields_hash_table_size = (sizeof (struct hash_table_entry)) * fields_hash_table_length;
|
uint32_t fields_hash_table_size = (sizeof (struct hash_table_entry)) * fields_hash_table_length;
|
||||||
struct hash_table_entry * fields_hash_table = malloc_class_arena(fields_hash_table_size);
|
struct hash_table_entry * fields_hash_table = malloc_class_arena(fields_hash_table_size);
|
||||||
hash_table_init(fields_hash_table_length, fields_hash_table);
|
hash_table_init(fields_hash_table_length, fields_hash_table);
|
||||||
@ -127,7 +128,7 @@ static int32_t class_resolver_create_fields_hash_table(int class_hash_table_leng
|
|||||||
struct constant * name_constant = &class_entry->class_file->constant_pool[field_info->name_index - 1];
|
struct constant * name_constant = &class_entry->class_file->constant_pool[field_info->name_index - 1];
|
||||||
assert(name_constant->tag == CONSTANT_Utf8);
|
assert(name_constant->tag == CONSTANT_Utf8);
|
||||||
debugf("hash table entry for static field: ");
|
debugf("hash table entry for static field: ");
|
||||||
print_utf8_string(name_constant);
|
debug_print__constant__utf8_string(name_constant);
|
||||||
debugf(": %d %p\n", static_index, field_entry);
|
debugf(": %d %p\n", static_index, field_entry);
|
||||||
|
|
||||||
hash_table_add(fields_hash_table_length,
|
hash_table_add(fields_hash_table_length,
|
||||||
@ -204,7 +205,7 @@ static void class_resolver_allocate_attribute_entry(struct class_entry * class_e
|
|||||||
uint32_t attribute_entry_size = (sizeof (union attribute_entry)) * class_file->constant_pool_count;
|
uint32_t attribute_entry_size = (sizeof (union attribute_entry)) * class_file->constant_pool_count;
|
||||||
union attribute_entry * attribute_entry = malloc_class_arena(attribute_entry_size);
|
union attribute_entry * attribute_entry = malloc_class_arena(attribute_entry_size);
|
||||||
|
|
||||||
for (int i = 0; i < class_file->constant_pool_count; i++) {
|
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
|
||||||
attribute_entry[i].class_entry = nullptr;
|
attribute_entry[i].class_entry = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +238,7 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff
|
|||||||
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
debugf("hash table entry for class: ");
|
debugf("hash table entry for class: ");
|
||||||
print_utf8_string(class_name_constant);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
debugf(" %p\n", &class_entry[i]);
|
debugf(" %p\n", &class_entry[i]);
|
||||||
|
|
||||||
hash_table_add(class_hash_table_length,
|
hash_table_add(class_hash_table_length,
|
||||||
@ -431,9 +432,17 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
|
|||||||
debug_print__method_info__method_name(class_entry, method_info);
|
debug_print__method_info__method_name(class_entry, method_info);
|
||||||
debugc('\n');
|
debugc('\n');
|
||||||
|
|
||||||
|
int code_index = find_code_name_index(class_entry->class_file);
|
||||||
|
assert(code_index != 0);
|
||||||
|
struct attribute_info * attribute = find_attribute(code_index,
|
||||||
|
method_info->attributes_count,
|
||||||
|
method_info->attributes);
|
||||||
|
assert(attribute != nullptr);
|
||||||
|
|
||||||
return (struct method_entry){
|
return (struct method_entry){
|
||||||
.class_entry = class_entry,
|
.class_entry = class_entry,
|
||||||
.method_info = method_info
|
.method_info = method_info,
|
||||||
|
.code_attribute = attribute->code,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,7 +453,7 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
|
|||||||
assert(class_constant->tag == CONSTANT_Class);
|
assert(class_constant->tag == CONSTANT_Class);
|
||||||
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
print_utf8_string(class_name_constant);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
debugf("\n");
|
debugf("\n");
|
||||||
|
|
||||||
// lookup the method from the superclass
|
// lookup the method from the superclass
|
||||||
@ -501,6 +510,14 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
|
|||||||
struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry)));
|
struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry)));
|
||||||
method_entry->class_entry = class_entry;
|
method_entry->class_entry = class_entry;
|
||||||
method_entry->method_info = method_info;
|
method_entry->method_info = method_info;
|
||||||
|
int code_index = find_code_name_index(class_entry->class_file);
|
||||||
|
assert(code_index != 0);
|
||||||
|
struct attribute_info * attribute = find_attribute(code_index,
|
||||||
|
method_info->attributes_count,
|
||||||
|
method_info->attributes);
|
||||||
|
assert(attribute != nullptr);
|
||||||
|
method_entry->code_attribute = attribute->code;
|
||||||
|
|
||||||
origin_class_entry->attribute_entry[methodref_index - 1].method_entry = method_entry;
|
origin_class_entry->attribute_entry[methodref_index - 1].method_entry = method_entry;
|
||||||
return method_entry;
|
return method_entry;
|
||||||
}
|
}
|
||||||
@ -512,7 +529,7 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
|
|||||||
assert(class_constant->tag == CONSTANT_Class);
|
assert(class_constant->tag == CONSTANT_Class);
|
||||||
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
print_utf8_string(class_name_constant);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
debugf("\n");
|
debugf("\n");
|
||||||
|
|
||||||
// lookup the method from the superclass
|
// lookup the method from the superclass
|
||||||
@ -526,6 +543,42 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
|
|||||||
assert(!"methodref method does not exist");
|
assert(!"methodref method does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry,
|
||||||
|
const uint8_t * method_name,
|
||||||
|
int method_name_length,
|
||||||
|
const uint8_t * method_descriptor,
|
||||||
|
int method_descriptor_length)
|
||||||
|
{
|
||||||
|
struct method_info * method_info = class_resolver_lookup_method(class_entry->methods.length,
|
||||||
|
class_entry->methods.entry,
|
||||||
|
method_name,
|
||||||
|
method_name_length,
|
||||||
|
method_descriptor,
|
||||||
|
method_descriptor_length);
|
||||||
|
|
||||||
|
if (method_info != nullptr) {
|
||||||
|
int code_index = find_code_name_index(class_entry->class_file);
|
||||||
|
assert(code_index != 0);
|
||||||
|
debugf("code_index: %d\n", code_index);
|
||||||
|
struct attribute_info * attribute = find_attribute(code_index,
|
||||||
|
method_info->attributes_count,
|
||||||
|
method_info->attributes);
|
||||||
|
assert(attribute != nullptr);
|
||||||
|
|
||||||
|
return (struct method_entry){
|
||||||
|
.class_entry = class_entry,
|
||||||
|
.method_info = method_info,
|
||||||
|
.code_attribute = attribute->code,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return (struct method_entry){
|
||||||
|
.class_entry = nullptr,
|
||||||
|
.method_info = nullptr,
|
||||||
|
.code_attribute = nullptr,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int32_t * class_resolver_lookup_string(int class_hash_table_length,
|
int32_t * class_resolver_lookup_string(int class_hash_table_length,
|
||||||
struct hash_table_entry * class_hash_table,
|
struct hash_table_entry * class_hash_table,
|
||||||
struct class_entry * class_entry,
|
struct class_entry * class_entry,
|
||||||
|
@ -14,6 +14,7 @@ enum initialization_state {
|
|||||||
struct method_entry {
|
struct method_entry {
|
||||||
struct class_entry * class_entry;
|
struct class_entry * class_entry;
|
||||||
struct method_info * method_info;
|
struct method_info * method_info;
|
||||||
|
struct Code_attribute * code_attribute;
|
||||||
};
|
};
|
||||||
|
|
||||||
union attribute_entry {
|
union attribute_entry {
|
||||||
@ -60,12 +61,6 @@ struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash
|
|||||||
struct hash_table_entry * class_hash_table,
|
struct hash_table_entry * class_hash_table,
|
||||||
struct class_entry * class_entry,
|
struct class_entry * class_entry,
|
||||||
int32_t class_index);
|
int32_t class_index);
|
||||||
struct method_info * class_resolver_lookup_method(int methods_hash_table_length,
|
|
||||||
struct hash_table_entry * methods_hash_table,
|
|
||||||
const uint8_t * method_name,
|
|
||||||
int method_name_length,
|
|
||||||
const uint8_t * method_descriptor,
|
|
||||||
int method_descriptor_length);
|
|
||||||
struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(int class_hash_table_length,
|
struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(int class_hash_table_length,
|
||||||
struct hash_table_entry * class_hash_table,
|
struct hash_table_entry * class_hash_table,
|
||||||
int32_t interfacemethodref_index,
|
int32_t interfacemethodref_index,
|
||||||
@ -75,6 +70,11 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
|
|||||||
struct hash_table_entry * class_hash_table,
|
struct hash_table_entry * class_hash_table,
|
||||||
int32_t methodref_index,
|
int32_t methodref_index,
|
||||||
struct class_entry * origin_class_entry);
|
struct class_entry * origin_class_entry);
|
||||||
|
struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry,
|
||||||
|
const uint8_t * method_name,
|
||||||
|
int method_name_length,
|
||||||
|
const uint8_t * method_descriptor,
|
||||||
|
int method_descriptor_length);
|
||||||
struct field_entry * class_resolver_lookup_field(int fields_hash_table_length,
|
struct field_entry * class_resolver_lookup_field(int fields_hash_table_length,
|
||||||
struct hash_table_entry * fields_hash_table,
|
struct hash_table_entry * fields_hash_table,
|
||||||
const uint8_t * field_name,
|
const uint8_t * field_name,
|
||||||
|
57
c/debug.c
57
c/debug.c
@ -2,8 +2,16 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
|
||||||
|
void debug_print__string(const uint8_t * bytes, int length)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
debugc(bytes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void debug_print__constant__utf8_string(struct constant * constant)
|
void debug_print__constant__utf8_string(struct constant * constant)
|
||||||
{
|
{
|
||||||
|
assert(constant->tag == CONSTANT_Utf8);
|
||||||
for (int i = 0; i < constant->utf8.length; i++) {
|
for (int i = 0; i < constant->utf8.length; i++) {
|
||||||
debugc(constant->utf8.bytes[i]);
|
debugc(constant->utf8.bytes[i]);
|
||||||
}
|
}
|
||||||
@ -14,28 +22,49 @@ void debug_print__class_entry__class_name(struct class_entry * class_entry)
|
|||||||
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
|
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
|
||||||
assert(class_constant->tag == CONSTANT_Class);
|
assert(class_constant->tag == CONSTANT_Class);
|
||||||
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
|
||||||
debug_print__constant__utf8_string(class_name_constant);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void debug_print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant)
|
||||||
|
{
|
||||||
|
debug_print__constant__utf8_string(name_constant);
|
||||||
|
debugc(' ');
|
||||||
|
debug_print__constant__utf8_string(descriptor_constant);
|
||||||
|
}
|
||||||
|
|
||||||
void debug_print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info)
|
void debug_print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info)
|
||||||
{
|
{
|
||||||
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_info->name_index - 1];
|
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_info->name_index - 1];
|
||||||
assert(method_name_constant->tag == CONSTANT_Utf8);
|
|
||||||
debug_print__constant__utf8_string(method_name_constant);
|
|
||||||
|
|
||||||
debugc(' ');
|
|
||||||
|
|
||||||
struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1];
|
struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1];
|
||||||
assert(method_descriptor_constant->tag == CONSTANT_Utf8);
|
debug_print__constant__method_name(method_name_constant, method_descriptor_constant);
|
||||||
debug_print__constant__utf8_string(method_descriptor_constant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug_print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant)
|
void print__constant__utf8_string(struct constant * constant)
|
||||||
{
|
{
|
||||||
assert(name_constant->tag == CONSTANT_Utf8);
|
assert(constant->tag == CONSTANT_Utf8);
|
||||||
debug_print__constant__utf8_string(name_constant);
|
for (int i = 0; i < constant->utf8.length; i++) {
|
||||||
debugc(' ');
|
printc(constant->utf8.bytes[i]);
|
||||||
assert(descriptor_constant->tag == CONSTANT_Utf8);
|
}
|
||||||
debug_print__constant__utf8_string(descriptor_constant);
|
}
|
||||||
|
|
||||||
|
void print__class_entry__class_name(struct class_entry * class_entry)
|
||||||
|
{
|
||||||
|
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
|
||||||
|
assert(class_constant->tag == CONSTANT_Class);
|
||||||
|
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
|
print__constant__utf8_string(class_name_constant);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant)
|
||||||
|
{
|
||||||
|
print__constant__utf8_string(name_constant);
|
||||||
|
printc(' ');
|
||||||
|
print__constant__utf8_string(descriptor_constant);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info)
|
||||||
|
{
|
||||||
|
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_info->name_index - 1];
|
||||||
|
struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1];
|
||||||
|
print__constant__method_name(method_name_constant, method_descriptor_constant);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,13 @@
|
|||||||
#include "class_file.h"
|
#include "class_file.h"
|
||||||
#include "class_resolver.h"
|
#include "class_resolver.h"
|
||||||
|
|
||||||
|
void debug_print__string(const uint8_t * bytes, int length);
|
||||||
void debug_print__constant__utf8_string(struct constant * constant);
|
void debug_print__constant__utf8_string(struct constant * constant);
|
||||||
void debug_print__class_entry__class_name(struct class_entry * class_entry);
|
void debug_print__class_entry__class_name(struct class_entry * class_entry);
|
||||||
void debug_print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info);
|
|
||||||
void debug_print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant);
|
void debug_print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant);
|
||||||
|
void debug_print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info);
|
||||||
|
|
||||||
|
void print__constant__utf8_string(struct constant * constant);
|
||||||
|
void print__class_entry__class_name(struct class_entry * class_entry);
|
||||||
|
void print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant);
|
||||||
|
void print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info);
|
||||||
|
@ -7,284 +7,322 @@
|
|||||||
#include "debug_class_file.h"
|
#include "debug_class_file.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
void print_utf8_string(struct constant * constant)
|
static void print_attribute(const char * indent, struct attribute_info * attribute, struct constant * constant_pool);
|
||||||
{
|
|
||||||
for (int i = 0; i < constant->utf8.length; i++) {
|
|
||||||
debugc(constant->utf8.bytes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_constant(struct constant * constant)
|
static void print_constant(struct constant * constant)
|
||||||
{
|
{
|
||||||
switch (constant->tag) {
|
switch (constant->tag) {
|
||||||
case CONSTANT_Class:
|
case CONSTANT_Class:
|
||||||
debugf("CONSTANT_Class name_index=%d\n",
|
printf("CONSTANT_Class name_index=%d\n",
|
||||||
constant->class.name_index);
|
constant->class.name_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Fieldref:
|
case CONSTANT_Fieldref:
|
||||||
debugf("CONSTANT_Fieldref class_index=%d name_and_type_index=%d\n",
|
printf("CONSTANT_Fieldref class_index=%d name_and_type_index=%d\n",
|
||||||
constant->fieldref.class_index,
|
constant->fieldref.class_index,
|
||||||
constant->fieldref.name_and_type_index);
|
constant->fieldref.name_and_type_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Methodref:
|
case CONSTANT_Methodref:
|
||||||
debugf("CONSTANT_Methodref class_index=%d name_and_type_index=%d\n",
|
printf("CONSTANT_Methodref class_index=%d name_and_type_index=%d\n",
|
||||||
constant->methodref.class_index,
|
constant->methodref.class_index,
|
||||||
constant->methodref.name_and_type_index);
|
constant->methodref.name_and_type_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_InterfaceMethodref:
|
case CONSTANT_InterfaceMethodref:
|
||||||
debugf("CONSTANT_InterfaceMethodref class_index=%d name_and_type_index=%d\n",
|
printf("CONSTANT_InterfaceMethodref class_index=%d name_and_type_index=%d\n",
|
||||||
constant->interfacemethodref.class_index,
|
constant->interfacemethodref.class_index,
|
||||||
constant->interfacemethodref.name_and_type_index);
|
constant->interfacemethodref.name_and_type_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_String:
|
case CONSTANT_String:
|
||||||
debugf("CONSTANT_String string_index=%d\n",
|
printf("CONSTANT_String string_index=%d\n",
|
||||||
constant->string.string_index);
|
constant->string.string_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Integer:
|
case CONSTANT_Integer:
|
||||||
debugf("CONSTANT_Integer bytes=%d\n",
|
printf("CONSTANT_Integer bytes=%d\n",
|
||||||
constant->integer.bytes);
|
constant->integer.bytes);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Float:
|
case CONSTANT_Float:
|
||||||
debugf("CONSTANT_Float bytes=%f\n",
|
printf("CONSTANT_Float bytes=%f\n",
|
||||||
*(float *)(&constant->_float.bytes));
|
*(float *)(&constant->_float.bytes));
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Long:
|
case CONSTANT_Long:
|
||||||
debugf("CONSTANT_Long bytes=%l\n",
|
printf("CONSTANT_Long bytes=%l\n",
|
||||||
constant->_long.bytes);
|
constant->_long.bytes);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Double:
|
case CONSTANT_Double:
|
||||||
debugf("CONSTANT_Double bytes=%f\n",
|
printf("CONSTANT_Double bytes=%f\n",
|
||||||
*(double *)(&constant->_double.bytes));
|
*(double *)(&constant->_double.bytes));
|
||||||
break;
|
break;
|
||||||
case CONSTANT_NameAndType:
|
case CONSTANT_NameAndType:
|
||||||
debugf("CONSTANT_NameAndType %d %d\n",
|
printf("CONSTANT_NameAndType name_index=%d descriptor_index=%d\n",
|
||||||
constant->nameandtype.name_index,
|
constant->nameandtype.name_index,
|
||||||
constant->nameandtype.descriptor_index);
|
constant->nameandtype.descriptor_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Utf8:
|
case CONSTANT_Utf8:
|
||||||
debugf("CONSTANT_Utf8 length=%d bytes=",
|
printf("CONSTANT_Utf8 length=%d bytes=",
|
||||||
constant->utf8.length);
|
constant->utf8.length);
|
||||||
print_utf8_string(constant);
|
print__constant__utf8_string(constant);
|
||||||
debugf("\n");
|
printf("\n");
|
||||||
break;
|
break;
|
||||||
case CONSTANT_MethodHandle:
|
case CONSTANT_MethodHandle:
|
||||||
debugf("CONSTANT_MethodHandle reference_kind=%d reference_index=%d\n",
|
printf("CONSTANT_MethodHandle reference_kind=%d reference_index=%d\n",
|
||||||
constant->methodhandle.reference_kind,
|
constant->methodhandle.reference_kind,
|
||||||
constant->methodhandle.reference_index);
|
constant->methodhandle.reference_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_MethodType:
|
case CONSTANT_MethodType:
|
||||||
debugf("CONSTANT_MethodType descriptor_index=%d\n",
|
printf("CONSTANT_MethodType descriptor_index=%d\n",
|
||||||
constant->methodtype.descriptor_index);
|
constant->methodtype.descriptor_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Dynamic:
|
case CONSTANT_Dynamic:
|
||||||
debugf("CONSTANT_Dynamic bootstrap_method_attr_index=%d name_and_type_index=%d\n",
|
printf("CONSTANT_Dynamic bootstrap_method_attr_index=%d name_and_type_index=%d\n",
|
||||||
constant->dynamic.bootstrap_method_attr_index,
|
constant->dynamic.bootstrap_method_attr_index,
|
||||||
constant->dynamic.name_and_type_index);
|
constant->dynamic.name_and_type_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_InvokeDynamic:
|
case CONSTANT_InvokeDynamic:
|
||||||
debugf("CONSTANT_InvokeDynamic bootstrap_method_attr_index=%d name_and_type_index=%d\n",
|
printf("CONSTANT_InvokeDynamic bootstrap_method_attr_index=%d name_and_type_index=%d\n",
|
||||||
constant->invokedynamic.bootstrap_method_attr_index,
|
constant->invokedynamic.bootstrap_method_attr_index,
|
||||||
constant->invokedynamic.name_and_type_index);
|
constant->invokedynamic.name_and_type_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Module:
|
case CONSTANT_Module:
|
||||||
debugf("CONSTANT_Module name_index=%d\n",
|
printf("CONSTANT_Module name_index=%d\n",
|
||||||
constant->module.name_index);
|
constant->module.name_index);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Package:
|
case CONSTANT_Package:
|
||||||
debugf("CONSTANT_Package name_index=%d\n",
|
printf("CONSTANT_Package name_index=%d\n",
|
||||||
constant->package.name_index);
|
constant->package.name_index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_attribute(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
|
static void print_bootstrap_methods(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
|
||||||
{
|
{
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("attribute_name_index: %d\n", attribute->attribute_name_index);
|
printf("num_bootstrap_methods: %d\n", attribute->bootstrap_methods->num_bootstrap_methods);
|
||||||
struct constant * attribute_name = &constant_pool[attribute->attribute_name_index - 1];
|
prints(indent);
|
||||||
debugs(indent);
|
printf("bootstrap methods:\n");
|
||||||
debugs(" ");
|
for (int i = 0; i < attribute->bootstrap_methods->num_bootstrap_methods; i++) {
|
||||||
print_constant(attribute_name);
|
prints(indent);
|
||||||
|
printf(" bootstrap_method %d:\n", i);
|
||||||
|
prints(indent);
|
||||||
|
printf(" bootstrap_method_ref: %d\n", attribute->bootstrap_methods->bootstrap_methods[i].bootstrap_method_ref);
|
||||||
|
prints(indent);
|
||||||
|
printf(" num_bootstrap_arguments: %d\n", attribute->bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments);
|
||||||
|
prints(indent);
|
||||||
|
printf(" bootstrap_arguments:\n");
|
||||||
|
for (int j = 0; j < attribute->bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments; j++) {
|
||||||
|
prints(indent);
|
||||||
|
printf(" bootstrap_argument %d: %d\n", j, attribute->bootstrap_methods->bootstrap_methods[i].bootstrap_arguments[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "ConstantValue")) {
|
static void print_nestmembers(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
|
||||||
debugs(indent);
|
{
|
||||||
debugf("constantvalue_index %d\n", attribute->constantvalue->constantvalue_index);
|
prints(indent);
|
||||||
|
printf("number_of_classes: %d\n", attribute->nestmembers->number_of_classes);
|
||||||
|
prints(indent);
|
||||||
|
printf("classes:\n");
|
||||||
|
for (int i = 0; i < attribute->nestmembers->number_of_classes; i++) {
|
||||||
|
prints(indent);
|
||||||
|
printf(" class %d:\n", i);
|
||||||
|
prints(indent);
|
||||||
|
prints(" ");
|
||||||
|
print_constant(&constant_pool[attribute->nestmembers->classes[i] - 1]);
|
||||||
|
int ix = constant_pool[attribute->nestmembers->classes[i] - 1].class.name_index;
|
||||||
|
prints(indent);
|
||||||
|
prints(" ");
|
||||||
|
print_constant(&constant_pool[ix - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_nesthost(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
|
||||||
|
{
|
||||||
|
prints(indent);
|
||||||
|
printf("host_class_index: %d\n", attribute->nesthost->host_class_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_constantvalue(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
|
||||||
|
{
|
||||||
|
prints(indent);
|
||||||
|
printf("constantvalue_index %d\n", attribute->constantvalue->constantvalue_index);
|
||||||
|
|
||||||
|
|
||||||
struct constant * value = &constant_pool[attribute->constantvalue->constantvalue_index - 1];
|
struct constant * value = &constant_pool[attribute->constantvalue->constantvalue_index - 1];
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugs(" ");
|
prints(" ");
|
||||||
print_constant(value);
|
print_constant(value);
|
||||||
if (value->tag == CONSTANT_String) {
|
if (value->tag == CONSTANT_String) {
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugs(" ");
|
prints(" ");
|
||||||
print_constant(&constant_pool[value->string.string_index - 1]);
|
print_constant(&constant_pool[value->string.string_index - 1]);
|
||||||
}
|
}
|
||||||
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "Code")) {
|
}
|
||||||
|
|
||||||
|
static void print_code(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
|
||||||
|
{
|
||||||
// print code
|
// print code
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("max_stack %d\n", attribute->code->max_stack);
|
printf("max_stack %d\n", attribute->code->max_stack);
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("max_locals %d\n", attribute->code->max_locals);
|
printf("max_locals %d\n", attribute->code->max_locals);
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("code_length %d\n", attribute->code->code_length);
|
printf("code_length %d\n", attribute->code->code_length);
|
||||||
|
|
||||||
// dump code
|
// dump code
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("code:\n");
|
printf("code:\n");
|
||||||
uint32_t pc = 0;
|
uint32_t pc = 0;
|
||||||
while (pc < attribute->code->code_length) {
|
while (pc < attribute->code->code_length) {
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugs(" ");
|
prints(" ");
|
||||||
pc = decode_print_instruction(attribute->code->code, pc);
|
pc = decode_print_instruction(attribute->code->code, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("exception_table_length: %d\n", attribute->code->exception_table_length);
|
printf("exception_table_length: %d\n", attribute->code->exception_table_length);
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("exceptions:\n");
|
printf("exceptions:\n");
|
||||||
for (int i = 0; i < attribute->code->exception_table_length; i++) {
|
for (int i = 0; i < attribute->code->exception_table_length; i++) {
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf(" exception %d:\n", i);
|
printf(" exception %d:\n", i);
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf(" start_pc: %d\n", attribute->code->exception_table[i].start_pc);
|
printf(" start_pc: %d\n", attribute->code->exception_table[i].start_pc);
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf(" end_pc: %d\n", attribute->code->exception_table[i].end_pc);
|
printf(" end_pc: %d\n", attribute->code->exception_table[i].end_pc);
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf(" handler_pc: %d\n", attribute->code->exception_table[i].handler_pc);
|
printf(" handler_pc: %d\n", attribute->code->exception_table[i].handler_pc);
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf(" catch_type: %d\n", attribute->code->exception_table[i].catch_type);
|
printf(" catch_type: %d\n", attribute->code->exception_table[i].catch_type);
|
||||||
}
|
}
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("attributes_count: %d\n", attribute->code->attributes_count);
|
printf("attributes_count: %d\n", attribute->code->attributes_count);
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("attributes:\n");
|
printf("attributes:\n");
|
||||||
for (int i = 0; i < attribute->code->attributes_count; i++) {
|
for (int i = 0; i < attribute->code->attributes_count; i++) {
|
||||||
char indent2[string_length(indent) + 2 + 1];
|
char indent2[string_length(indent) + 2 + 1];
|
||||||
string_copy(indent2, indent);
|
string_copy(indent2, indent);
|
||||||
string_copy(indent2 + string_length(indent), " ");
|
string_copy(indent2 + string_length(indent), " ");
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf(" attribute %d:\n", i);
|
printf(" attribute %d:\n", i);
|
||||||
print_attribute(indent2, &attribute->code->attributes[i], constant_pool);
|
print_attribute(indent2, &attribute->code->attributes[i], constant_pool);
|
||||||
}
|
}
|
||||||
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "BootstrapMethods")) {
|
|
||||||
debugs(indent);
|
}
|
||||||
debugf("num_bootstrap_methods: %d\n", attribute->bootstrapmethods->num_bootstrap_methods);
|
|
||||||
debugs(indent);
|
static void print_line_number_table(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
|
||||||
debugf("bootstrap methods:\n");
|
{
|
||||||
for (int i = 0; i < attribute->bootstrapmethods->num_bootstrap_methods; i++) {
|
prints(indent);
|
||||||
debugs(indent);
|
printf("line_number_table_length: %d\n", attribute->line_number_table->line_number_table_length);
|
||||||
debugf(" bootstrap_method %d:\n", i);
|
prints(indent);
|
||||||
debugs(indent);
|
printf("line_number_table:\n");
|
||||||
debugf(" bootstrap_method_ref: %d\n", attribute->bootstrapmethods->bootstrap_methods[i].bootstrap_method_ref);
|
for (int i = 0; i < attribute->line_number_table->line_number_table_length; i++) {
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf(" num_bootstrap_arguments: %d\n", attribute->bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments);
|
printf(" start_pc=%d line_number=%d\n",
|
||||||
debugs(indent);
|
attribute->line_number_table->line_number_table[i].start_pc,
|
||||||
debugf(" bootstrap_arguments:\n");
|
attribute->line_number_table->line_number_table[i].line_number);
|
||||||
for (int j = 0; j < attribute->bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments; j++) {
|
|
||||||
debugs(indent);
|
|
||||||
debugf(" bootstrap_argument %d: %d\n", j, attribute->bootstrapmethods->bootstrap_methods[i].bootstrap_arguments[j]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "NestHost")) {
|
|
||||||
debugs(indent);
|
static void print_attribute(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
|
||||||
debugf("host_class_index: %d\n", attribute->nesthost->host_class_index);
|
{
|
||||||
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "NestMembers")) {
|
prints(indent);
|
||||||
debugs(indent);
|
printf("attribute_name_index: %d\n", attribute->attribute_name_index);
|
||||||
debugf("number_of_classes: %d\n", attribute->nestmembers->number_of_classes);
|
struct constant * attribute_name = &constant_pool[attribute->attribute_name_index - 1];
|
||||||
debugs(indent);
|
prints(indent);
|
||||||
debugf("classes:\n");
|
prints(" ");
|
||||||
for (int i = 0; i < attribute->nestmembers->number_of_classes; i++) {
|
print_constant(attribute_name);
|
||||||
debugs(indent);
|
|
||||||
debugf(" class %d:\n", i);
|
if (constant_equal(attribute_name, "ConstantValue")) {
|
||||||
debugs(indent);
|
print_constantvalue(indent, attribute, constant_pool);
|
||||||
debugs(" ");
|
} else if (constant_equal(attribute_name, "Code")) {
|
||||||
print_constant(&constant_pool[attribute->nestmembers->classes[i] - 1]);
|
print_code(indent, attribute, constant_pool);
|
||||||
int ix = constant_pool[attribute->nestmembers->classes[i] - 1].class.name_index;
|
} else if (constant_equal(attribute_name, "BootstrapMethods")) {
|
||||||
debugs(indent);
|
print_bootstrap_methods(indent, attribute, constant_pool);
|
||||||
debugs(" ");
|
} else if (constant_equal(attribute_name, "NestHost")) {
|
||||||
print_constant(&constant_pool[ix - 1]);
|
print_nesthost(indent, attribute, constant_pool);
|
||||||
}
|
} else if (constant_equal(attribute_name, "NestMembers")) {
|
||||||
|
print_nestmembers(indent, attribute, constant_pool);
|
||||||
|
} else if (constant_equal(attribute_name, "LineNumberTable")) {
|
||||||
|
print_line_number_table(indent, attribute, constant_pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_class_file(struct class_file * class_file)
|
void print_class_file(struct class_file * class_file)
|
||||||
{
|
{
|
||||||
debugf("magic %08x\n", class_file->magic);
|
printf("magic %08x\n", class_file->magic);
|
||||||
debugf("minor_version %d\n", class_file->minor_version);
|
printf("minor_version %d\n", class_file->minor_version);
|
||||||
debugf("major_version %d\n", class_file->major_version);
|
printf("major_version %d\n", class_file->major_version);
|
||||||
debugf("constant_pool_count %d\n", class_file->constant_pool_count);
|
printf("constant_pool_count %d\n", class_file->constant_pool_count);
|
||||||
|
|
||||||
debugf("constants:\n");
|
printf("constants:\n");
|
||||||
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
|
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
|
||||||
if (class_file->constant_pool[i].tag != 0) {
|
if (class_file->constant_pool[i].tag != 0) {
|
||||||
debugf("%4d: ", i + 1);
|
printf("%4d: ", i + 1);
|
||||||
print_constant(&class_file->constant_pool[i]);
|
print_constant(&class_file->constant_pool[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debugf("access_flags %04x\n", class_file->access_flags);
|
printf("access_flags %04x\n", class_file->access_flags);
|
||||||
debugf("this_class %d\n", class_file->this_class);
|
printf("this_class %d\n", class_file->this_class);
|
||||||
debugf("super_class %d\n", class_file->super_class);
|
printf("super_class %d\n", class_file->super_class);
|
||||||
debugf("interfaces_count %d\n", class_file->interfaces_count);
|
printf("interfaces_count %d\n", class_file->interfaces_count);
|
||||||
|
|
||||||
debugf("interfaces:\n");
|
printf("interfaces:\n");
|
||||||
for (int i = 0; i < class_file->interfaces_count; i++) {
|
for (int i = 0; i < class_file->interfaces_count; i++) {
|
||||||
debugf(" interface %3d:\n", i);
|
printf(" interface %3d:\n", i);
|
||||||
int interface_index = class_file->interfaces[i];
|
int interface_index = class_file->interfaces[i];
|
||||||
debugs(" ");
|
prints(" ");
|
||||||
struct constant * class_constant = &class_file->constant_pool[interface_index - 1];
|
struct constant * class_constant = &class_file->constant_pool[interface_index - 1];
|
||||||
print_constant(class_constant);
|
print_constant(class_constant);
|
||||||
debugs(" ");
|
prints(" ");
|
||||||
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
print_constant(class_name_constant);
|
print_constant(class_name_constant);
|
||||||
}
|
}
|
||||||
|
|
||||||
debugf("fields_count %d\n", class_file->fields_count);
|
printf("fields_count %d\n", class_file->fields_count);
|
||||||
debugf("fields:\n");
|
printf("fields:\n");
|
||||||
for (int i = 0; i < class_file->fields_count; i++) {
|
for (int i = 0; i < class_file->fields_count; i++) {
|
||||||
debugf(" field %d:\n", i);
|
printf(" field %d:\n", i);
|
||||||
debugf(" access_flags %d\n", class_file->fields[i].access_flags);
|
printf(" access_flags %d\n", class_file->fields[i].access_flags);
|
||||||
debugf(" name_index %d\n", class_file->fields[i].name_index);
|
printf(" name_index %d\n", class_file->fields[i].name_index);
|
||||||
debugf(" ");
|
printf(" ");
|
||||||
print_constant(&class_file->constant_pool[class_file->fields[i].name_index - 1]);
|
print_constant(&class_file->constant_pool[class_file->fields[i].name_index - 1]);
|
||||||
debugf(" descriptor_index %d\n", class_file->fields[i].descriptor_index);
|
printf(" descriptor_index %d\n", class_file->fields[i].descriptor_index);
|
||||||
debugf(" ");
|
printf(" ");
|
||||||
print_constant(&class_file->constant_pool[class_file->fields[i].descriptor_index - 1]);
|
print_constant(&class_file->constant_pool[class_file->fields[i].descriptor_index - 1]);
|
||||||
debugf(" attributes_count %d\n", class_file->fields[i].attributes_count);
|
printf(" attributes_count %d\n", class_file->fields[i].attributes_count);
|
||||||
debugf(" attributes:\n");
|
printf(" attributes:\n");
|
||||||
for (int j = 0; j < class_file->fields[i].attributes_count; j++) {
|
for (int j = 0; j < class_file->fields[i].attributes_count; j++) {
|
||||||
debugf(" attribute %d:\n", j);
|
printf(" attribute %d:\n", j);
|
||||||
print_attribute(" ", &class_file->fields[i].attributes[j], class_file->constant_pool);
|
print_attribute(" ", &class_file->fields[i].attributes[j], class_file->constant_pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debugf("methods_count %d\n", class_file->methods_count);
|
printf("methods_count %d\n", class_file->methods_count);
|
||||||
debugf("methods:\n");
|
printf("methods:\n");
|
||||||
for (int i = 0; i < class_file->methods_count; i++) {
|
for (int i = 0; i < class_file->methods_count; i++) {
|
||||||
debugf(" method %d:\n", i);
|
printf(" method %d:\n", i);
|
||||||
debugf(" access_flags %04x\n", class_file->methods[i].access_flags);
|
printf(" access_flags %04x\n", class_file->methods[i].access_flags);
|
||||||
debugf(" name_index %d\n", class_file->methods[i].name_index);
|
printf(" name_index %d\n", class_file->methods[i].name_index);
|
||||||
debugf(" ");
|
printf(" ");
|
||||||
print_constant(&class_file->constant_pool[class_file->methods[i].name_index - 1]);
|
print_constant(&class_file->constant_pool[class_file->methods[i].name_index - 1]);
|
||||||
debugf(" descriptor_index %d\n", class_file->methods[i].descriptor_index);
|
printf(" descriptor_index %d\n", class_file->methods[i].descriptor_index);
|
||||||
debugf(" ");
|
printf(" ");
|
||||||
print_constant(&class_file->constant_pool[class_file->methods[i].descriptor_index - 1]);
|
print_constant(&class_file->constant_pool[class_file->methods[i].descriptor_index - 1]);
|
||||||
debugf(" attributes_count %d\n", class_file->methods[i].attributes_count);
|
printf(" attributes_count %d\n", class_file->methods[i].attributes_count);
|
||||||
debugf(" attributes:\n");
|
printf(" attributes:\n");
|
||||||
for (int j = 0; j < class_file->methods[i].attributes_count; j++) {
|
for (int j = 0; j < class_file->methods[i].attributes_count; j++) {
|
||||||
debugf(" attribute %d:\n", j);
|
printf(" attribute %d:\n", j);
|
||||||
print_attribute(" ", &class_file->methods[i].attributes[j], class_file->constant_pool);
|
print_attribute(" ", &class_file->methods[i].attributes[j], class_file->constant_pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
debugf("attributes_count %d\n", class_file->attributes_count);
|
printf("attributes_count %d\n", class_file->attributes_count);
|
||||||
debugf("attributes:\n");
|
printf("attributes:\n");
|
||||||
for (int i = 0; i < class_file->attributes_count; i++) {
|
for (int i = 0; i < class_file->attributes_count; i++) {
|
||||||
debugf(" attribute %d:\n", i);
|
printf(" attribute %d:\n", i);
|
||||||
print_attribute(" ", &class_file->attributes[i], class_file->constant_pool);
|
print_attribute(" ", &class_file->attributes[i], class_file->constant_pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,4 @@
|
|||||||
|
|
||||||
#include "class_file.h"
|
#include "class_file.h"
|
||||||
|
|
||||||
void print_utf8_string(struct constant * constant);
|
|
||||||
void print_constant(struct constant * constant);
|
|
||||||
void print_attribute(const char * indent, struct attribute_info * attribute, struct constant * constant_pool);
|
|
||||||
void print_class_file(struct class_file * class_file);
|
void print_class_file(struct class_file * class_file);
|
||||||
|
14
c/execute.c
14
c/execute.c
@ -7,6 +7,7 @@
|
|||||||
#include "field_size.h"
|
#include "field_size.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "parse_type.h"
|
#include "parse_type.h"
|
||||||
|
#include "backtrace.h"
|
||||||
|
|
||||||
void op_aaload(struct vm * vm)
|
void op_aaload(struct vm * vm)
|
||||||
{
|
{
|
||||||
@ -125,6 +126,7 @@ void op_astore_3(struct vm * vm)
|
|||||||
|
|
||||||
void op_athrow(struct vm * vm)
|
void op_athrow(struct vm * vm)
|
||||||
{
|
{
|
||||||
|
backtrace_print(vm);
|
||||||
assert(!"op_athrow");
|
assert(!"op_athrow");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +226,7 @@ void op_checkcast(struct vm * vm, uint32_t index)
|
|||||||
assert(class_constant->tag == CONSTANT_Class);
|
assert(class_constant->tag == CONSTANT_Class);
|
||||||
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
print_utf8_string(class_name_constant);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
debugf("\n");
|
debugf("\n");
|
||||||
|
|
||||||
// superclass lookup
|
// superclass lookup
|
||||||
@ -1193,7 +1195,7 @@ void op_instanceof(struct vm * vm, uint32_t index)
|
|||||||
assert(class_constant->tag == CONSTANT_Class);
|
assert(class_constant->tag == CONSTANT_Class);
|
||||||
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
print_utf8_string(class_name_constant);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
debugf("\n");
|
debugf("\n");
|
||||||
|
|
||||||
// superclass lookup
|
// superclass lookup
|
||||||
@ -1223,7 +1225,7 @@ void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count)
|
|||||||
class_entry,
|
class_entry,
|
||||||
vm->current_frame->class_entry);
|
vm->current_frame->class_entry);
|
||||||
|
|
||||||
vm_special_method_call(vm, method_entry.class_entry, method_entry.method_info);
|
vm_special_method_call(vm, method_entry.class_entry, &method_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void op_invokespecial(struct vm * vm, uint32_t index)
|
void op_invokespecial(struct vm * vm, uint32_t index)
|
||||||
@ -1234,7 +1236,7 @@ void op_invokespecial(struct vm * vm, uint32_t index)
|
|||||||
index,
|
index,
|
||||||
vm->current_frame->class_entry);
|
vm->current_frame->class_entry);
|
||||||
|
|
||||||
vm_special_method_call(vm, method_entry->class_entry, method_entry->method_info);
|
vm_special_method_call(vm, method_entry->class_entry, method_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void op_invokestatic(struct vm * vm, uint32_t index)
|
void op_invokestatic(struct vm * vm, uint32_t index)
|
||||||
@ -1249,7 +1251,7 @@ void op_invokestatic(struct vm * vm, uint32_t index)
|
|||||||
declared the resolved method is initialized if that class or interface has
|
declared the resolved method is initialized if that class or interface has
|
||||||
not already been initialized (§5.5). */
|
not already been initialized (§5.5). */
|
||||||
|
|
||||||
vm_static_method_call(vm, method_entry->class_entry, method_entry->method_info);
|
vm_static_method_call(vm, method_entry->class_entry, method_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -1283,7 +1285,7 @@ void op_invokevirtual(struct vm * vm, uint32_t index)
|
|||||||
class_entry,
|
class_entry,
|
||||||
vm->current_frame->class_entry);
|
vm->current_frame->class_entry);
|
||||||
|
|
||||||
vm_special_method_call(vm, method_entry.class_entry, method_entry.method_info);
|
vm_special_method_call(vm, method_entry.class_entry, &method_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void op_ior(struct vm * vm)
|
void op_ior(struct vm * vm)
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#include "debug_class_file.h"
|
|
||||||
|
|
||||||
static inline void class_entry_field_entry_from_constant_index(struct vm * vm,
|
static inline void class_entry_field_entry_from_constant_index(struct vm * vm,
|
||||||
int32_t index,
|
int32_t index,
|
||||||
struct class_entry ** class_entry,
|
struct class_entry ** class_entry,
|
||||||
|
55
c/find_attribute.c
Normal file
55
c/find_attribute.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include "assert.h"
|
||||||
|
#include "class_file.h"
|
||||||
|
#include "bytes.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "printf.h"
|
||||||
|
|
||||||
|
int find_code_name_index(struct class_file * class_file)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
|
||||||
|
struct constant * constant = &class_file->constant_pool[i];
|
||||||
|
if (constant->tag == CONSTANT_Utf8) {
|
||||||
|
if (constant_equal(constant, "Code")) {
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_constantvalue_name_index(struct class_file * class_file)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
|
||||||
|
struct constant * constant = &class_file->constant_pool[i];
|
||||||
|
if (constant->tag == CONSTANT_Utf8) {
|
||||||
|
if (constant_equal(constant, "ConstantValue")) {
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_linenumbertable_name_index(struct class_file * class_file)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
|
||||||
|
struct constant * constant = &class_file->constant_pool[i];
|
||||||
|
if (constant->tag == CONSTANT_Utf8) {
|
||||||
|
if (constant_equal(constant, "LineNumberTable")) {
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct attribute_info * find_attribute(int name_index,
|
||||||
|
int attributes_count,
|
||||||
|
struct attribute_info * attributes)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < attributes_count; i++) {
|
||||||
|
if (attributes[i].attribute_name_index == name_index)
|
||||||
|
return &attributes[i];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
10
c/find_attribute.h
Normal file
10
c/find_attribute.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "class_file.h"
|
||||||
|
|
||||||
|
int find_code_name_index(struct class_file * class_file);
|
||||||
|
int find_constantvalue_name_index(struct class_file * class_file);
|
||||||
|
int find_linenumbertable_name_index(struct class_file * class_file);
|
||||||
|
struct attribute_info * find_attribute(int name_index,
|
||||||
|
int attributes_count,
|
||||||
|
struct attribute_info * attributes);
|
162
c/frame.c
162
c/frame.c
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
#include "class_file.h"
|
#include "class_file.h"
|
||||||
#include "debug_class_file.h"
|
|
||||||
#include "bytes.h"
|
#include "bytes.h"
|
||||||
#include "decode.h"
|
#include "decode.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
@ -11,43 +10,8 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
#include "fatal.h"
|
#include "fatal.h"
|
||||||
|
#include "debug.h"
|
||||||
struct Code_attribute * get_code_attribute(int code_name_index,
|
#include "find_attribute.h"
|
||||||
int attributes_count,
|
|
||||||
struct attribute_info * attributes)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < attributes_count; i++) {
|
|
||||||
if (attributes[i].attribute_name_index == code_name_index)
|
|
||||||
return attributes[i].code;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int find_code_name_index(struct class_file * class_file)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < class_file->constant_pool_count; i++) {
|
|
||||||
struct constant * constant = &class_file->constant_pool[i];
|
|
||||||
if (constant->tag == CONSTANT_Utf8) {
|
|
||||||
if (bytes_equal(constant->utf8.length, constant->utf8.bytes, "Code")) {
|
|
||||||
return i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int find_constantvalue_name_index(struct class_file * class_file)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < class_file->constant_pool_count; i++) {
|
|
||||||
struct constant * constant = &class_file->constant_pool[i];
|
|
||||||
if (constant->tag == CONSTANT_Utf8) {
|
|
||||||
if (bytes_equal(constant->utf8.length, constant->utf8.bytes, "ConstantValue")) {
|
|
||||||
return i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type)
|
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type)
|
||||||
{
|
{
|
||||||
@ -56,7 +20,7 @@ int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_typ
|
|||||||
assert(descriptor_constant->utf8.bytes[0] == '(');
|
assert(descriptor_constant->utf8.bytes[0] == '(');
|
||||||
|
|
||||||
debugf("method descriptor: ");
|
debugf("method descriptor: ");
|
||||||
print_utf8_string(descriptor_constant);
|
debug_print__constant__utf8_string(descriptor_constant);
|
||||||
debugf("\n");
|
debugf("\n");
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
@ -107,7 +71,7 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
#endif
|
#endif
|
||||||
print_constant(class_name_constant);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
debugf("\n");
|
debugf("\n");
|
||||||
|
|
||||||
if (class_entry->initialization_state == CLASS_INITIALIZED)
|
if (class_entry->initialization_state == CLASS_INITIALIZED)
|
||||||
@ -164,27 +128,25 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
|
|||||||
/* Next, if C declares a class or interface initialization method, execute
|
/* Next, if C declares a class or interface initialization method, execute
|
||||||
that method. */
|
that method. */
|
||||||
const uint8_t * method_name = (const uint8_t *)"<clinit>";
|
const uint8_t * method_name = (const uint8_t *)"<clinit>";
|
||||||
int method_name_length = 8;
|
int method_name_length = string_length((const char *)method_name);
|
||||||
const uint8_t * method_descriptor = (const uint8_t *)"()V";
|
const uint8_t * method_descriptor = (const uint8_t *)"()V";
|
||||||
int method_descriptor_length = 3;
|
int method_descriptor_length = string_length((const char *)method_descriptor);
|
||||||
|
|
||||||
int methods_hash_table_length = class_entry->methods.length;
|
struct method_entry method_entry =
|
||||||
struct hash_table_entry * methods_hash_table = class_entry->methods.entry;
|
class_resolver_lookup_method_from_method_name_method_descriptor(class_entry,
|
||||||
|
|
||||||
struct method_info * method_info = class_resolver_lookup_method(methods_hash_table_length,
|
|
||||||
methods_hash_table,
|
|
||||||
method_name,
|
method_name,
|
||||||
method_name_length,
|
method_name_length,
|
||||||
method_descriptor,
|
method_descriptor,
|
||||||
method_descriptor_length);
|
method_descriptor_length);
|
||||||
if (method_info != nullptr) {
|
|
||||||
assert((method_info->access_flags & METHOD_ACC_STATIC) != 0);
|
if (method_entry.method_info != nullptr) {
|
||||||
|
assert((method_entry.method_info->access_flags & METHOD_ACC_STATIC) != 0);
|
||||||
debugf("<clinit>\n");
|
debugf("<clinit>\n");
|
||||||
|
|
||||||
// tamper with next_pc
|
// tamper with next_pc
|
||||||
vm->current_frame->next_pc = vm->current_frame->pc;
|
vm->current_frame->next_pc = vm->current_frame->pc;
|
||||||
|
|
||||||
vm_static_method_call(vm, class_entry, method_info);
|
vm_static_method_call(vm, class_entry, &method_entry);
|
||||||
|
|
||||||
vm->current_frame->initialization_frame = 1;
|
vm->current_frame->initialization_frame = 1;
|
||||||
return false;
|
return false;
|
||||||
@ -196,9 +158,9 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info, int nargs, uint8_t return_type)
|
void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry, int nargs, uint8_t return_type)
|
||||||
{
|
{
|
||||||
debugf("vm_static_native_method_call: nargs %d\n", nargs);
|
debugf("vm_native_method_call: nargs %d\n", nargs);
|
||||||
|
|
||||||
uint32_t args[nargs];
|
uint32_t args[nargs];
|
||||||
for (int i = 0; i < nargs; i++) {
|
for (int i = 0; i < nargs; i++) {
|
||||||
@ -210,10 +172,10 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str
|
|||||||
debugf("native:\n ");
|
debugf("native:\n ");
|
||||||
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
|
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
|
||||||
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
print_constant(class_name_constant);
|
debug_print__constant__utf8_string(class_name_constant);
|
||||||
debugf(" ");
|
debugf(" ");
|
||||||
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_info->name_index - 1];
|
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_entry->method_info->name_index - 1];
|
||||||
print_constant(method_name_constant);
|
debug_print__constant__utf8_string(method_name_constant);
|
||||||
|
|
||||||
|
|
||||||
int java_lang_math_length = 14;
|
int java_lang_math_length = 14;
|
||||||
@ -360,22 +322,15 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str
|
|||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info, int nargs, uint8_t return_type)
|
void vm_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry, int nargs, uint8_t return_type)
|
||||||
{
|
{
|
||||||
int code_name_index = find_code_name_index(class_entry->class_file);
|
assert(method_entry->code_attribute != nullptr);
|
||||||
assert(code_name_index > 0);
|
|
||||||
|
|
||||||
struct Code_attribute * code = get_code_attribute(code_name_index,
|
|
||||||
method_info->attributes_count,
|
|
||||||
method_info->attributes);
|
|
||||||
assert(code != nullptr);
|
|
||||||
|
|
||||||
struct frame * old_frame = vm->current_frame;
|
struct frame * old_frame = vm->current_frame;
|
||||||
|
|
||||||
vm->current_frame = stack_push_frame(&vm->frame_stack, 1);
|
vm->current_frame = stack_push_frame(&vm->frame_stack, 1);
|
||||||
vm->current_frame->code = code;
|
vm->current_frame->local_variable = stack_push_data(&vm->data_stack, method_entry->code_attribute->max_locals);
|
||||||
vm->current_frame->local_variable = stack_push_data(&vm->data_stack, code->max_locals);
|
vm->current_frame->operand_stack = stack_push_data(&vm->data_stack, method_entry->code_attribute->max_stack);
|
||||||
vm->current_frame->operand_stack = stack_push_data(&vm->data_stack, code->max_stack);
|
|
||||||
vm->current_frame->operand_stack_ix = 0;
|
vm->current_frame->operand_stack_ix = 0;
|
||||||
vm->current_frame->initialization_frame = 0;
|
vm->current_frame->initialization_frame = 0;
|
||||||
vm->current_frame->return_type = return_type;
|
vm->current_frame->return_type = return_type;
|
||||||
@ -389,12 +344,13 @@ void vm_method_call(struct vm * vm, struct class_entry * class_entry, struct met
|
|||||||
vm->current_frame->pc = 0;
|
vm->current_frame->pc = 0;
|
||||||
vm->current_frame->next_pc = 0;
|
vm->current_frame->next_pc = 0;
|
||||||
vm->current_frame->class_entry = class_entry;
|
vm->current_frame->class_entry = class_entry;
|
||||||
vm->current_frame->method = method_info;
|
vm->current_frame->method_info = method_entry->method_info;
|
||||||
|
vm->current_frame->code_attribute = method_entry->code_attribute;
|
||||||
|
|
||||||
debugf("operand_stack_ix: %d\n", vm->current_frame->operand_stack_ix);
|
debugf("operand_stack_ix: %d\n", vm->current_frame->operand_stack_ix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info)
|
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry)
|
||||||
{
|
{
|
||||||
/* If the method is not native, the nargs argument values are popped from the
|
/* If the method is not native, the nargs argument values are popped from the
|
||||||
operand stack. A new frame is created on the Java Virtual Machine stack for
|
operand stack. A new frame is created on the Java Virtual Machine stack for
|
||||||
@ -407,19 +363,19 @@ void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, st
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
uint8_t return_type;
|
uint8_t return_type;
|
||||||
struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1];
|
struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_entry->method_info->descriptor_index - 1];
|
||||||
int nargs = descriptor_nargs(descriptor_constant, &return_type);
|
int nargs = descriptor_nargs(descriptor_constant, &return_type);
|
||||||
nargs += 1;
|
nargs += 1;
|
||||||
debugf("nargs+1: %d\n", nargs);
|
debugf("nargs+1: %d\n", nargs);
|
||||||
|
|
||||||
if (method_info->access_flags & METHOD_ACC_NATIVE) {
|
if (method_entry->method_info->access_flags & METHOD_ACC_NATIVE) {
|
||||||
vm_native_method_call(vm, class_entry, method_info, nargs, return_type);
|
vm_native_method_call(vm, class_entry, method_entry, nargs, return_type);
|
||||||
} else {
|
} else {
|
||||||
vm_method_call(vm, class_entry, method_info, nargs, return_type);
|
vm_method_call(vm, class_entry, method_entry, nargs, return_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info)
|
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry)
|
||||||
{
|
{
|
||||||
/* If the method is not native, the nargs argument values are popped from the
|
/* If the method is not native, the nargs argument values are popped from the
|
||||||
operand stack. A new frame is created on the Java Virtual Machine stack for
|
operand stack. A new frame is created on the Java Virtual Machine stack for
|
||||||
@ -432,14 +388,14 @@ void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, str
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
uint8_t return_type;
|
uint8_t return_type;
|
||||||
struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1];
|
struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_entry->method_info->descriptor_index - 1];
|
||||||
int nargs = descriptor_nargs(descriptor_constant, &return_type);
|
int nargs = descriptor_nargs(descriptor_constant, &return_type);
|
||||||
debugf("nargs %d\n", nargs);
|
debugf("nargs %d\n", nargs);
|
||||||
|
|
||||||
if (method_info->access_flags & METHOD_ACC_NATIVE) {
|
if (method_entry->method_info->access_flags & METHOD_ACC_NATIVE) {
|
||||||
vm_native_method_call(vm, class_entry, method_info, nargs, return_type);
|
vm_native_method_call(vm, class_entry, method_entry, nargs, return_type);
|
||||||
} else {
|
} else {
|
||||||
vm_method_call(vm, class_entry, method_info, nargs, return_type);
|
vm_method_call(vm, class_entry, method_entry, nargs, return_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,8 +409,8 @@ void vm_method_return(struct vm * vm)
|
|||||||
|
|
||||||
struct frame * old_frame = vm->current_frame;
|
struct frame * old_frame = vm->current_frame;
|
||||||
|
|
||||||
stack_pop_data(&vm->data_stack, old_frame->code->max_locals);
|
stack_pop_data(&vm->data_stack, old_frame->code_attribute->max_locals);
|
||||||
stack_pop_data(&vm->data_stack, old_frame->code->max_stack);
|
stack_pop_data(&vm->data_stack, old_frame->code_attribute->max_stack);
|
||||||
|
|
||||||
vm->current_frame = stack_pop_frame(&vm->frame_stack, 1);
|
vm->current_frame = stack_pop_frame(&vm->frame_stack, 1);
|
||||||
assert(vm->current_frame != old_frame);
|
assert(vm->current_frame != old_frame);
|
||||||
@ -537,22 +493,14 @@ static void print_vm_stack(struct vm * vm)
|
|||||||
void vm_execute(struct vm * vm)
|
void vm_execute(struct vm * vm)
|
||||||
{
|
{
|
||||||
while (true) {
|
while (true) {
|
||||||
assert(vm->current_frame->pc < vm->current_frame->code->code_length);
|
assert(vm->current_frame->pc < vm->current_frame->code_attribute->code_length);
|
||||||
print_vm_stack(vm);
|
print_vm_stack(vm);
|
||||||
decode_print_instruction(vm->current_frame->code->code, vm->current_frame->pc);
|
decode_print_instruction(vm->current_frame->code_attribute->code, vm->current_frame->pc);
|
||||||
//uint32_t old_pc = vm->current_frame->pc;
|
decode_execute_instruction(vm, vm->current_frame->code_attribute->code, vm->current_frame->pc);
|
||||||
//struct method_info * old_method = vm->current_frame->method;
|
if (vm->frame_stack.ix == 0) {
|
||||||
decode_execute_instruction(vm, vm->current_frame->code->code, vm->current_frame->pc);
|
|
||||||
if (vm->frame_stack.ix == 1) {
|
|
||||||
debugf("terminate\n");
|
debugf("terminate\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (vm->current_frame->method == old_method && vm->current_frame->pc == old_pc) {
|
|
||||||
// if the instruction did not branch, increment pc
|
|
||||||
vm->current_frame->pc = vm->current_frame->next_pc;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
vm->current_frame->pc = vm->current_frame->next_pc;
|
vm->current_frame->pc = vm->current_frame->next_pc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -567,21 +515,18 @@ struct vm * vm_start(int class_hash_table_length,
|
|||||||
main_class_name,
|
main_class_name,
|
||||||
main_class_name_length);
|
main_class_name_length);
|
||||||
|
|
||||||
const char * method_name = "main";
|
const uint8_t * method_name = (const uint8_t *)"main";
|
||||||
int method_name_length = string_length(method_name);
|
int method_name_length = string_length((const char *)method_name);
|
||||||
const char * method_descriptor = "()V";
|
const uint8_t * method_descriptor = (const uint8_t *)"()V";
|
||||||
int method_descriptor_length = string_length(method_descriptor);
|
int method_descriptor_length = string_length((const char *)method_descriptor);
|
||||||
|
|
||||||
int methods_hash_table_length = class_entry->methods.length;
|
struct method_entry method_entry =
|
||||||
struct hash_table_entry * methods_hash_table = class_entry->methods.entry;
|
class_resolver_lookup_method_from_method_name_method_descriptor(class_entry,
|
||||||
|
method_name,
|
||||||
struct method_info * method_info = class_resolver_lookup_method(methods_hash_table_length,
|
|
||||||
methods_hash_table,
|
|
||||||
(const uint8_t *)method_name,
|
|
||||||
method_name_length,
|
method_name_length,
|
||||||
(const uint8_t *)method_descriptor,
|
method_descriptor,
|
||||||
method_descriptor_length);
|
method_descriptor_length);
|
||||||
assert(method_info != nullptr);
|
assert(method_entry.method_info != nullptr);
|
||||||
|
|
||||||
static struct vm vm;
|
static struct vm vm;
|
||||||
vm.class_hash_table.entry = class_hash_table;
|
vm.class_hash_table.entry = class_hash_table;
|
||||||
@ -597,16 +542,7 @@ struct vm * vm_start(int class_hash_table_length,
|
|||||||
uint32_t data[vm.data_stack.capacity];
|
uint32_t data[vm.data_stack.capacity];
|
||||||
vm.data_stack.data = data;
|
vm.data_stack.data = data;
|
||||||
|
|
||||||
struct frame * entry_frame = stack_push_frame(&vm.frame_stack, 1);
|
vm_static_method_call(&vm, class_entry, &method_entry);
|
||||||
struct Code_attribute code;
|
|
||||||
code.max_locals = 0;
|
|
||||||
code.max_stack = 0;
|
|
||||||
entry_frame->code = &code;
|
|
||||||
entry_frame->local_variable = 0;
|
|
||||||
entry_frame->operand_stack = 0;
|
|
||||||
entry_frame->operand_stack_ix = 0;
|
|
||||||
|
|
||||||
vm_static_method_call(&vm, class_entry, method_info);
|
|
||||||
|
|
||||||
return &vm;
|
return &vm;
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
struct frame {
|
struct frame {
|
||||||
struct class_entry * class_entry;
|
struct class_entry * class_entry;
|
||||||
struct method_info * method;
|
struct method_info * method_info;
|
||||||
struct Code_attribute * code;
|
struct Code_attribute * code_attribute;
|
||||||
uint32_t * local_variable;
|
uint32_t * local_variable;
|
||||||
uint32_t * operand_stack;
|
uint32_t * operand_stack;
|
||||||
uint32_t pc;
|
uint32_t pc;
|
||||||
@ -156,8 +156,8 @@ static inline double operand_stack_pop_f64(struct frame * frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry);
|
bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry);
|
||||||
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info);
|
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);
|
||||||
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info);
|
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);
|
||||||
void vm_method_return(struct vm * vm);
|
void vm_method_return(struct vm * vm);
|
||||||
void vm_execute(struct vm * vm);
|
void vm_execute(struct vm * vm);
|
||||||
struct vm * vm_start(int class_hash_table_length,
|
struct vm * vm_start(int class_hash_table_length,
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "memory_allocator.h"
|
#include "memory_allocator.h"
|
||||||
|
#include "backtrace.h"
|
||||||
|
|
||||||
static struct hash_table_entry * load_from_filenames(const char * filenames[], int length, int * hash_table_length)
|
static struct hash_table_entry * load_from_filenames(const char * filenames[], int length, int * hash_table_length)
|
||||||
{
|
{
|
||||||
@ -53,5 +54,8 @@ int main(int argc, const char * argv[])
|
|||||||
class_hash_table,
|
class_hash_table,
|
||||||
main_class,
|
main_class,
|
||||||
main_class_length);
|
main_class_length);
|
||||||
|
|
||||||
|
backtrace_print(vm);
|
||||||
|
|
||||||
vm_execute(vm);
|
vm_execute(vm);
|
||||||
}
|
}
|
||||||
|
4
java.mk
4
java.mk
@ -20,7 +20,9 @@ OBJ = \
|
|||||||
c/native.o \
|
c/native.o \
|
||||||
c/debug.o \
|
c/debug.o \
|
||||||
c/fatal.o \
|
c/fatal.o \
|
||||||
c/parse_type.o
|
c/parse_type.o \
|
||||||
|
c/backtrace.o \
|
||||||
|
c/find_attribute.o
|
||||||
|
|
||||||
MAIN_DREAMCAST_OBJ = \
|
MAIN_DREAMCAST_OBJ = \
|
||||||
c/main_dreamcast.o \
|
c/main_dreamcast.o \
|
||||||
|
20
java/lang/Exception.java
Normal file
20
java/lang/Exception.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package java.lang;
|
||||||
|
|
||||||
|
public class Exception extends Throwable {
|
||||||
|
|
||||||
|
public Exception() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
}
|
23
java/lang/Throwable.java
Normal file
23
java/lang/Throwable.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package java.lang;
|
||||||
|
|
||||||
|
public class Throwable {
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
private Throwable cause = this;
|
||||||
|
|
||||||
|
public Throwable() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Throwable(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Throwable(String message, Throwable cause) {
|
||||||
|
this.message = message;
|
||||||
|
this.cause = cause;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Throwable(Throwable cause) {
|
||||||
|
this.cause = cause;
|
||||||
|
}
|
||||||
|
}
|
11
p/TestException.java
Normal file
11
p/TestException.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package p;
|
||||||
|
|
||||||
|
class TestException {
|
||||||
|
static void test() throws Exception {
|
||||||
|
throw new Exception("asdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main() throws Exception {
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user