#ifndef CLASSFILE_H #define CLASSFILE_H #include #include #include // https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.htmls table 4.3 #define CP_UTF8 1 #define CP_INTEGER 3 #define CP_FLOAT 4 #define CP_LONG 5 #define CP_DOUBLE 6 #define CP_CLASS 7 #define CP_STRING 8 #define CP_FIELDREF 9 #define CP_METHODREF 10 #define CP_IFACE_METHODREF 11 #define CP_NAME_AND_TYPE 12 // https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html table 4.1 #define ACC_PUBLIC 0x0001 #define ACC_PRIVATE 0x0002 #define ACC_PROTECTED 0x0004 #define ACC_STATIC 0x0008 #define ACC_FINAL 0x0010 #define ACC_SYNCHRONIZED 0x0020 #define ACC_NATIVE 0x0100 #define ACC_ABSTRACT 0x0400 /* ── opcodes we handle ──────────────────────────────────────────────────── */ #define OP_NOP 0x00 #define OP_ACONST_NULL 0x01 #define OP_ICONST_M1 0x02 #define OP_ICONST_0 0x03 #define OP_ICONST_1 0x04 #define OP_ICONST_2 0x05 #define OP_ICONST_3 0x06 #define OP_ICONST_4 0x07 #define OP_ICONST_5 0x08 #define OP_LCONST_0 0x09 #define OP_LCONST_1 0x0A #define OP_BIPUSH 0x10 #define OP_SIPUSH 0x11 #define OP_LDC 0x12 #define OP_LDC_W 0x13 #define OP_LDC2_W 0x14 #define OP_ILOAD 0x15 #define OP_ALOAD 0x19 #define OP_ILOAD_0 0x1A #define OP_ILOAD_1 0x1B #define OP_ILOAD_2 0x1C #define OP_ILOAD_3 0x1D #define OP_ALOAD_0 0x2A #define OP_ALOAD_1 0x2B #define OP_ALOAD_2 0x2C #define OP_ALOAD_3 0x2D #define OP_IALOAD 0x2E #define OP_ISTORE 0x36 #define OP_ASTORE 0x3A #define OP_ISTORE_0 0x3B #define OP_ISTORE_1 0x3C #define OP_ISTORE_2 0x3D #define OP_ISTORE_3 0x3E #define OP_ASTORE_0 0x4B #define OP_ASTORE_1 0x4C #define OP_ASTORE_2 0x4D #define OP_ASTORE_3 0x4E #define OP_IASTORE 0x4F #define OP_POP 0x57 #define OP_POP2 0x58 #define OP_DUP 0x59 #define OP_DUP_X1 0x5A #define OP_SWAP 0x5F #define OP_IADD 0x60 #define OP_LADD 0x61 #define OP_ISUB 0x64 #define OP_IMUL 0x68 #define OP_IDIV 0x6C #define OP_IREM 0x70 #define OP_INEG 0x74 #define OP_ISHL 0x78 #define OP_ISHR 0x7A #define OP_IUSHR 0x7C #define OP_IAND 0x7E #define OP_IOR 0x80 #define OP_IXOR 0x82 #define OP_IINC 0x84 #define OP_I2L 0x85 #define OP_I2C 0x92 #define OP_LCMP 0x94 #define OP_IFEQ 0x99 #define OP_IFNE 0x9A #define OP_IFLT 0x9B #define OP_IFGE 0x9C #define OP_IFGT 0x9D #define OP_IFLE 0x9E #define OP_IF_ICMPEQ 0x9F #define OP_IF_ICMPNE 0xA0 #define OP_IF_ICMPLT 0xA1 #define OP_IF_ICMPGE 0xA2 #define OP_IF_ICMPGT 0xA3 #define OP_IF_ICMPLE 0xA4 #define OP_IF_ACMPEQ 0xA5 #define OP_IF_ACMPNE 0xA6 #define OP_GOTO 0xA7 #define OP_IRETURN 0xAC #define OP_LRETURN 0xAD #define OP_ARETURN 0xB0 #define OP_RETURN 0xB1 #define OP_GETSTATIC 0xB2 #define OP_PUTSTATIC 0xB3 #define OP_GETFIELD 0xB4 #define OP_PUTFIELD 0xB5 #define OP_INVOKEVIRTUAL 0xB6 #define OP_INVOKESPECIAL 0xB7 #define OP_INVOKESTATIC 0xB8 #define OP_NEW 0xBB #define OP_NEWARRAY 0xBC #define OP_ANEWARRAY 0xBD #define OP_ARRAYLENGTH 0xBE #define OP_ATHROW 0xBF #define OP_CHECKCAST 0xC0 #define OP_INSTANCEOF 0xC1 #define OP_IFNULL 0xC6 #define OP_IFNONNULL 0xC7 /* ── constant pool entry ────────────────────────────────────────────────── */ typedef struct { uint8_t tag; union { /* CP_UTF8 */ struct { uint16_t len; char *bytes; } utf8; /* CP_INTEGER */ struct { int32_t value; } integer; /* CP_FLOAT */ struct { float value; } flt; /* CP_LONG */ struct { int64_t value; } lng; /* CP_DOUBLE */ struct { double value; } dbl; /* CP_CLASS, CP_STRING */ struct { uint16_t index; } cls_or_str; /* CP_FIELDREF, CP_METHODREF, CP_IFACE_METHODREF */ struct { uint16_t class_index; uint16_t name_and_type_index; } ref; /* CP_NAME_AND_TYPE */ struct { uint16_t name_index; uint16_t descriptor_index; } nat; }; } CPEntry; /* ── exception handler table entry ─────────────────────────────────────── */ typedef struct { uint16_t start_pc; uint16_t end_pc; uint16_t handler_pc; uint16_t catch_type; /* CP index to Class, or 0 = catch all */ } ExceptionHandler; /* ── Code attribute (lives inside a Method) ─────────────────────────────── */ typedef struct { uint16_t max_stack; uint16_t max_locals; uint32_t code_len; uint8_t *code; uint16_t exception_table_len; ExceptionHandler *exception_table; } CodeAttr; /* ── field ──────────────────────────────────────────────────────────────── */ typedef struct { uint16_t access_flags; uint16_t name_index; /* → CP_UTF8 */ uint16_t descriptor_index; /* → CP_UTF8 */ } Field; /* ── method ─────────────────────────────────────────────────────────────── */ typedef struct { uint16_t access_flags; uint16_t name_index; /* → CP_UTF8 */ uint16_t descriptor_index; /* → CP_UTF8 */ CodeAttr code; /* zeroed if native/abstract */ int has_code; } Method; /* ── top-level class file ───────────────────────────────────────────────── */ typedef struct { uint16_t minor_version; uint16_t major_version; /* 46 = Java 1.2 … 50 = Java 6 */ uint16_t cp_count; /* constant_pool_count from spec (1-indexed) */ CPEntry *cp; /* cp[1..cp_count-1], cp[0] unused */ uint16_t access_flags; uint16_t this_class; /* CP index */ uint16_t super_class; /* CP index (0 = java/lang/Object) */ uint16_t interfaces_count; uint16_t *interfaces; /* array of CP indices */ uint16_t fields_count; Field *fields; uint16_t methods_count; Method *methods; } ClassFile; /* ── helper: resolve UTF8 string from CP ───────────────────────────────── */ static inline const char *cp_utf8(const ClassFile *cf, uint16_t idx) { if (idx == 0 || idx >= cf->cp_count) return ""; if (cf->cp[idx].tag != CP_UTF8) return ""; return cf->cp[idx].utf8.bytes; } /* ── function declarations ──────────────────────────────────────────────── */ ClassFile *classfile_load(const char *path); void classfile_free(ClassFile *cf); Method *classfile_find_method(ClassFile *cf, const char *name, const char *descriptor); void classfile_dump(const ClassFile *cf); /* debug print */ #endif /* CLASSFILE_H */