implement backtrace allocation / printing

This commit is contained in:
Zack Buhman 2025-01-05 21:47:13 -06:00
parent 7914abe702
commit 47fc2b90e2
11 changed files with 115 additions and 64 deletions

View File

@ -2,35 +2,66 @@
#include "printf.h" #include "printf.h"
#include "debug.h" #include "debug.h"
#include "find_attribute.h" #include "find_attribute.h"
#include "memory_allocator.h"
void backtrace_print(struct vm * vm) struct backtrace * backtrace_allocate(struct vm * vm)
{ {
for (int i = (vm->frame_stack.ix - 1); i >= 0; i--) { struct backtrace * backtrace = memory_allocate((sizeof (struct backtrace)));
printf("ix %d\n", i); backtrace->num_entries = vm->frame_stack.ix;
struct frame * frame = &vm->frame_stack.frame[i]; int backtrace_entries_size = (sizeof (struct backtrace_entry)) * backtrace->num_entries;
printf(" class: "); backtrace->entry = memory_allocate(backtrace_entries_size);
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); for (int i = (vm->frame_stack.ix - 1); i >= 0; i--) {
struct attribute_info * attribute_info = find_attribute(linenumbertable_name_index, struct frame * frame = &vm->frame_stack.frame[i];
frame->code_attribute->attributes_count, backtrace->entry[i].class_file = frame->class_entry->class_file;
frame->code_attribute->attributes); backtrace->entry[i].method_info = frame->method_info;
assert(attribute_info != nullptr); backtrace->entry[i].pc = frame->pc;
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; return backtrace;
int line_number = 0; }
for (int i = 0; i < line_number_table_length; i++) {
if (frame->pc >= line_number_table[i].start_pc) { static int get_line_number(struct class_file * class_file, struct method_info * method_info, int pc)
line_number = line_number_table[i].line_number; {
} else { int code_index = find_code_name_index(class_file);
break; assert(code_index != 0);
} struct attribute_info * attribute = find_attribute(code_index,
method_info->attributes_count,
method_info->attributes);
assert(attribute != nullptr);
struct Code_attribute * code_attribute = attribute->code;
int linenumbertable_name_index = find_linenumbertable_name_index(class_file);
struct attribute_info * attribute_info = find_attribute(linenumbertable_name_index,
code_attribute->attributes_count,
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 (pc >= line_number_table[i].start_pc) {
line_number = line_number_table[i].line_number;
} else {
break;
} }
printf(" line_number: %d\n", line_number); }
return line_number;
}
void backtrace_print(struct backtrace * backtrace)
{
prints("backtrace:\n");
for (int i = (backtrace->num_entries - 1); i >= 0; i--) {
struct backtrace_entry * backtrace_entry = &backtrace->entry[i];
prints(" class: ");
print__class_file__class_name(backtrace_entry->class_file);
prints(" method: ");
print__method_info__method_name(backtrace_entry->class_file, backtrace_entry->method_info);
printc('\n');
printf(" pc: %3d ", backtrace_entry->pc);
int line_number = get_line_number(backtrace_entry->class_file,
backtrace_entry->method_info,
backtrace_entry->pc);
printf(" line_number: %3d\n", line_number);
} }
} }

View File

@ -2,4 +2,17 @@
#include "frame.h" #include "frame.h"
void backtrace_print(struct vm * vm); struct backtrace_entry {
struct class_file * class_file;
struct method_info * method_info;
int pc;
};
struct backtrace {
int num_entries;
struct backtrace_entry * entry;
};
struct backtrace * backtrace_allocate(struct vm * vm);
void backtrace_print(struct backtrace * backtrace);

View File

@ -427,9 +427,9 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
if (method_info != nullptr) { if (method_info != nullptr) {
debugf("method resolved:\n"); debugf("method resolved:\n");
debugf(" class: "); debugf(" class: ");
debug_print__class_entry__class_name(class_entry); debug_print__class_file__class_name(class_entry->class_file);
debugf("\n method: "); debugf("\n method: ");
debug_print__method_info__method_name(class_entry, method_info); debug_print__method_info__method_name(class_entry->class_file, method_info);
debugc('\n'); debugc('\n');
int code_index = find_code_name_index(class_entry->class_file); int code_index = find_code_name_index(class_entry->class_file);
@ -502,9 +502,9 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
// cache the result // cache the result
debugf("method resolved:\n"); debugf("method resolved:\n");
debugf(" class: "); debugf(" class: ");
debug_print__class_entry__class_name(class_entry); debug_print__class_file__class_name(class_entry->class_file);
debugf("\n method: "); debugf("\n method: ");
debug_print__method_info__method_name(class_entry, method_info); debug_print__method_info__method_name(class_entry->class_file, method_info);
debugc('\n'); debugc('\n');
struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry))); struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry)));

View File

@ -17,11 +17,11 @@ 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_file__class_name(struct class_file * class_file)
{ {
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1]; struct constant * class_constant = &class_file->constant_pool[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_file->constant_pool[class_constant->class.name_index - 1];
debug_print__constant__utf8_string(class_name_constant); debug_print__constant__utf8_string(class_name_constant);
} }
@ -32,10 +32,10 @@ void debug_print__constant__method_name(struct constant * name_constant, struct
debug_print__constant__utf8_string(descriptor_constant); 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_file * class_file, 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_file->constant_pool[method_info->name_index - 1];
struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1]; struct constant * method_descriptor_constant = &class_file->constant_pool[method_info->descriptor_index - 1];
debug_print__constant__method_name(method_name_constant, method_descriptor_constant); debug_print__constant__method_name(method_name_constant, method_descriptor_constant);
} }
@ -47,11 +47,11 @@ void print__constant__utf8_string(struct constant * constant)
} }
} }
void print__class_entry__class_name(struct class_entry * class_entry) void print__class_file__class_name(struct class_file * class_file)
{ {
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1]; struct constant * class_constant = &class_file->constant_pool[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_file->constant_pool[class_constant->class.name_index - 1];
print__constant__utf8_string(class_name_constant); print__constant__utf8_string(class_name_constant);
} }
@ -62,9 +62,9 @@ void print__constant__method_name(struct constant * name_constant, struct consta
print__constant__utf8_string(descriptor_constant); print__constant__utf8_string(descriptor_constant);
} }
void print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info) void print__method_info__method_name(struct class_file * class_file, 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_file->constant_pool[method_info->name_index - 1];
struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1]; struct constant * method_descriptor_constant = &class_file->constant_pool[method_info->descriptor_index - 1];
print__constant__method_name(method_name_constant, method_descriptor_constant); print__constant__method_name(method_name_constant, method_descriptor_constant);
} }

View File

@ -5,11 +5,11 @@
void debug_print__string(const uint8_t * bytes, int length); 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_file__class_name(struct class_file * class_file);
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 debug_print__method_info__method_name(struct class_file * class_file, struct method_info * method_info);
void print__constant__utf8_string(struct constant * constant); void print__constant__utf8_string(struct constant * constant);
void print__class_entry__class_name(struct class_entry * class_entry); void print__class_file__class_name(struct class_file * class_file);
void print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant); 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); void print__method_info__method_name(struct class_file * class_file, struct method_info * method_info);

View File

@ -209,8 +209,8 @@ void op_checkcast(struct vm * vm, uint32_t index)
} }
struct class_entry * class_entry = (struct class_entry *)objectref[0]; struct class_entry * class_entry = (struct class_entry *)objectref[0];
debug_print__class_entry__class_name(index_class_entry); debug_print__class_file__class_name(index_class_entry->class_file);
debug_print__class_entry__class_name(class_entry); debug_print__class_file__class_name(class_entry->class_file);
while (true) { while (true) {
assert(class_entry != nullptr); assert(class_entry != nullptr);

View File

@ -47,9 +47,9 @@ struct attribute_info * find_attribute(int name_index,
int attributes_count, int attributes_count,
struct attribute_info * attributes) struct attribute_info * attributes)
{ {
debugf("find_attribute: name_index=%d attributes_count=%d\n", name_index, attributes_count); //debugf("find_attribute: name_index=%d attributes_count=%d\n", name_index, attributes_count);
for (int i = 0; i < attributes_count; i++) { for (int i = 0; i < attributes_count; i++) {
debugf("find_attribute: attribute[%d]: %d\n", i, attributes[i].attribute_name_index); //debugf("find_attribute: attribute[%d]: %d\n", i, attributes[i].attribute_name_index);
if (attributes[i].attribute_name_index == name_index) if (attributes[i].attribute_name_index == name_index)
return &attributes[i]; return &attributes[i];
} }

View File

@ -475,9 +475,9 @@ void vm_method_return(struct vm * vm)
if (vm->frame_stack.ix > 0) { if (vm->frame_stack.ix > 0) {
debugs("vm_method_return\n"); debugs("vm_method_return\n");
debugs("current_frame:\n class: "); debugs("current_frame:\n class: ");
debug_print__class_entry__class_name(vm->current_frame->class_entry); debug_print__class_file__class_name(vm->current_frame->class_entry->class_file);
debugs("\n method: "); debugs("\n method: ");
debug_print__method_info__method_name(vm->current_frame->class_entry, vm->current_frame->method_info); debug_print__method_info__method_name(vm->current_frame->class_entry->class_file, vm->current_frame->method_info);
debugf("\n pc: %d", vm->current_frame->pc); debugf("\n pc: %d", vm->current_frame->pc);
debugf("\n next_pc: %d\n", vm->current_frame->next_pc); debugf("\n next_pc: %d\n", vm->current_frame->next_pc);
} }
@ -488,6 +488,12 @@ void vm_exception(struct vm * vm, int32_t * objectref)
// If objectref is null, athrow throws a NullPointerException instead of objectref. // If objectref is null, athrow throws a NullPointerException instead of objectref.
assert(objectref != nullptr); assert(objectref != nullptr);
struct class_entry * exception_class_entry = (struct class_entry *)objectref[0];
if (objectref[1] == 0) {
struct backtrace * backtrace = backtrace_allocate(vm);
objectref[1] = (int32_t)backtrace;
}
while (vm->frame_stack.ix > 0) { while (vm->frame_stack.ix > 0) {
for (int i = 0; i < vm->current_frame->code_attribute->exception_table_length; i++) { for (int i = 0; i < vm->current_frame->code_attribute->exception_table_length; i++) {
struct exception_table_entry * entry = &vm->current_frame->code_attribute->exception_table[i]; struct exception_table_entry * entry = &vm->current_frame->code_attribute->exception_table[i];
@ -497,9 +503,9 @@ void vm_exception(struct vm * vm, int32_t * objectref)
debugs("vm_exception (handled)\n"); debugs("vm_exception (handled)\n");
debugs("current_frame:\n class: "); debugs("current_frame:\n class: ");
debug_print__class_entry__class_name(vm->current_frame->class_entry); debug_print__class_file__class_name(vm->current_frame->class_entry->class_file);
debugs("\n method: "); debugs("\n method: ");
debug_print__method_info__method_name(vm->current_frame->class_entry, vm->current_frame->method_info); debug_print__method_info__method_name(vm->current_frame->class_entry->class_file, vm->current_frame->method_info);
debugf("\n pc: %d", vm->current_frame->pc); debugf("\n pc: %d", vm->current_frame->pc);
debugf("\n next_pc: %d\n", vm->current_frame->next_pc); debugf("\n next_pc: %d\n", vm->current_frame->next_pc);
@ -508,7 +514,10 @@ void vm_exception(struct vm * vm, int32_t * objectref)
} }
vm->current_frame = stack_pop_frame(&vm->frame_stack, 1); vm->current_frame = stack_pop_frame(&vm->frame_stack, 1);
} }
backtrace_print(vm);
assert(objectref[1] != 0);
backtrace_print((struct backtrace *)objectref[1]);
assert(!"exception"); assert(!"exception");
} }

View File

@ -55,7 +55,5 @@ int main(int argc, const char * argv[])
main_class, main_class,
main_class_length); main_class_length);
backtrace_print(vm);
vm_execute(vm); vm_execute(vm);
} }

View File

@ -1,7 +1,7 @@
package java.lang; package java.lang;
public class Throwable { public class Throwable {
private Object backtrace;
private String message; private String message;
private Throwable cause = this; private Throwable cause = this;

View File

@ -6,12 +6,12 @@ class TestException {
} }
static void test() throws Exception { static void test() throws Exception {
try { // try {
test2(); test2();
} catch (Exception e) { //} catch (Exception e) {
System.out.println(e); //System.out.println(e);
throw e; //throw e;
} //}
} }
public static void main() throws Exception { public static void main() throws Exception {