From 47fc2b90e2f6e838384f74bf8879d44905b174ac Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sun, 5 Jan 2025 21:47:13 -0600 Subject: [PATCH] implement backtrace allocation / printing --- c/backtrace.c | 83 +++++++++++++++++++++++++++------------- c/backtrace.h | 15 +++++++- c/class_resolver.c | 8 ++-- c/debug.c | 24 ++++++------ c/debug.h | 8 ++-- c/execute.c | 4 +- c/find_attribute.c | 4 +- c/frame.c | 19 ++++++--- c/main_hosted.c | 2 - java/lang/Throwable.java | 2 +- p/TestException.java | 10 ++--- 11 files changed, 115 insertions(+), 64 deletions(-) diff --git a/c/backtrace.c b/c/backtrace.c index 71708b0..7aa73b8 100644 --- a/c/backtrace.c +++ b/c/backtrace.c @@ -2,35 +2,66 @@ #include "printf.h" #include "debug.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--) { - 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); + struct backtrace * backtrace = memory_allocate((sizeof (struct backtrace))); + backtrace->num_entries = vm->frame_stack.ix; + int backtrace_entries_size = (sizeof (struct backtrace_entry)) * backtrace->num_entries; + backtrace->entry = memory_allocate(backtrace_entries_size); - 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; - } + for (int i = (vm->frame_stack.ix - 1); i >= 0; i--) { + struct frame * frame = &vm->frame_stack.frame[i]; + backtrace->entry[i].class_file = frame->class_entry->class_file; + backtrace->entry[i].method_info = frame->method_info; + backtrace->entry[i].pc = frame->pc; + } + return backtrace; +} + +static int get_line_number(struct class_file * class_file, struct method_info * method_info, int pc) +{ + int code_index = find_code_name_index(class_file); + 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); } } diff --git a/c/backtrace.h b/c/backtrace.h index 2eb9099..9dbb88a 100644 --- a/c/backtrace.h +++ b/c/backtrace.h @@ -2,4 +2,17 @@ #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); diff --git a/c/class_resolver.c b/c/class_resolver.c index 4165842..e4819b4 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -427,9 +427,9 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i if (method_info != nullptr) { debugf("method resolved:\n"); debugf(" class: "); - debug_print__class_entry__class_name(class_entry); + debug_print__class_file__class_name(class_entry->class_file); 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'); 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 debugf("method resolved:\n"); debugf(" class: "); - debug_print__class_entry__class_name(class_entry); + debug_print__class_file__class_name(class_entry->class_file); 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'); struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry))); diff --git a/c/debug.c b/c/debug.c index dc10baf..e5545ac 100644 --- a/c/debug.c +++ b/c/debug.c @@ -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); - 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); } @@ -32,10 +32,10 @@ void debug_print__constant__method_name(struct constant * name_constant, struct 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_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1]; + struct constant * method_name_constant = &class_file->constant_pool[method_info->name_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); } @@ -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); - 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); } @@ -62,9 +62,9 @@ void print__constant__method_name(struct constant * name_constant, struct consta 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_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1]; + struct constant * method_name_constant = &class_file->constant_pool[method_info->name_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); } diff --git a/c/debug.h b/c/debug.h index 408fa37..face1d8 100644 --- a/c/debug.h +++ b/c/debug.h @@ -5,11 +5,11 @@ void debug_print__string(const uint8_t * bytes, int length); 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__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__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__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); diff --git a/c/execute.c b/c/execute.c index 2d752e7..ae6a122 100644 --- a/c/execute.c +++ b/c/execute.c @@ -209,8 +209,8 @@ void op_checkcast(struct vm * vm, uint32_t index) } struct class_entry * class_entry = (struct class_entry *)objectref[0]; - debug_print__class_entry__class_name(index_class_entry); - debug_print__class_entry__class_name(class_entry); + debug_print__class_file__class_name(index_class_entry->class_file); + debug_print__class_file__class_name(class_entry->class_file); while (true) { assert(class_entry != nullptr); diff --git a/c/find_attribute.c b/c/find_attribute.c index 0a0abbb..437568f 100644 --- a/c/find_attribute.c +++ b/c/find_attribute.c @@ -47,9 +47,9 @@ struct attribute_info * find_attribute(int name_index, int attributes_count, 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++) { - 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) return &attributes[i]; } diff --git a/c/frame.c b/c/frame.c index 8d76660..f96feab 100644 --- a/c/frame.c +++ b/c/frame.c @@ -475,9 +475,9 @@ void vm_method_return(struct vm * vm) if (vm->frame_stack.ix > 0) { debugs("vm_method_return\n"); 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: "); - 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 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. 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) { 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]; @@ -497,9 +503,9 @@ void vm_exception(struct vm * vm, int32_t * objectref) debugs("vm_exception (handled)\n"); 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: "); - 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 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); } - backtrace_print(vm); + + assert(objectref[1] != 0); + backtrace_print((struct backtrace *)objectref[1]); + assert(!"exception"); } diff --git a/c/main_hosted.c b/c/main_hosted.c index 101a367..3ee43f3 100644 --- a/c/main_hosted.c +++ b/c/main_hosted.c @@ -55,7 +55,5 @@ int main(int argc, const char * argv[]) main_class, main_class_length); - backtrace_print(vm); - vm_execute(vm); } diff --git a/java/lang/Throwable.java b/java/lang/Throwable.java index 2eb6c35..43f02cd 100644 --- a/java/lang/Throwable.java +++ b/java/lang/Throwable.java @@ -1,7 +1,7 @@ package java.lang; public class Throwable { - + private Object backtrace; private String message; private Throwable cause = this; diff --git a/p/TestException.java b/p/TestException.java index 19984a6..c4ec118 100644 --- a/p/TestException.java +++ b/p/TestException.java @@ -6,12 +6,12 @@ class TestException { } static void test() throws Exception { - try { + // try { test2(); - } catch (Exception e) { - System.out.println(e); - throw e; - } + //} catch (Exception e) { + //System.out.println(e); + //throw e; + //} } public static void main() throws Exception {