From 5fc36bc7f7cf501efdfafc65acef5e0861e0b137 Mon Sep 17 00:00:00 2001 From: BENEDEK Date: Thu, 16 May 2024 19:01:49 +0200 Subject: [PATCH] instruction init --- classfile.c | 42 +++++++++++++++++++++------------ classfile.h | 1 + instruction.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ instruction.h | 24 +++++++++++++++++++ main.c | 2 +- 5 files changed, 118 insertions(+), 16 deletions(-) create mode 100644 instruction.c create mode 100644 instruction.h diff --git a/classfile.c b/classfile.c index d107887..cb8e626 100644 --- a/classfile.c +++ b/classfile.c @@ -1,4 +1,5 @@ #include "classfile.h" +#include "instruction.h" #include #include #include @@ -359,18 +360,18 @@ ClassFile* ClassFile_load(const char* path) { } 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=%hx\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", + printf("Metadata:\n" + "\tmagic=%X\n" + "\tminor_version=%hu\n" + "\tmajor_version=%hu\n" + "\tconstant_pool_count=%hu\n" + "\taccess_flags=%hx\n" + "\tthis_class=%hu\n" + "\tsuper_class=%hu\n" + "\tinterfaces_count=%hu\n" + "\tfields_count=%hu\n" + "\tmethods_count=%hu\n" + "\tattributes_count=%hu\n\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); @@ -426,7 +427,7 @@ void ClassFile_info(const ClassFile* cf) { buffer); free(buffer); default: - putchar('\n'); + printf("\n"); } } @@ -435,7 +436,7 @@ void ClassFile_info(const ClassFile* cf) { char* super_name = cf->super_class != 0 ? (char*)cf->constant_pool[cf->constant_pool[cf->super_class - 1].info.class_info.name_index - 1].info.utf8_info.bytes : NULL; char* type = (cf->access_flags & ACC_INTERFACE ? "interface" : (cf->access_flags & ACC_ENUM ? "enum" : (cf->access_flags & ACC_MODULE ? "module" : "class"))); - printf("%s%s%s%s %s%s%s ", cf->access_flags & ACC_PUBLIC ? "public " : "", cf->access_flags & ACC_FINAL ? "final " : "", + printf("\n%s%s%s%s %s%s%s ", cf->access_flags & ACC_PUBLIC ? "public " : "", cf->access_flags & ACC_FINAL ? "final " : "", cf->access_flags & ACC_ABSTRACT ? "abstract " : "", type, this_name, super_name ? " extends " : "", super_name ? super_name : ""); // interfaces @@ -476,7 +477,18 @@ void ClassFile_info(const ClassFile* cf) { for (u2 j = 0; j < cf->methods[i].attributes_count; j++) { } - printf(";\n"); + printf("{\n"); + + // code + for (u2 j = 0; j < cf->methods[i].attributes_count; j++) { + if (cf->methods[i].attributes[j]._tag == CODE) { + Instruction* code = Instruction_parse(cf->methods[i].attributes[j].info.code_attribute.code_length, cf->methods[i].attributes[j].info.code_attribute.code); + Instruction_print_code(code); + // TODO: free code + } + } + + printf("\t}\n\n"); } } diff --git a/classfile.h b/classfile.h index 01ba851..ece236b 100644 --- a/classfile.h +++ b/classfile.h @@ -8,6 +8,7 @@ typedef uint8_t u1; typedef uint16_t u2; typedef uint32_t u4; +typedef uint64_t u8; typedef enum { ACC_PUBLIC = 0x0001, diff --git a/instruction.c b/instruction.c new file mode 100644 index 0000000..828bd84 --- /dev/null +++ b/instruction.c @@ -0,0 +1,65 @@ +#include "instruction.h" +#include +#include +#include +#include +#include "classfile.h" + +Instruction* Instruction_parse(uint32_t bytes_length, uint8_t* bytes) { + Instruction* start = (Instruction*)malloc(sizeof(Instruction)); + Instruction* current = start; + + u4 i = 0, n = 0; + + while (i < bytes_length) { + current->opcode = bytes[i++]; + + switch (current->opcode) { + case ALOAD_0: + case RETURN: + current->operands = NULL; + break; + case LDC: + *(u1*)¤t->operands = bytes[i++]; + break; + case GETSTATIC: + case INVOKESPECIAL: + case INVOKEVIRTUAL: + // current->operands = malloc(sizeof(u2)); + *(u2*)¤t->operands = (*(u2*)&bytes[i] << 8) | bytes[i + 1]; + i += 2; + break; + } + + if (i < bytes_length) { + current->next = (Instruction*)malloc(sizeof(Instruction)); + current = current->next; + } else { + current->next = NULL; + } + } + + return start; +} + +void Instruction_print_code(Instruction* code) { + u4 i = 0; + while (code) { + printf("\t\t%hx ", (u1)code[i].opcode); + switch (code[i].opcode) { + case ALOAD_0: + case RETURN: + putchar('\n'); + break; + case LDC: + printf("#%hhu\n", *(u1*)&code[i].operands); + break; + case GETSTATIC: + case INVOKESPECIAL: + case INVOKEVIRTUAL: + printf("#%hu\n", *(u2*)&code[i].operands); + break; + } + code = code->next; + } +} \ No newline at end of file diff --git a/instruction.h b/instruction.h new file mode 100644 index 0000000..63f5833 --- /dev/null +++ b/instruction.h @@ -0,0 +1,24 @@ +#include +#include + +#pragma pack(1) + +typedef enum { + ALOAD_0 = 0x2a, + INVOKESPECIAL = 0xb7, + RETURN = 0xb1, + GETSTATIC = 0xb2, + LDC = 0x12, + INVOKEVIRTUAL = 0xb6, +} OPCODE; + +typedef struct Instruction { + OPCODE opcode; + uint8_t* operands; + struct Instruction* next; +} Instruction; + +Instruction* Instruction_parse(uint32_t bytes_length, uint8_t* bytes); +void Instruction_print_code(Instruction* code); + +#pragma pack() \ No newline at end of file diff --git a/main.c b/main.c index dbdbbc0..112fa72 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,6 @@ #include "classfile.h" int main(int argc, char **argv) { - ClassFile *cf = ClassFile_load("test/Main.class"); + ClassFile *cf = ClassFile_load("Main.class"); ClassFile_info(cf); } \ No newline at end of file