diff --git a/classfile.c b/classfile.c index 470616a..54e5147 100644 --- a/classfile.c +++ b/classfile.c @@ -1,4 +1,5 @@ #include "classfile.h" +#include #include #include #include @@ -14,12 +15,12 @@ void read_u2(void *ptr, size_t n, FILE *file) { buffer[i] = (buffer[i] >> 8) | (buffer[i] << 8); } #endif - memcpy(ptr, &buffer, n*sizeof(u2)); + memcpy(ptr, &buffer, n * sizeof(u2)); } void read_u4(void *ptr, size_t n, FILE *file) { u4 buffer[n]; - fread(&buffer, sizeof(u2), n, file); + fread(&buffer, sizeof(u4), n, file); #ifdef SWAP_ENDIANNESS for (size_t i = 0; i < n; i++) { buffer[i] = ((buffer[i] >> 24) & 0xff) | // move byte 3 to byte 0 @@ -28,7 +29,7 @@ void read_u4(void *ptr, size_t n, FILE *file) { ((buffer[i] << 24) & 0xff000000); } #endif - memcpy(ptr, &buffer, n*sizeof(u4)); + memcpy(ptr, &buffer, n * sizeof(u4)); } ClassFile *ClassFile_load(const char *path) { @@ -40,96 +41,125 @@ ClassFile *ClassFile_load(const char *path) { // magic 4bytes, minor_version 2bytes, major_version 2bytes, // constant_pool_count 2bytes - fread(&(cf->magic), 4 + 2 + 2 + 2, 1, file); + read_u4(&(cf->magic), 1, file); + read_u2(&(cf->minor_version), 3, file); // constant_pool cf->constant_pool = (cp_info *)malloc(sizeof(cp_info) * (cf->constant_pool_count - 1)); for (u2 i = 0; i < (cf->constant_pool_count - 1); i++) { // cp_info.tag 2bytes - fread(&(cf->constant_pool[i].tag), 2, 1, file); + fread(&(cf->constant_pool[i].tag), 1, 1, file); size_t size; switch (cf->constant_pool[i].tag) { case CONSTANT_Class: - size = sizeof(CONSTANT_Class_info); + read_u2(&(cf->constant_pool[i].info.class_info.name_index), 1, file); break; case CONSTANT_Fieldref: - size = sizeof(CONSTANT_Fieldref_info); + 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, + file); break; case CONSTANT_Methodref: - size = sizeof(CONSTANT_Methodref_info); + 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), + 1, file); break; case CONSTANT_InterfaceMethodref: - size = sizeof(CONSTANT_InterfaceMethodref_info); + read_u2(&(cf->constant_pool[i].info.interface_methodred_info.class_index), + 1, file); + read_u2(&(cf->constant_pool[i] + .info.interface_methodred_info.name_and_type_index), + 1, file); break; case CONSTANT_String: - size = sizeof(CONSTANT_String_info); + read_u2(&(cf->constant_pool[i].info.string_info.string_index), 1, file); break; case CONSTANT_Integer: - size = sizeof(CONSTANT_Integer_info); + read_u4(&(cf->constant_pool[i].info.integer_info.bytes), 1, file); break; case CONSTANT_Float: - size = sizeof(CONSTANT_Float_info); + read_u4(&(cf->constant_pool[i].info.float_info.bytes), 1, file); break; case CONSTANT_Long: - size = sizeof(CONSTANT_Long_info); + read_u4(&(cf->constant_pool[i].info.long_info.high_bytes), 1, file); + read_u4(&(cf->constant_pool[i].info.long_info.low_bytes), 1, file); break; case CONSTANT_Double: - size = sizeof(CONSTANT_Double_info); + read_u4(&(cf->constant_pool[i].info.double_info.high_bytes), 1, file); + read_u4(&(cf->constant_pool[i].info.double_info.low_bytes), 1, file); break; case CONSTANT_NameAndType: - size = sizeof(CONSTANT_NameAndType_info); + read_u2(&(cf->constant_pool[i].info.name_and_type_info.name_index), 1, + file); + read_u2(&(cf->constant_pool[i].info.name_and_type_info.descriptor_index), + 1, file); break; case CONSTANT_Utf8: - size = sizeof(CONSTANT_Utf8_info); + 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.length, 1, file); break; case CONSTANT_MethodHandle: - size = sizeof(CONSTANT_MethodHandle_info); + fread(&(cf->constant_pool[i].info.method_handle_info.reference_kind), 1, + 1, file); + read_u2(&(cf->constant_pool[i].info.method_handle_info.reference_index), + 1, file); break; case CONSTANT_MethodType: - size = sizeof(CONSTANT_MethodType_info); + read_u2(&(cf->constant_pool[i].info.method_type_info.descriptor_index), 1, + file); break; case CONSTANT_Dynamic: - size = sizeof(CONSTANT_Dynamic_info); + read_u2( + &(cf->constant_pool[i].info.dynamic_info.bootstrap_method_attr_index), + 1, file); + read_u2(&(cf->constant_pool[i].info.dynamic_info.name_and_type_index), 1, + file); break; case CONSTANT_InvokeDynamic: - size = sizeof(CONSTANT_InvokeDynamic_info); + read_u2(&(cf->constant_pool[i] + .info.invoke_dynamic_info.bootstrap_method_attr_index), + 1, file); + read_u2( + &(cf->constant_pool[i].info.invoke_dynamic_info.name_and_type_index), + 1, file); break; case CONSTANT_Module: - size = sizeof(CONSTANT_Module_info); + read_u2(&(cf->constant_pool[i].info.module_info.name_index), 1, file); break; case CONSTANT_Package: - size = sizeof(CONSTANT_Package_info); + read_u2(&(cf->constant_pool[i].info.package_info.name_index), 1, file); break; + default: + printf("unknown constant tag: %hhu\n", cf->constant_pool[i].tag); + // assert(0); } - - cf->constant_pool[i].info = (void *)malloc(size); - fread(cf->constant_pool[i].info, size, 1, file); } // access_flags 2bytes, this_class 2bytes, super_class 2bytes, interface_count - // 2bytes - fread(&(cf->access_flags), 2 + 2 + 2 + 2, 1, file); + // 2byte + read_u2(&(cf->access_flags), 4, file); // interfaces cf->interfaces = (u2 *)malloc(2 * cf->interfaces_count); - fread(cf->interfaces, 2 * cf->interfaces_count, 1, file); + read_u2(cf->interfaces, cf->interfaces_count, file); // fields_count 2bytes - fread(&(cf->fields_count), 2, 1, file); + read_u2(&(cf->fields_count), 1, file); // fields cf->fields = (field_info *)malloc(sizeof(field_info) * cf->fields_count); for (u2 i = 0; i < cf->fields_count; i++) { // access_flags 2bytes, name_index 2bytes, descriptor_index 2bytes, // attributes_count 2bytes - fread(&(cf->fields[i].access_flags), 2 + 2 + 2 + 2, 1, file); + read_u2(&(cf->fields[i].access_flags), 4, file); cf->fields[i].attributes = (attribute_info *)malloc( sizeof(attribute_info) * cf->fields[i].attributes_count); for (u2 j = 0; j < cf->fields[i].attributes_count; j++) { // attribute_name_index 2bytes, attribute_length 4bytes - fread(&(cf->fields[i].attributes[j].attribute_name_index), 2 + 4, 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); cf->fields[i].attributes[j].info = (u1 *)malloc(cf->fields[i].attributes[j].attribute_length); fread(cf->fields[i].attributes[j].info, @@ -138,20 +168,20 @@ ClassFile *ClassFile_load(const char *path) { } // methods_count 2bytes - fread(&(cf->methods_count), 2, 1, file); + read_u2(&(cf->methods_count), 1, file); // methods cf->methods = (method_info *)malloc(sizeof(method_info) * cf->methods_count); for (u2 i = 0; i < cf->methods_count; i++) { // access_flags 2bytes, name_index 2bytes, descriptor_index 2bytes, // attributes_count 2bytes - fread(&(cf->methods[i].access_flags), 2 + 2 + 2 + 2, 1, file); + read_u2(&(cf->methods[i].access_flags), 4, file); cf->methods[i].attributes = (attribute_info *)malloc( sizeof(attribute_info) * cf->methods[i].attributes_count); for (u2 j = 0; j < cf->methods[i].attributes_count; j++) { // attribute_name_index 2bytes, attribute_length 4bytes - fread(&(cf->methods[i].attributes[j].attribute_name_index), 2 + 4, 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); cf->methods[i].attributes[j].info = (u1 *)malloc(cf->methods[i].attributes[j].attribute_length); fread(cf->methods[i].attributes[j].info, @@ -160,14 +190,15 @@ ClassFile *ClassFile_load(const char *path) { } // attributes_count 2bytes - fread(&(cf->attributes_count), 2, 1, file); + read_u2(&(cf->attributes_count), 1, file); // attributes cf->attributes = (attribute_info *)malloc(sizeof(attribute_info) * cf->attributes_count); for (u2 i = 0; i < cf->attributes_count; i++) { // attribute_name_index 2bytes, attribute_length 4bytes - fread(&(cf->attributes[i].attribute_name_index), 2 + 4, 1, file); + read_u2(&(cf->attributes[i].attribute_name_index), 1, file); + read_u4(&(cf->attributes[i].attribute_length), 1, file); cf->attributes[i].info = (u1 *)malloc(cf->attributes[i].attribute_length); fread(cf->attributes[i].info, cf->attributes[i].attribute_length, 1, file); } @@ -182,7 +213,7 @@ void ClassFile_info(const ClassFile *cf) { "minor_version=%hu\n" "major_version=%hu\n" "constant_pool_count=%hu\n" - "access_flags=%hu\n" + "access_flags=%hx\n" "this_class=%hu\n" "super_class=%hu\n" "interfaces_count=%hu\n" diff --git a/classfile.h b/classfile.h index abdb419..62d930d 100644 --- a/classfile.h +++ b/classfile.h @@ -52,17 +52,10 @@ typedef enum { } CONSTANT_TAGS; typedef struct { - u1 tag; - void *info; -} cp_info; - -typedef struct { - u1 tag; u2 name_index; } CONSTANT_Class_info; typedef struct { - u1 tag; u2 class_index; u2 name_and_type_index; } CONSTANT_Fieldref_info; @@ -70,63 +63,76 @@ typedef CONSTANT_Fieldref_info CONSTANT_Methodref_info; typedef CONSTANT_Fieldref_info CONSTANT_InterfaceMethodref_info; typedef struct { - u1 tag; u2 string_index; } CONSTANT_String_info; typedef struct { - u1 tag; u4 bytes; } CONSTANT_Integer_info; typedef CONSTANT_Integer_info CONSTANT_Float_info; typedef struct { - u1 tag; u4 high_bytes; u4 low_bytes; } CONSTANT_Long_info; typedef CONSTANT_Long_info CONSTANT_Double_info; typedef struct { - u1 tag; u2 name_index; u2 descriptor_index; } CONSTANT_NameAndType_info; typedef struct { - u1 tag; u2 length; u1 *bytes; } CONSTANT_Utf8_info; typedef struct { - u1 tag; u1 reference_kind; u2 reference_index; } CONSTANT_MethodHandle_info; typedef struct { - u1 tag; u2 descriptor_index; } CONSTANT_MethodType_info; typedef struct { - u1 tag; u2 bootstrap_method_attr_index; u2 name_and_type_index; } CONSTANT_Dynamic_info; typedef CONSTANT_Dynamic_info CONSTANT_InvokeDynamic_info; typedef struct { - u1 tag; u2 name_index; } CONSTANT_Module_info; typedef struct { - u1 tag; u2 name_index; } CONSTANT_Package_info; +typedef struct { + u1 tag; + union { + CONSTANT_Class_info class_info; + CONSTANT_Fieldref_info fieldref_info; + CONSTANT_Methodref_info methodref_info; + CONSTANT_InterfaceMethodref_info interface_methodred_info; + CONSTANT_String_info string_info; + CONSTANT_Integer_info integer_info; + CONSTANT_Float_info float_info; + CONSTANT_Long_info long_info; + CONSTANT_Double_info double_info; + CONSTANT_NameAndType_info name_and_type_info; + CONSTANT_Utf8_info utf8_info; + CONSTANT_MethodHandle_info method_handle_info; + CONSTANT_MethodType_info method_type_info; + CONSTANT_Dynamic_info dynamic_info; + CONSTANT_InvokeDynamic_info invoke_dynamic_info; + CONSTANT_Module_info module_info; + CONSTANT_Package_info package_info; + } info; +} cp_info; + typedef struct { u2 attribute_name_index; u4 attribute_length;