fix endianness

This commit is contained in:
Benedek László 2024-04-12 15:49:14 +02:00
parent 807527310d
commit 7a003fc89f
2 changed files with 93 additions and 56 deletions

View File

@ -1,4 +1,5 @@
#include "classfile.h" #include "classfile.h"
#include <assert.h>
#include <memory.h> #include <memory.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
@ -14,12 +15,12 @@ void read_u2(void *ptr, size_t n, FILE *file) {
buffer[i] = (buffer[i] >> 8) | (buffer[i] << 8); buffer[i] = (buffer[i] >> 8) | (buffer[i] << 8);
} }
#endif #endif
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(u2), n, file); fread(&buffer, sizeof(u4), n, file);
#ifdef SWAP_ENDIANNESS #ifdef SWAP_ENDIANNESS
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
buffer[i] = ((buffer[i] >> 24) & 0xff) | // move byte 3 to byte 0 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); ((buffer[i] << 24) & 0xff000000);
} }
#endif #endif
memcpy(ptr, &buffer, n*sizeof(u4)); memcpy(ptr, &buffer, n * sizeof(u4));
} }
ClassFile *ClassFile_load(const char *path) { ClassFile *ClassFile_load(const char *path) {
@ -40,96 +41,125 @@ ClassFile *ClassFile_load(const char *path) {
// magic 4bytes, minor_version 2bytes, major_version 2bytes, // magic 4bytes, minor_version 2bytes, major_version 2bytes,
// constant_pool_count 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 // 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), 2, 1, file); fread(&(cf->constant_pool[i].tag), 1, 1, file);
size_t size; size_t size;
switch (cf->constant_pool[i].tag) { switch (cf->constant_pool[i].tag) {
case CONSTANT_Class: case CONSTANT_Class:
size = sizeof(CONSTANT_Class_info); read_u2(&(cf->constant_pool[i].info.class_info.name_index), 1, file);
break; break;
case CONSTANT_Fieldref: 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; break;
case CONSTANT_Methodref: 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; break;
case CONSTANT_InterfaceMethodref: 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; break;
case CONSTANT_String: case CONSTANT_String:
size = sizeof(CONSTANT_String_info); read_u2(&(cf->constant_pool[i].info.string_info.string_index), 1, file);
break; break;
case CONSTANT_Integer: case CONSTANT_Integer:
size = sizeof(CONSTANT_Integer_info); read_u4(&(cf->constant_pool[i].info.integer_info.bytes), 1, file);
break; break;
case CONSTANT_Float: case CONSTANT_Float:
size = sizeof(CONSTANT_Float_info); read_u4(&(cf->constant_pool[i].info.float_info.bytes), 1, file);
break; break;
case CONSTANT_Long: 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; break;
case CONSTANT_Double: 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; break;
case CONSTANT_NameAndType: 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; break;
case CONSTANT_Utf8: 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; break;
case CONSTANT_MethodHandle: 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; break;
case CONSTANT_MethodType: case CONSTANT_MethodType:
size = sizeof(CONSTANT_MethodType_info); read_u2(&(cf->constant_pool[i].info.method_type_info.descriptor_index), 1,
file);
break; break;
case CONSTANT_Dynamic: 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; break;
case CONSTANT_InvokeDynamic: 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; break;
case CONSTANT_Module: case CONSTANT_Module:
size = sizeof(CONSTANT_Module_info); read_u2(&(cf->constant_pool[i].info.module_info.name_index), 1, file);
break; break;
case CONSTANT_Package: case CONSTANT_Package:
size = sizeof(CONSTANT_Package_info); read_u2(&(cf->constant_pool[i].info.package_info.name_index), 1, file);
break; 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 // access_flags 2bytes, this_class 2bytes, super_class 2bytes, interface_count
// 2bytes // 2byte
fread(&(cf->access_flags), 2 + 2 + 2 + 2, 1, 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);
fread(cf->interfaces, 2 * cf->interfaces_count, 1, file); read_u2(cf->interfaces, cf->interfaces_count, file);
// fields_count 2bytes // fields_count 2bytes
fread(&(cf->fields_count), 2, 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
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( 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
fread(&(cf->fields[i].attributes[j].attribute_name_index), 2 + 4, 1, read_u2(&(cf->fields[i].attributes[j].attribute_name_index), 1, file);
file); read_u4(&(cf->fields[i].attributes[j].attribute_length), 1, file);
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,
@ -138,20 +168,20 @@ ClassFile *ClassFile_load(const char *path) {
} }
// methods_count 2bytes // methods_count 2bytes
fread(&(cf->methods_count), 2, 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
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( 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
fread(&(cf->methods[i].attributes[j].attribute_name_index), 2 + 4, 1, read_u2(&(cf->methods[i].attributes[j].attribute_name_index), 1, file);
file); read_u4(&(cf->methods[i].attributes[j].attribute_length), 1, file);
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,
@ -160,14 +190,15 @@ ClassFile *ClassFile_load(const char *path) {
} }
// attributes_count 2bytes // attributes_count 2bytes
fread(&(cf->attributes_count), 2, 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
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); cf->attributes[i].info = (u1 *)malloc(cf->attributes[i].attribute_length);
fread(cf->attributes[i].info, cf->attributes[i].attribute_length, 1, file); 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" "minor_version=%hu\n"
"major_version=%hu\n" "major_version=%hu\n"
"constant_pool_count=%hu\n" "constant_pool_count=%hu\n"
"access_flags=%hu\n" "access_flags=%hx\n"
"this_class=%hu\n" "this_class=%hu\n"
"super_class=%hu\n" "super_class=%hu\n"
"interfaces_count=%hu\n" "interfaces_count=%hu\n"

View File

@ -52,17 +52,10 @@ typedef enum {
} CONSTANT_TAGS; } CONSTANT_TAGS;
typedef struct { typedef struct {
u1 tag;
void *info;
} cp_info;
typedef struct {
u1 tag;
u2 name_index; u2 name_index;
} CONSTANT_Class_info; } CONSTANT_Class_info;
typedef struct { typedef struct {
u1 tag;
u2 class_index; u2 class_index;
u2 name_and_type_index; u2 name_and_type_index;
} CONSTANT_Fieldref_info; } CONSTANT_Fieldref_info;
@ -70,63 +63,76 @@ typedef CONSTANT_Fieldref_info CONSTANT_Methodref_info;
typedef CONSTANT_Fieldref_info CONSTANT_InterfaceMethodref_info; typedef CONSTANT_Fieldref_info CONSTANT_InterfaceMethodref_info;
typedef struct { typedef struct {
u1 tag;
u2 string_index; u2 string_index;
} CONSTANT_String_info; } CONSTANT_String_info;
typedef struct { typedef struct {
u1 tag;
u4 bytes; u4 bytes;
} CONSTANT_Integer_info; } CONSTANT_Integer_info;
typedef CONSTANT_Integer_info CONSTANT_Float_info; typedef CONSTANT_Integer_info CONSTANT_Float_info;
typedef struct { typedef struct {
u1 tag;
u4 high_bytes; u4 high_bytes;
u4 low_bytes; u4 low_bytes;
} CONSTANT_Long_info; } CONSTANT_Long_info;
typedef CONSTANT_Long_info CONSTANT_Double_info; typedef CONSTANT_Long_info CONSTANT_Double_info;
typedef struct { typedef struct {
u1 tag;
u2 name_index; u2 name_index;
u2 descriptor_index; u2 descriptor_index;
} CONSTANT_NameAndType_info; } CONSTANT_NameAndType_info;
typedef struct { typedef struct {
u1 tag;
u2 length; u2 length;
u1 *bytes; u1 *bytes;
} CONSTANT_Utf8_info; } CONSTANT_Utf8_info;
typedef struct { typedef struct {
u1 tag;
u1 reference_kind; u1 reference_kind;
u2 reference_index; u2 reference_index;
} CONSTANT_MethodHandle_info; } CONSTANT_MethodHandle_info;
typedef struct { typedef struct {
u1 tag;
u2 descriptor_index; u2 descriptor_index;
} CONSTANT_MethodType_info; } CONSTANT_MethodType_info;
typedef struct { typedef struct {
u1 tag;
u2 bootstrap_method_attr_index; u2 bootstrap_method_attr_index;
u2 name_and_type_index; u2 name_and_type_index;
} CONSTANT_Dynamic_info; } CONSTANT_Dynamic_info;
typedef CONSTANT_Dynamic_info CONSTANT_InvokeDynamic_info; typedef CONSTANT_Dynamic_info CONSTANT_InvokeDynamic_info;
typedef struct { typedef struct {
u1 tag;
u2 name_index; u2 name_index;
} CONSTANT_Module_info; } CONSTANT_Module_info;
typedef struct { typedef struct {
u1 tag;
u2 name_index; u2 name_index;
} CONSTANT_Package_info; } 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 { typedef struct {
u2 attribute_name_index; u2 attribute_name_index;
u4 attribute_length; u4 attribute_length;