backtrace / code_attribute / method_entry refactor

This commit is contained in:
Zack Buhman 2025-01-05 16:37:44 -06:00
parent 16db74a16a
commit d101710e0f
23 changed files with 638 additions and 359 deletions

13
.gitignore vendored
View File

@ -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
View 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
View File

@ -0,0 +1,5 @@
#pragma once
#include "frame.h"
void backtrace_print(struct vm * vm);

View File

@ -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);
}

View File

@ -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;
} }

View File

@ -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).

View File

@ -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,

View File

@ -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,

View File

@ -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);
} }

View File

@ -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);

View File

@ -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);
} }
} }

View File

@ -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);

View File

@ -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)

View File

@ -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
View 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
View 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
View File

@ -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;
} }

View File

@ -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,

View File

@ -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);
} }

View File

@ -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
View 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
View 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
View 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();
}
}