StackMapFrames
This commit is contained in:
parent
c4eea4d1d1
commit
d5e3237bb2
245
classfile.c
245
classfile.c
@ -4,10 +4,11 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define SWAP_ENDIANNESS
|
#define SWAP_ENDIANNESS
|
||||||
|
|
||||||
void read_u2(void *ptr, size_t n, FILE *file) {
|
void read_u2(void* ptr, size_t n, FILE* file) {
|
||||||
u2 buffer[n];
|
u2 buffer[n];
|
||||||
fread(&buffer, sizeof(u2), n, file);
|
fread(&buffer, sizeof(u2), n, file);
|
||||||
#ifdef SWAP_ENDIANNESS
|
#ifdef SWAP_ENDIANNESS
|
||||||
@ -18,7 +19,7 @@ void read_u2(void *ptr, size_t n, FILE *file) {
|
|||||||
memcpy(ptr, &buffer, n * sizeof(u2));
|
memcpy(ptr, &buffer, n * sizeof(u2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_u4(void *ptr, size_t n, FILE *file) {
|
void read_u4(void* ptr, size_t n, FILE* file) {
|
||||||
u4 buffer[n];
|
u4 buffer[n];
|
||||||
fread(&buffer, sizeof(u4), n, file);
|
fread(&buffer, sizeof(u4), n, file);
|
||||||
#ifdef SWAP_ENDIANNESS
|
#ifdef SWAP_ENDIANNESS
|
||||||
@ -32,12 +33,144 @@ void read_u4(void *ptr, size_t n, FILE *file) {
|
|||||||
memcpy(ptr, &buffer, n * sizeof(u4));
|
memcpy(ptr, &buffer, n * sizeof(u4));
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassFile *ClassFile_load(const char *path) {
|
stack_frame_type stack_frame_type_enum(u2 frame_type) {
|
||||||
FILE *file = fopen(path, "rb");
|
if (0 <= frame_type && frame_type <= 63) {
|
||||||
|
return SAME;
|
||||||
|
} else if (64 <= frame_type && frame_type <= 127) {
|
||||||
|
return SAME_LOCALS_1_STACK_ITEM_FRAME;
|
||||||
|
} else if (frame_type == 247) {
|
||||||
|
return SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
|
||||||
|
} else if (248 <= frame_type && frame_type <= 250) {
|
||||||
|
return CHOP;
|
||||||
|
} else if (frame_type == 251) {
|
||||||
|
return SAME_FRAME_EXTENDED;
|
||||||
|
} else if (252 <= frame_type && frame_type <= 254) {
|
||||||
|
return APPEND;
|
||||||
|
} else if (frame_type == 255) {
|
||||||
|
return FULL_FRAME;
|
||||||
|
} else {
|
||||||
|
printf("unknown stack frame type: %hu\n", frame_type);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_attribute(ClassFile* cf, attribute_info* base, FILE* file) {
|
||||||
|
char* name = (char*)cf->constant_pool[base->attribute_name_index - 1].info.utf8_info.bytes;
|
||||||
|
printf("%s\n", name);
|
||||||
|
if (strcmp("ConstantValue", name) == 0) {
|
||||||
|
read_u2(&(base->info.constant_value_attribute.constantvalue_index), 1, file);
|
||||||
|
} else if (strcmp("Code", name) == 0) {
|
||||||
|
read_u2(&(base->info.code_attribute.max_stack), 2, file);
|
||||||
|
read_u4(&(base->info.code_attribute.code_length), 1, file);
|
||||||
|
base->info.code_attribute.code = (u1*)malloc(base->info.code_attribute.code_length);
|
||||||
|
fread(base->info.code_attribute.code, base->info.code_attribute.code_length, 1, file);
|
||||||
|
read_u2(&(base->info.code_attribute.exception_table_length), 1, file);
|
||||||
|
base->info.code_attribute.exception_table = malloc(sizeof(u2) * 4 * base->info.code_attribute.exception_table_length);
|
||||||
|
for (u2 i = 0; i < base->info.code_attribute.exception_table_length; i++) {
|
||||||
|
read_u2(&(base->info.code_attribute.exception_table[i].start_pc), 4, file);
|
||||||
|
}
|
||||||
|
read_u2(&(base->info.code_attribute.attributes_count), 1, file);
|
||||||
|
base->info.code_attribute.attributes = malloc(sizeof(attribute_info) * base->info.code_attribute.attributes_count);
|
||||||
|
for (u2 i = 0; i < base->info.code_attribute.attributes_count; i++) {
|
||||||
|
attribute_info* attr = &(base->info.code_attribute.attributes[i]);
|
||||||
|
read_u2(&(attr->attribute_name_index), 1, file);
|
||||||
|
read_u4(&(attr->attribute_length), 1, file);
|
||||||
|
parse_attribute(cf, attr, file);
|
||||||
|
}
|
||||||
|
} else if (strcmp("StackMapTable", name) == 0) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.number_of_entries), 1, file);
|
||||||
|
base->info.stack_map_table_attribute.entries = malloc(sizeof(stack_map_frame) * base->info.stack_map_table_attribute.number_of_entries);
|
||||||
|
for (u2 i = 0; i < base->info.stack_map_table_attribute.number_of_entries; i++) {
|
||||||
|
fread(&(base->info.stack_map_table_attribute.entries[i].frame_type), 1, 1, file);
|
||||||
|
u1 frame_type = base->info.stack_map_table_attribute.entries[i].frame_type;
|
||||||
|
switch (stack_frame_type_enum(frame_type)) {
|
||||||
|
case SAME:
|
||||||
|
break;
|
||||||
|
case SAME_LOCALS_1_STACK_ITEM_FRAME:
|
||||||
|
fread(&(base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame.stack[0].tag), 1, 1, file);
|
||||||
|
if (base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame.stack[0].tag == ITEM_Object) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame.stack[0].Object_variable_info.cpool_index), 1, file);
|
||||||
|
} else if (base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame.stack[0].tag == ITEM_Uninitialized) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame.stack[0].Uninitialized_variable_info.offset), 1, file);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame_extended.offset_delta), 1, file);
|
||||||
|
fread(&(base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame_extended.stack[0].tag), 1, 1, file);
|
||||||
|
if (base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame_extended.stack[0].tag == ITEM_Object) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame_extended.stack[0].Object_variable_info.cpool_index), 1,
|
||||||
|
file);
|
||||||
|
} else if (base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame_extended.stack[0].tag == ITEM_Uninitialized) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].same_locals_1_stack_item_frame_extended.stack[0].Uninitialized_variable_info.offset), 1,
|
||||||
|
file);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CHOP:
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].chop_frame.offset_delta), 1, file);
|
||||||
|
break;
|
||||||
|
case SAME_FRAME_EXTENDED:
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].same_frame_extended.offset_delta), 1, file);
|
||||||
|
break;
|
||||||
|
case APPEND:
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].append_frame.offset_delta), 1, file);
|
||||||
|
u2 count = frame_type - 251;
|
||||||
|
base->info.stack_map_table_attribute.entries[i].append_frame.locals = malloc(sizeof(verification_type_info) * count);
|
||||||
|
for (u2 j = 0; j < count; j++) {
|
||||||
|
fread(&(base->info.stack_map_table_attribute.entries[i].append_frame.locals[j].tag), 1, 1, file);
|
||||||
|
if (base->info.stack_map_table_attribute.entries[i].append_frame.locals[j].tag == ITEM_Object) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].append_frame.locals[j].Object_variable_info.cpool_index), 1, file);
|
||||||
|
} else if (base->info.stack_map_table_attribute.entries[i].append_frame.locals[j].tag == ITEM_Uninitialized) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].append_frame.locals[j].Uninitialized_variable_info.offset), 1, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FULL_FRAME:
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].full_frame.offset_delta), 1, file);
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].full_frame.number_of_locals), 1, file);
|
||||||
|
base->info.stack_map_table_attribute.entries[i].full_frame.locals =
|
||||||
|
malloc(sizeof(verification_type_info) * base->info.stack_map_table_attribute.entries[i].full_frame.number_of_locals);
|
||||||
|
for (u2 j = 0; j < base->info.stack_map_table_attribute.entries[i].full_frame.number_of_locals; j++) {
|
||||||
|
fread(&(base->info.stack_map_table_attribute.entries[i].full_frame.locals[j].tag), 1, 1, file);
|
||||||
|
if (base->info.stack_map_table_attribute.entries[i].full_frame.locals[j].tag == ITEM_Object) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].full_frame.locals[j].Object_variable_info.cpool_index), 1, file);
|
||||||
|
} else if (base->info.stack_map_table_attribute.entries[i].full_frame.locals[j].tag == ITEM_Uninitialized) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].full_frame.locals[j].Uninitialized_variable_info.offset), 1, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].full_frame.number_of_stack_items), 1, file);
|
||||||
|
base->info.stack_map_table_attribute.entries[i].full_frame.stack =
|
||||||
|
malloc(sizeof(verification_type_info) * base->info.stack_map_table_attribute.entries[i].full_frame.number_of_stack_items);
|
||||||
|
for (u2 j = 0; j < base->info.stack_map_table_attribute.entries[i].full_frame.number_of_stack_items; j++) {
|
||||||
|
fread(&(base->info.stack_map_table_attribute.entries[i].full_frame.stack[j].tag), 1, 1, file);
|
||||||
|
if (base->info.stack_map_table_attribute.entries[i].full_frame.stack[j].tag == ITEM_Object) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].full_frame.stack[j].Object_variable_info.cpool_index), 1, file);
|
||||||
|
} else if (base->info.stack_map_table_attribute.entries[i].full_frame.stack[j].tag == ITEM_Uninitialized) {
|
||||||
|
read_u2(&(base->info.stack_map_table_attribute.entries[i].full_frame.stack[j].Uninitialized_variable_info.offset), 1, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (strcmp("NestHost", name) == 0) {
|
||||||
|
printf("NestHost not implemented.\n");
|
||||||
|
assert(0);
|
||||||
|
} else if (strcmp("NestMembers", name)) {
|
||||||
|
printf("NestMembers not implemented.\n");
|
||||||
|
assert(0);
|
||||||
|
} else if (strcmp("PermittedSubclasses", name) == 0) {
|
||||||
|
printf("PermittedSubclasses not implemented.\n");
|
||||||
|
assert(0);
|
||||||
|
} else {
|
||||||
|
printf("unhandled attribute type: %s", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFile* ClassFile_load(const char* path) {
|
||||||
|
FILE* file = fopen(path, "rb");
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ClassFile *cf = (ClassFile *)malloc(sizeof(ClassFile));
|
ClassFile* cf = (ClassFile*)malloc(sizeof(ClassFile));
|
||||||
|
|
||||||
// magic 4bytes, minor_version 2bytes, major_version 2bytes,
|
// magic 4bytes, minor_version 2bytes, major_version 2bytes,
|
||||||
// constant_pool_count 2bytes
|
// constant_pool_count 2bytes
|
||||||
@ -45,8 +178,7 @@ ClassFile *ClassFile_load(const char *path) {
|
|||||||
read_u2(&(cf->minor_version), 3, file);
|
read_u2(&(cf->minor_version), 3, file);
|
||||||
|
|
||||||
// constant_pool
|
// constant_pool
|
||||||
cf->constant_pool =
|
cf->constant_pool = (cp_info*)malloc(sizeof(cp_info) * (cf->constant_pool_count - 1));
|
||||||
(cp_info *)malloc(sizeof(cp_info) * (cf->constant_pool_count - 1));
|
|
||||||
for (u2 i = 0; i < (cf->constant_pool_count - 1); i++) {
|
for (u2 i = 0; i < (cf->constant_pool_count - 1); i++) {
|
||||||
// cp_info.tag 2bytes
|
// cp_info.tag 2bytes
|
||||||
fread(&(cf->constant_pool[i].tag), 1, 1, file);
|
fread(&(cf->constant_pool[i].tag), 1, 1, file);
|
||||||
@ -57,20 +189,15 @@ ClassFile *ClassFile_load(const char *path) {
|
|||||||
break;
|
break;
|
||||||
case CONSTANT_Fieldref:
|
case CONSTANT_Fieldref:
|
||||||
read_u2(&(cf->constant_pool[i].info.fieldref_info.class_index), 1, file);
|
read_u2(&(cf->constant_pool[i].info.fieldref_info.class_index), 1, file);
|
||||||
read_u2(&(cf->constant_pool[i].info.fieldref_info.name_and_type_index), 1,
|
read_u2(&(cf->constant_pool[i].info.fieldref_info.name_and_type_index), 1, file);
|
||||||
file);
|
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Methodref:
|
case CONSTANT_Methodref:
|
||||||
read_u2(&(cf->constant_pool[i].info.methodref_info.class_index), 1, file);
|
read_u2(&(cf->constant_pool[i].info.methodref_info.class_index), 1, file);
|
||||||
read_u2(&(cf->constant_pool[i].info.methodref_info.name_and_type_index),
|
read_u2(&(cf->constant_pool[i].info.methodref_info.name_and_type_index), 1, file);
|
||||||
1, file);
|
|
||||||
break;
|
break;
|
||||||
case CONSTANT_InterfaceMethodref:
|
case CONSTANT_InterfaceMethodref:
|
||||||
read_u2(&(cf->constant_pool[i].info.interface_methodred_info.class_index),
|
read_u2(&(cf->constant_pool[i].info.interface_methodred_info.class_index), 1, file);
|
||||||
1, file);
|
read_u2(&(cf->constant_pool[i].info.interface_methodred_info.name_and_type_index), 1, file);
|
||||||
read_u2(&(cf->constant_pool[i]
|
|
||||||
.info.interface_methodred_info.name_and_type_index),
|
|
||||||
1, file);
|
|
||||||
break;
|
break;
|
||||||
case CONSTANT_String:
|
case CONSTANT_String:
|
||||||
read_u2(&(cf->constant_pool[i].info.string_info.string_index), 1, file);
|
read_u2(&(cf->constant_pool[i].info.string_info.string_index), 1, file);
|
||||||
@ -90,40 +217,28 @@ ClassFile *ClassFile_load(const char *path) {
|
|||||||
read_u4(&(cf->constant_pool[i].info.double_info.low_bytes), 1, file);
|
read_u4(&(cf->constant_pool[i].info.double_info.low_bytes), 1, file);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_NameAndType:
|
case CONSTANT_NameAndType:
|
||||||
read_u2(&(cf->constant_pool[i].info.name_and_type_info.name_index), 1,
|
read_u2(&(cf->constant_pool[i].info.name_and_type_info.name_index), 1, file);
|
||||||
file);
|
read_u2(&(cf->constant_pool[i].info.name_and_type_info.descriptor_index), 1, file);
|
||||||
read_u2(&(cf->constant_pool[i].info.name_and_type_info.descriptor_index),
|
|
||||||
1, file);
|
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Utf8:
|
case CONSTANT_Utf8:
|
||||||
read_u2(&(cf->constant_pool[i].info.utf8_info.length), 1, file);
|
read_u2(&(cf->constant_pool[i].info.utf8_info.length), 1, file);
|
||||||
fread(&(cf->constant_pool[i].info.utf8_info.bytes),
|
cf->constant_pool[i].info.utf8_info.bytes = (u1*)malloc(cf->constant_pool[i].info.utf8_info.length);
|
||||||
cf->constant_pool[i].info.utf8_info.length, 1, file);
|
fread(cf->constant_pool[i].info.utf8_info.bytes, cf->constant_pool[i].info.utf8_info.length, 1, file);
|
||||||
break;
|
break;
|
||||||
case CONSTANT_MethodHandle:
|
case CONSTANT_MethodHandle:
|
||||||
fread(&(cf->constant_pool[i].info.method_handle_info.reference_kind), 1,
|
fread(&(cf->constant_pool[i].info.method_handle_info.reference_kind), 1, 1, file);
|
||||||
1, file);
|
read_u2(&(cf->constant_pool[i].info.method_handle_info.reference_index), 1, file);
|
||||||
read_u2(&(cf->constant_pool[i].info.method_handle_info.reference_index),
|
|
||||||
1, file);
|
|
||||||
break;
|
break;
|
||||||
case CONSTANT_MethodType:
|
case CONSTANT_MethodType:
|
||||||
read_u2(&(cf->constant_pool[i].info.method_type_info.descriptor_index), 1,
|
read_u2(&(cf->constant_pool[i].info.method_type_info.descriptor_index), 1, file);
|
||||||
file);
|
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Dynamic:
|
case CONSTANT_Dynamic:
|
||||||
read_u2(
|
read_u2(&(cf->constant_pool[i].info.dynamic_info.bootstrap_method_attr_index), 1, file);
|
||||||
&(cf->constant_pool[i].info.dynamic_info.bootstrap_method_attr_index),
|
read_u2(&(cf->constant_pool[i].info.dynamic_info.name_and_type_index), 1, file);
|
||||||
1, file);
|
|
||||||
read_u2(&(cf->constant_pool[i].info.dynamic_info.name_and_type_index), 1,
|
|
||||||
file);
|
|
||||||
break;
|
break;
|
||||||
case CONSTANT_InvokeDynamic:
|
case CONSTANT_InvokeDynamic:
|
||||||
read_u2(&(cf->constant_pool[i]
|
read_u2(&(cf->constant_pool[i].info.invoke_dynamic_info.bootstrap_method_attr_index), 1, file);
|
||||||
.info.invoke_dynamic_info.bootstrap_method_attr_index),
|
read_u2(&(cf->constant_pool[i].info.invoke_dynamic_info.name_and_type_index), 1, file);
|
||||||
1, file);
|
|
||||||
read_u2(
|
|
||||||
&(cf->constant_pool[i].info.invoke_dynamic_info.name_and_type_index),
|
|
||||||
1, file);
|
|
||||||
break;
|
break;
|
||||||
case CONSTANT_Module:
|
case CONSTANT_Module:
|
||||||
read_u2(&(cf->constant_pool[i].info.module_info.name_index), 1, file);
|
read_u2(&(cf->constant_pool[i].info.module_info.name_index), 1, file);
|
||||||
@ -142,30 +257,31 @@ ClassFile *ClassFile_load(const char *path) {
|
|||||||
read_u2(&(cf->access_flags), 4, file);
|
read_u2(&(cf->access_flags), 4, file);
|
||||||
|
|
||||||
// interfaces
|
// interfaces
|
||||||
cf->interfaces = (u2 *)malloc(2 * cf->interfaces_count);
|
cf->interfaces = (u2*)malloc(2 * cf->interfaces_count);
|
||||||
read_u2(cf->interfaces, cf->interfaces_count, file);
|
read_u2(cf->interfaces, cf->interfaces_count, file);
|
||||||
|
|
||||||
// fields_count 2bytes
|
// fields_count 2bytes
|
||||||
read_u2(&(cf->fields_count), 1, file);
|
read_u2(&(cf->fields_count), 1, file);
|
||||||
|
|
||||||
// fields
|
// fields
|
||||||
cf->fields = (field_info *)malloc(sizeof(field_info) * cf->fields_count);
|
cf->fields = (field_info*)malloc(sizeof(field_info) * cf->fields_count);
|
||||||
for (u2 i = 0; i < cf->fields_count; i++) {
|
for (u2 i = 0; i < cf->fields_count; i++) {
|
||||||
// access_flags 2bytes, name_index 2bytes, descriptor_index 2bytes,
|
// access_flags 2bytes, name_index 2bytes, descriptor_index 2bytes,
|
||||||
// attributes_count 2bytes
|
// attributes_count 2bytes
|
||||||
read_u2(&(cf->fields[i].access_flags), 4, file);
|
read_u2(&(cf->fields[i].access_flags), 4, file);
|
||||||
cf->fields[i].attributes = (attribute_info *)malloc(
|
cf->fields[i].attributes = (attribute_info*)malloc(sizeof(attribute_info) * cf->fields[i].attributes_count);
|
||||||
sizeof(attribute_info) * cf->fields[i].attributes_count);
|
|
||||||
for (u2 j = 0; j < cf->fields[i].attributes_count; j++) {
|
for (u2 j = 0; j < cf->fields[i].attributes_count; j++) {
|
||||||
// attribute_name_index 2bytes, attribute_length 4bytes
|
// attribute_name_index 2bytes, attribute_length 4bytes
|
||||||
read_u2(&(cf->fields[i].attributes[j].attribute_name_index), 1, file);
|
read_u2(&(cf->fields[i].attributes[j].attribute_name_index), 1, file);
|
||||||
read_u4(&(cf->fields[i].attributes[j].attribute_length), 1, file);
|
read_u4(&(cf->fields[i].attributes[j].attribute_length), 1, file);
|
||||||
// TODO: parse attributes by tag
|
// TODO: parse attributes by tag
|
||||||
// this has an unknown amount of layers, should be moved out to a function
|
// this has an unknown amount of layers, should be moved out to a function
|
||||||
cf->fields[i].attributes[j].info =
|
// cf->fields[i].attributes[j].info =
|
||||||
(u1 *)malloc(cf->fields[i].attributes[j].attribute_length);
|
// (u1 *)malloc(cf->fields[i].attributes[j].attribute_length);
|
||||||
fread(cf->fields[i].attributes[j].info,
|
// fread(cf->fields[i].attributes[j].info,
|
||||||
cf->fields[i].attributes[j].attribute_length, 1, file);
|
// cf->fields[i].attributes[j].attribute_length, 1, file);
|
||||||
|
|
||||||
|
parse_attribute(cf, &(cf->fields[i].attributes[j]), file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,23 +289,23 @@ ClassFile *ClassFile_load(const char *path) {
|
|||||||
read_u2(&(cf->methods_count), 1, file);
|
read_u2(&(cf->methods_count), 1, file);
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
cf->methods = (method_info *)malloc(sizeof(method_info) * cf->methods_count);
|
cf->methods = (method_info*)malloc(sizeof(method_info) * cf->methods_count);
|
||||||
for (u2 i = 0; i < cf->methods_count; i++) {
|
for (u2 i = 0; i < cf->methods_count; i++) {
|
||||||
// access_flags 2bytes, name_index 2bytes, descriptor_index 2bytes,
|
// access_flags 2bytes, name_index 2bytes, descriptor_index 2bytes,
|
||||||
// attributes_count 2bytes
|
// attributes_count 2bytes
|
||||||
read_u2(&(cf->methods[i].access_flags), 4, file);
|
read_u2(&(cf->methods[i].access_flags), 4, file);
|
||||||
cf->methods[i].attributes = (attribute_info *)malloc(
|
cf->methods[i].attributes = (attribute_info*)malloc(sizeof(attribute_info) * cf->methods[i].attributes_count);
|
||||||
sizeof(attribute_info) * cf->methods[i].attributes_count);
|
|
||||||
for (u2 j = 0; j < cf->methods[i].attributes_count; j++) {
|
for (u2 j = 0; j < cf->methods[i].attributes_count; j++) {
|
||||||
// attribute_name_index 2bytes, attribute_length 4bytes
|
// attribute_name_index 2bytes, attribute_length 4bytes
|
||||||
read_u2(&(cf->methods[i].attributes[j].attribute_name_index), 1, file);
|
read_u2(&(cf->methods[i].attributes[j].attribute_name_index), 1, file);
|
||||||
read_u4(&(cf->methods[i].attributes[j].attribute_length), 1, file);
|
read_u4(&(cf->methods[i].attributes[j].attribute_length), 1, file);
|
||||||
// TODO: parse attributes by tag
|
// TODO: parse attributes by tag
|
||||||
// this has an unknown amount of layers, should be moved out to a function
|
// this has an unknown amount of layers, should be moved out to a function
|
||||||
cf->methods[i].attributes[j].info =
|
// cf->methods[i].attributes[j].info =
|
||||||
(u1 *)malloc(cf->methods[i].attributes[j].attribute_length);
|
// (u1 *)malloc(cf->methods[i].attributes[j].attribute_length);
|
||||||
fread(cf->methods[i].attributes[j].info,
|
// fread(cf->methods[i].attributes[j].info,
|
||||||
cf->methods[i].attributes[j].attribute_length, 1, file);
|
// cf->methods[i].attributes[j].attribute_length, 1, file);
|
||||||
|
parse_attribute(cf, &(cf->methods[i].attributes[j]), file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,16 +313,18 @@ ClassFile *ClassFile_load(const char *path) {
|
|||||||
read_u2(&(cf->attributes_count), 1, file);
|
read_u2(&(cf->attributes_count), 1, file);
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
cf->attributes =
|
cf->attributes = (attribute_info*)malloc(sizeof(attribute_info) * cf->attributes_count);
|
||||||
(attribute_info *)malloc(sizeof(attribute_info) * cf->attributes_count);
|
|
||||||
for (u2 i = 0; i < cf->attributes_count; i++) {
|
for (u2 i = 0; i < cf->attributes_count; i++) {
|
||||||
// attribute_name_index 2bytes, attribute_length 4bytes
|
// attribute_name_index 2bytes, attribute_length 4bytes
|
||||||
read_u2(&(cf->attributes[i].attribute_name_index), 1, file);
|
read_u2(&(cf->attributes[i].attribute_name_index), 1, file);
|
||||||
read_u4(&(cf->attributes[i].attribute_length), 1, file);
|
read_u4(&(cf->attributes[i].attribute_length), 1, file);
|
||||||
cf->attributes[i].info = (u1 *)malloc(cf->attributes[i].attribute_length);
|
// cf->attributes[i].info = (u1
|
||||||
|
// *)malloc(cf->attributes[i].attribute_length);
|
||||||
// TODO: parse attributes by tag
|
// TODO: parse attributes by tag
|
||||||
// this has an unknown amount of layers, should be moved out to a function
|
// this has an unknown amount of layers, should be moved out to a function
|
||||||
fread(cf->attributes[i].info, cf->attributes[i].attribute_length, 1, file);
|
// fread(cf->attributes[i].info, cf->attributes[i].attribute_length, 1,
|
||||||
|
// file);
|
||||||
|
parse_attribute(cf, &(cf->attributes[i]), file);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
@ -214,8 +332,9 @@ ClassFile *ClassFile_load(const char *path) {
|
|||||||
return cf;
|
return cf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassFile_info(const ClassFile *cf) {
|
void ClassFile_info(const ClassFile* cf) {
|
||||||
printf("magic=%X\n"
|
printf(
|
||||||
|
"magic=%X\n"
|
||||||
"minor_version=%hu\n"
|
"minor_version=%hu\n"
|
||||||
"major_version=%hu\n"
|
"major_version=%hu\n"
|
||||||
"constant_pool_count=%hu\n"
|
"constant_pool_count=%hu\n"
|
||||||
@ -226,8 +345,6 @@ void ClassFile_info(const ClassFile *cf) {
|
|||||||
"fields_count=%hu\n"
|
"fields_count=%hu\n"
|
||||||
"methods_count=%hu\n"
|
"methods_count=%hu\n"
|
||||||
"attributes_count=%hu\n",
|
"attributes_count=%hu\n",
|
||||||
cf->magic, cf->minor_version, cf->major_version,
|
cf->magic, cf->minor_version, cf->major_version, cf->constant_pool_count, cf->access_flags, cf->this_class, cf->super_class, cf->interfaces_count,
|
||||||
cf->constant_pool_count, cf->access_flags, cf->this_class,
|
cf->fields_count, cf->methods_count, cf->attributes_count);
|
||||||
cf->super_class, cf->interfaces_count, cf->fields_count,
|
|
||||||
cf->methods_count, cf->attributes_count);
|
|
||||||
}
|
}
|
125
classfile.h
125
classfile.h
@ -84,7 +84,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u2 length;
|
u2 length;
|
||||||
u1 *bytes;
|
u1* bytes;
|
||||||
} CONSTANT_Utf8_info;
|
} CONSTANT_Utf8_info;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -138,12 +138,10 @@ typedef struct {
|
|||||||
} ConstantValue_attribute;
|
} ConstantValue_attribute;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u2 attribute_name_index;
|
|
||||||
u4 attribute_length;
|
|
||||||
u2 max_stack;
|
u2 max_stack;
|
||||||
u2 max_locals;
|
u2 max_locals;
|
||||||
u4 code_length;
|
u4 code_length;
|
||||||
u1 *code;
|
u1* code;
|
||||||
u2 exception_table_length;
|
u2 exception_table_length;
|
||||||
struct {
|
struct {
|
||||||
u2 start_pc;
|
u2 start_pc;
|
||||||
@ -152,46 +150,115 @@ typedef struct {
|
|||||||
u2 catch_type;
|
u2 catch_type;
|
||||||
} * exception_table;
|
} * exception_table;
|
||||||
u2 attributes_count;
|
u2 attributes_count;
|
||||||
void *attributes;
|
void* attributes;
|
||||||
} Code_attribute;
|
} Code_attribute;
|
||||||
|
|
||||||
// TODO: stack_map_frame
|
typedef enum {
|
||||||
|
ITEM_Top = 0,
|
||||||
|
ITEM_Integer = 1,
|
||||||
|
ITEM_Float = 2,
|
||||||
|
ITEM_Double = 3,
|
||||||
|
ITEM_Long = 4,
|
||||||
|
ITEM_Null = 5,
|
||||||
|
ITEM_UninitializedThis = 6,
|
||||||
|
ITEM_Object = 7,
|
||||||
|
ITEM_Uninitialized = 8,
|
||||||
|
} VERIFICATION_TAG;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u1 tag;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
} Top_variable_info;
|
||||||
|
struct {
|
||||||
|
} Integer_variable_info;
|
||||||
|
struct {
|
||||||
|
} Float_variable_info;
|
||||||
|
struct {
|
||||||
|
} Long_variable_info;
|
||||||
|
struct {
|
||||||
|
} Double_variable_info;
|
||||||
|
struct {
|
||||||
|
} Null_variable_info;
|
||||||
|
struct {
|
||||||
|
} UninitializedThis_variable_info;
|
||||||
|
struct {
|
||||||
|
u2 cpool_index;
|
||||||
|
} Object_variable_info;
|
||||||
|
struct {
|
||||||
|
u2 offset;
|
||||||
|
} Uninitialized_variable_info;
|
||||||
|
};
|
||||||
|
} verification_type_info;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SAME,
|
||||||
|
SAME_LOCALS_1_STACK_ITEM_FRAME,
|
||||||
|
SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED,
|
||||||
|
CHOP,
|
||||||
|
SAME_FRAME_EXTENDED,
|
||||||
|
APPEND,
|
||||||
|
FULL_FRAME,
|
||||||
|
} stack_frame_type;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u1 frame_type;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
} same_frame; // 0-63
|
||||||
|
struct {
|
||||||
|
verification_type_info stack[1];
|
||||||
|
} same_locals_1_stack_item_frame; // 64-127
|
||||||
|
struct {
|
||||||
|
u2 offset_delta;
|
||||||
|
verification_type_info stack[1];
|
||||||
|
} same_locals_1_stack_item_frame_extended; // 247
|
||||||
|
struct {
|
||||||
|
u2 offset_delta;
|
||||||
|
} chop_frame; // 248-250
|
||||||
|
struct {
|
||||||
|
u2 offset_delta;
|
||||||
|
} same_frame_extended; // 251
|
||||||
|
struct {
|
||||||
|
u2 offset_delta;
|
||||||
|
verification_type_info* locals; // [frame_type - 251]
|
||||||
|
} append_frame; // 252-254
|
||||||
|
struct {
|
||||||
|
u2 offset_delta;
|
||||||
|
u2 number_of_locals;
|
||||||
|
verification_type_info* locals;
|
||||||
|
u2 number_of_stack_items;
|
||||||
|
verification_type_info* stack;
|
||||||
|
} full_frame; // 255
|
||||||
|
};
|
||||||
|
} stack_map_frame;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u2 attribute_name_index;
|
|
||||||
u4 attribute_length;
|
|
||||||
u2 number_of_entries;
|
u2 number_of_entries;
|
||||||
//stack_map_frame *entries;
|
stack_map_frame* entries;
|
||||||
} StackMapTable_attribute;
|
} StackMapTable_attribute;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u2 attribute_name_index;
|
|
||||||
u4 attribute_length;
|
|
||||||
u2 num_bootstrap_methods;
|
u2 num_bootstrap_methods;
|
||||||
struct {
|
struct {
|
||||||
u2 bootstrap_method_ref;
|
u2 bootstrap_method_ref;
|
||||||
u2 num_bootstrap_arguments;
|
u2 num_bootstrap_arguments;
|
||||||
u2 *bootstrap_arguments;
|
u2* bootstrap_arguments;
|
||||||
} * bootstrap_methods;
|
} * bootstrap_methods;
|
||||||
} BootstrapMethods_attribute;
|
} BootstrapMethods_attribute;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u2 attribute_name_index;
|
|
||||||
u4 attribute_length;
|
|
||||||
u2 host_class_index;
|
u2 host_class_index;
|
||||||
} NestHost_attribute;
|
} NestHost_attribute;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u2 attribute_name_index;
|
|
||||||
u4 attribute_length;
|
|
||||||
u2 number_of_classes;
|
u2 number_of_classes;
|
||||||
u2 *classes;
|
u2* classes;
|
||||||
} NestMembers_attribute;
|
} NestMembers_attribute;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u2 attribute_name_index;
|
|
||||||
u4 attribute_length;
|
|
||||||
u2 number_of_classes;
|
u2 number_of_classes;
|
||||||
u2 *classes;
|
u2* classes;
|
||||||
} PermittedSubclasses_attribute;
|
} PermittedSubclasses_attribute;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -213,7 +280,7 @@ typedef struct {
|
|||||||
u2 name_index;
|
u2 name_index;
|
||||||
u2 descriptor_index;
|
u2 descriptor_index;
|
||||||
u2 attributes_count;
|
u2 attributes_count;
|
||||||
attribute_info *attributes;
|
attribute_info* attributes;
|
||||||
} field_info;
|
} field_info;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -221,7 +288,7 @@ typedef struct {
|
|||||||
u2 name_index;
|
u2 name_index;
|
||||||
u2 descriptor_index;
|
u2 descriptor_index;
|
||||||
u2 attributes_count;
|
u2 attributes_count;
|
||||||
attribute_info *attributes;
|
attribute_info* attributes;
|
||||||
} method_info;
|
} method_info;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -229,21 +296,21 @@ typedef struct {
|
|||||||
u2 minor_version;
|
u2 minor_version;
|
||||||
u2 major_version;
|
u2 major_version;
|
||||||
u2 constant_pool_count;
|
u2 constant_pool_count;
|
||||||
cp_info *constant_pool;
|
cp_info* constant_pool;
|
||||||
u2 access_flags;
|
u2 access_flags;
|
||||||
u2 this_class;
|
u2 this_class;
|
||||||
u2 super_class;
|
u2 super_class;
|
||||||
u2 interfaces_count;
|
u2 interfaces_count;
|
||||||
u2 *interfaces;
|
u2* interfaces;
|
||||||
u2 fields_count;
|
u2 fields_count;
|
||||||
field_info *fields;
|
field_info* fields;
|
||||||
u2 methods_count;
|
u2 methods_count;
|
||||||
method_info *methods;
|
method_info* methods;
|
||||||
u2 attributes_count;
|
u2 attributes_count;
|
||||||
attribute_info *attributes;
|
attribute_info* attributes;
|
||||||
} ClassFile;
|
} ClassFile;
|
||||||
|
|
||||||
ClassFile *ClassFile_load(const char *path);
|
ClassFile* ClassFile_load(const char* path);
|
||||||
void ClassFile_info(const ClassFile *cf);
|
void ClassFile_info(const ClassFile* cf);
|
||||||
|
|
||||||
#pragma pack()
|
#pragma pack()
|
Loading…
Reference in New Issue
Block a user