java-llvm/classfile.c

196 lines
6.3 KiB
C

#include "classfile.h"
#include <memory.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#define SWAP_ENDIANNESS
void read_u2(void *ptr, size_t n, FILE *file) {
u2 buffer[n];
fread(&buffer, sizeof(u2), n, file);
#ifdef SWAP_ENDIANNESS
for (size_t i = 0; i < n; i++) {
buffer[i] = (buffer[i] >> 8) | (buffer[i] << 8);
}
#endif
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);
#ifdef SWAP_ENDIANNESS
for (size_t i = 0; i < n; i++) {
buffer[i] = ((buffer[i] >> 24) & 0xff) | // move byte 3 to byte 0
((buffer[i] << 8) & 0xff0000) | // move byte 1 to byte 2
((buffer[i] >> 8) & 0xff00) | // move byte 2 to byte 1
((buffer[i] << 24) & 0xff000000);
}
#endif
memcpy(ptr, &buffer, n*sizeof(u4));
}
ClassFile *ClassFile_load(const char *path) {
FILE *file = fopen(path, "rb");
if (file == NULL)
return NULL;
ClassFile *cf = (ClassFile *)malloc(sizeof(ClassFile));
// magic 4bytes, minor_version 2bytes, major_version 2bytes,
// constant_pool_count 2bytes
fread(&(cf->magic), 4 + 2 + 2 + 2, 1, 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);
size_t size;
switch (cf->constant_pool[i].tag) {
case CONSTANT_Class:
size = sizeof(CONSTANT_Class_info);
break;
case CONSTANT_Fieldref:
size = sizeof(CONSTANT_Fieldref_info);
break;
case CONSTANT_Methodref:
size = sizeof(CONSTANT_Methodref_info);
break;
case CONSTANT_InterfaceMethodref:
size = sizeof(CONSTANT_InterfaceMethodref_info);
break;
case CONSTANT_String:
size = sizeof(CONSTANT_String_info);
break;
case CONSTANT_Integer:
size = sizeof(CONSTANT_Integer_info);
break;
case CONSTANT_Float:
size = sizeof(CONSTANT_Float_info);
break;
case CONSTANT_Long:
size = sizeof(CONSTANT_Long_info);
break;
case CONSTANT_Double:
size = sizeof(CONSTANT_Double_info);
break;
case CONSTANT_NameAndType:
size = sizeof(CONSTANT_NameAndType_info);
break;
case CONSTANT_Utf8:
size = sizeof(CONSTANT_Utf8_info);
break;
case CONSTANT_MethodHandle:
size = sizeof(CONSTANT_MethodHandle_info);
break;
case CONSTANT_MethodType:
size = sizeof(CONSTANT_MethodType_info);
break;
case CONSTANT_Dynamic:
size = sizeof(CONSTANT_Dynamic_info);
break;
case CONSTANT_InvokeDynamic:
size = sizeof(CONSTANT_InvokeDynamic_info);
break;
case CONSTANT_Module:
size = sizeof(CONSTANT_Module_info);
break;
case CONSTANT_Package:
size = sizeof(CONSTANT_Package_info);
break;
}
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);
// interfaces
cf->interfaces = (u2 *)malloc(2 * cf->interfaces_count);
fread(cf->interfaces, 2 * cf->interfaces_count, 1, file);
// fields_count 2bytes
fread(&(cf->fields_count), 2, 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);
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);
cf->fields[i].attributes[j].info =
(u1 *)malloc(cf->fields[i].attributes[j].attribute_length);
fread(cf->fields[i].attributes[j].info,
cf->fields[i].attributes[j].attribute_length, 1, file);
}
}
// methods_count 2bytes
fread(&(cf->methods_count), 2, 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);
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);
cf->methods[i].attributes[j].info =
(u1 *)malloc(cf->methods[i].attributes[j].attribute_length);
fread(cf->methods[i].attributes[j].info,
cf->methods[i].attributes[j].attribute_length, 1, file);
}
}
// attributes_count 2bytes
fread(&(cf->attributes_count), 2, 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);
cf->attributes[i].info = (u1 *)malloc(cf->attributes[i].attribute_length);
fread(cf->attributes[i].info, cf->attributes[i].attribute_length, 1, file);
}
fclose(file);
return cf;
}
void ClassFile_info(const ClassFile *cf) {
printf("magic=%X\n"
"minor_version=%hu\n"
"major_version=%hu\n"
"constant_pool_count=%hu\n"
"access_flags=%hu\n"
"this_class=%hu\n"
"super_class=%hu\n"
"interfaces_count=%hu\n"
"fields_count=%hu\n"
"methods_count=%hu\n"
"attributes_count=%hu\n",
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->fields_count,
cf->methods_count, cf->attributes_count);
}