implement backtrace allocation / printing
This commit is contained in:
parent
7914abe702
commit
47fc2b90e2
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)));
|
||||
|
24
c/debug.c
24
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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
}
|
||||
|
19
c/frame.c
19
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");
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,5 @@ int main(int argc, const char * argv[])
|
||||
main_class,
|
||||
main_class_length);
|
||||
|
||||
backtrace_print(vm);
|
||||
|
||||
vm_execute(vm);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package java.lang;
|
||||
|
||||
public class Throwable {
|
||||
|
||||
private Object backtrace;
|
||||
private String message;
|
||||
private Throwable cause = this;
|
||||
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user