implement backtrace allocation / printing
This commit is contained in:
parent
7914abe702
commit
47fc2b90e2
@ -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 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,
|
struct attribute_info * attribute_info = find_attribute(linenumbertable_name_index,
|
||||||
frame->code_attribute->attributes_count,
|
code_attribute->attributes_count,
|
||||||
frame->code_attribute->attributes);
|
code_attribute->attributes);
|
||||||
assert(attribute_info != nullptr);
|
assert(attribute_info != nullptr);
|
||||||
int line_number_table_length = attribute_info->line_number_table->line_number_table_length;
|
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;
|
struct line_number_table * line_number_table = attribute_info->line_number_table->line_number_table;
|
||||||
int line_number = 0;
|
int line_number = 0;
|
||||||
for (int i = 0; i < line_number_table_length; i++) {
|
for (int i = 0; i < line_number_table_length; i++) {
|
||||||
if (frame->pc >= line_number_table[i].start_pc) {
|
if (pc >= line_number_table[i].start_pc) {
|
||||||
line_number = line_number_table[i].line_number;
|
line_number = line_number_table[i].line_number;
|
||||||
} else {
|
} else {
|
||||||
break;
|
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"
|
#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) {
|
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)));
|
||||||
|
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);
|
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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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];
|
||||||
}
|
}
|
||||||
|
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) {
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user