mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-27 23:37:04 -05:00
1107 lines
34 KiB
Rust
1107 lines
34 KiB
Rust
#pragma author WerWolv
|
|
#pragma description Java Class files
|
|
|
|
#pragma endian big
|
|
#pragma pattern_limit 100000000
|
|
#pragma MIME application/x-java-applet
|
|
|
|
import std.string;
|
|
import std.math;
|
|
import std.core;
|
|
import std.io;
|
|
import std.sys;
|
|
|
|
using BitfieldOrder = std::core::BitfieldOrder;
|
|
|
|
using u1 = u8;
|
|
using u2 = u16;
|
|
using u4 = u32;
|
|
|
|
using f4 = float;
|
|
using f8 = double;
|
|
|
|
using cp_ref = u16 [[format("fmt::const_ref_top")]];
|
|
|
|
bool applyPadding = false;
|
|
|
|
struct cp_info {
|
|
bool isTop = false;
|
|
if(applyPadding) {
|
|
isTop = true;
|
|
applyPadding = false;
|
|
}
|
|
else {
|
|
u1 tag;
|
|
match(tag) {
|
|
(1): { /* cp_utf8 */
|
|
u2 length;
|
|
char bytes[length];
|
|
}
|
|
(3): { /* cp_integer */
|
|
u4 bytes;
|
|
}
|
|
(4): { /* cp_float */
|
|
float bytes;
|
|
}
|
|
(5): { /* cp_long */
|
|
u64 bytes;
|
|
applyPadding = true;
|
|
}
|
|
(6): { /* cp_double */
|
|
double bytes;
|
|
applyPadding = true;
|
|
}
|
|
(7): { /* cp_class */
|
|
cp_ref name_index;
|
|
}
|
|
(8): { /* cp_string */
|
|
cp_ref string_index;
|
|
}
|
|
(9): { /* cp_fieldref */
|
|
cp_ref class_index;
|
|
cp_ref name_and_type_index;
|
|
}
|
|
(10): { /* cp_methodref */
|
|
cp_ref class_index;
|
|
cp_ref name_and_type_index;
|
|
}
|
|
(11): { /* cp_interface_methodref */
|
|
cp_ref class_index;
|
|
cp_ref name_and_type_index;
|
|
}
|
|
(12): { /* cp_name_and_type */
|
|
cp_ref name_index;
|
|
cp_ref descriptor_index;
|
|
}
|
|
(15): { /* cp_method_handle */
|
|
u1 reference_kind;
|
|
cp_ref reference_index;
|
|
}
|
|
(16): { /* cp_method_type */
|
|
cp_ref descriptor_index;
|
|
}
|
|
(18): { /* cp_invoke_dynamic */
|
|
u2 bootstrap_method_attr_index;
|
|
cp_ref name_and_type_index;
|
|
}
|
|
(19): { /* cp_module */
|
|
cp_ref name_index;
|
|
}
|
|
(20): { /* cp_package */
|
|
cp_ref name_index;
|
|
}
|
|
}
|
|
}
|
|
} [[format("fmt::const_name")]];
|
|
|
|
namespace fmt {
|
|
fn const_name(auto tag) {
|
|
if(tag.isTop) return "Top";
|
|
match(tag.tag) {
|
|
(1): return "Utf8";
|
|
(3): return "Integer";
|
|
(4): return "Float";
|
|
(5): return "Long";
|
|
(6): return "Double";
|
|
(7): return "Class";
|
|
(8): return "String";
|
|
(9): return "Fieldref";
|
|
(10): return "Methodref";
|
|
(11): return "InterfaceMethodref";
|
|
(12): return "NameAndType";
|
|
(15): return "MethodHandle";
|
|
(16): return "MethodType";
|
|
(18): return "InvokeDynamic";
|
|
(_): return "Unknown";
|
|
}
|
|
};
|
|
|
|
fn const_ref(u2 index) {
|
|
cp_info info = file.constant_pool[index-1];
|
|
match(info.tag) {
|
|
(1): return info.bytes;
|
|
(3): return std::format("{:d} [{:d}]", index, info.bytes);
|
|
(4): return std::format("{:d} [{:f}]", index, info.bytes);
|
|
(5): return std::format("{:d} [{:d}", index, info.bytes);
|
|
(6): return std::format("{:d} [{:f}", index, info.bytes);
|
|
(7): return std::format("{:d} [Class({})]", index, fmt::const_ref(info.name_index));
|
|
(8): return std::format("{:d} [String({})]", index, fmt::const_ref(info.string_index));
|
|
(9): return std::format("{:d} [Fieldref({}, {})]", index, fmt::const_ref(info.class_index), fmt::const_ref(info.name_and_type_index));
|
|
(10): return std::format("{:d} [Methodref({}, {})]", index, fmt::const_ref(info.class_index), fmt::const_ref(info.name_and_type_index));
|
|
(11): return std::format("{:d} [InterfaceMethodref({}, {})]", index, fmt::const_ref(info.class_index), fmt::const_ref(info.name_and_type_index));
|
|
(12): return std::format("{:d} [NameAndType({}, {})]", index, fmt::const_ref(info.name_index), fmt::const_ref(info.descriptor_index));
|
|
(15): return std::format("{:d} [MethodHandle({}, {})]", index, info.reference_kind, fmt::const_ref(info.reference_index));
|
|
(16): return std::format("{:d} [MethodType({})]", index, fmt::const_ref(info.descriptor_index));
|
|
(18): return std::format("{:d} [InvokeDynamic({}, {})]", index, info.bootstrap_method_attr_index, fmt::const_ref(info.name_and_type_index));
|
|
(19): return std::format("{:d} [Module({})]", index, fmt::const_ref(info.name_index));
|
|
(20): return std::format("{:d} [Package({})]", index, fmt::const_ref(info.name_index));
|
|
(_): return std::format("{:d} [Unknown]", index);
|
|
}
|
|
};
|
|
|
|
fn const_ref_top(u2 index) {
|
|
cp_info info = file.constant_pool[index-1];
|
|
match(info.tag) {
|
|
(1): return std::format("{:d} [{:s}]", index, info.bytes);
|
|
(_): return fmt::const_ref(index);
|
|
}
|
|
};
|
|
|
|
fn byte_code_fmt(auto value) {
|
|
match(value) {
|
|
(00): return "nop";
|
|
(01): return "aconst_null";
|
|
(02): return "iconst_m1";
|
|
(03): return "iconst_0";
|
|
(04): return "iconst_1";
|
|
(05): return "iconst_2";
|
|
(06): return "iconst_3";
|
|
(07): return "iconst_4";
|
|
(08): return "iconst_5";
|
|
(09): return "lconst_0";
|
|
(10): return "lconst_1";
|
|
(11): return "fconst_0";
|
|
(12): return "fconst_1";
|
|
(13): return "fconst_2";
|
|
(14): return "dconst_0";
|
|
(15): return "dconst_1";
|
|
(16): return "bipush";
|
|
(17): return "sipush";
|
|
(18): return "ldc";
|
|
(19): return "ldc_w";
|
|
(20): return "ldc2_w";
|
|
(21): return "iload";
|
|
(22): return "lload";
|
|
(23): return "fload";
|
|
(24): return "dload";
|
|
(25): return "aload";
|
|
(26): return "iload_0";
|
|
(27): return "iload_1";
|
|
(28): return "iload_2";
|
|
(29): return "iload_3";
|
|
(30): return "lload_0";
|
|
(31): return "lload_1";
|
|
(32): return "lload_2";
|
|
(33): return "lload_3";
|
|
(34): return "fload_0";
|
|
(35): return "fload_1";
|
|
(36): return "fload_2";
|
|
(37): return "fload_3";
|
|
(38): return "dload_0";
|
|
(39): return "dload_1";
|
|
(40): return "dload_2";
|
|
(41): return "dload_3";
|
|
(42): return "aload_0";
|
|
(43): return "aload_1";
|
|
(44): return "aload_2";
|
|
(45): return "aload_3";
|
|
(46): return "iaload";
|
|
(47): return "laload";
|
|
(48): return "faload";
|
|
(49): return "daload";
|
|
(50): return "aaload";
|
|
(51): return "baload";
|
|
(52): return "caload";
|
|
(53): return "saload";
|
|
(54): return "istore";
|
|
(55): return "lstore";
|
|
(56): return "fstore";
|
|
(57): return "dstore";
|
|
(58): return "astore";
|
|
(59): return "istore_0";
|
|
(60): return "istore_1";
|
|
(61): return "istore_2";
|
|
(62): return "istore_3";
|
|
(63): return "lstore_0";
|
|
(64): return "lstore_1";
|
|
(65): return "lstore_2";
|
|
(66): return "lstore_3";
|
|
(67): return "fstore_0";
|
|
(68): return "fstore_1";
|
|
(69): return "fstore_2";
|
|
(70): return "fstore_3";
|
|
(71): return "dstore_0";
|
|
(72): return "dstore_1";
|
|
(73): return "dstore_2";
|
|
(74): return "dstore_3";
|
|
(75): return "astore_0";
|
|
(76): return "astore_1";
|
|
(77): return "astore_2";
|
|
(78): return "astore_3";
|
|
(79): return "iastore";
|
|
(80): return "lastore";
|
|
(81): return "fastore";
|
|
(82): return "dastore";
|
|
(83): return "aastore";
|
|
(84): return "bastore";
|
|
(85): return "castore";
|
|
(86): return "sastore";
|
|
(87): return "pop";
|
|
(88): return "pop2";
|
|
(89): return "dup";
|
|
(90): return "dup_x1";
|
|
(91): return "dup_x2";
|
|
(92): return "dup2";
|
|
(93): return "dup2_x1";
|
|
(94): return "dup2_x2";
|
|
(95): return "swap";
|
|
(96): return "iadd";
|
|
(97): return "ladd";
|
|
(98): return "fadd";
|
|
(99): return "dadd";
|
|
(100): return "isub";
|
|
(101): return "lsub";
|
|
(102): return "fsub";
|
|
(103): return "dsub";
|
|
(104): return "imul";
|
|
(105): return "lmul";
|
|
(106): return "fmul";
|
|
(107): return "dmul";
|
|
(108): return "idiv";
|
|
(109): return "ldiv";
|
|
(110): return "fdiv";
|
|
(111): return "ddiv";
|
|
(112): return "irem";
|
|
(113): return "lrem";
|
|
(114): return "frem";
|
|
(115): return "drem";
|
|
(116): return "ineg";
|
|
(117): return "lneg";
|
|
(118): return "fneg";
|
|
(119): return "dneg";
|
|
(120): return "ishl";
|
|
(121): return "lshl";
|
|
(122): return "ishr";
|
|
(123): return "lshr";
|
|
(124): return "iushr";
|
|
(125): return "lushr";
|
|
(126): return "iand";
|
|
(127): return "land";
|
|
(128): return "ior";
|
|
(129): return "lor";
|
|
(130): return "ixor";
|
|
(131): return "lxor";
|
|
(132): return "iinc";
|
|
(133): return "i2l";
|
|
(134): return "i2f";
|
|
(135): return "i2d";
|
|
(136): return "l2i";
|
|
(137): return "l2f";
|
|
(138): return "l2d";
|
|
(139): return "f2i";
|
|
(140): return "f2l";
|
|
(141): return "f2d";
|
|
(142): return "d2i";
|
|
(143): return "d2l";
|
|
(144): return "d2f";
|
|
(145): return "i2b";
|
|
(146): return "i2c";
|
|
(147): return "i2s";
|
|
(148): return "lcmp";
|
|
(149): return "fcmpl";
|
|
(150): return "fcmpg";
|
|
(151): return "dcmpl";
|
|
(152): return "dcmpg";
|
|
(153): return "ifeq";
|
|
(154): return "ifne";
|
|
(155): return "iflt";
|
|
(156): return "ifge";
|
|
(157): return "ifgt";
|
|
(158): return "ifle";
|
|
(159): return "if_icmpeq";
|
|
(160): return "if_icmpne";
|
|
(161): return "if_icmplt";
|
|
(162): return "if_icmpge";
|
|
(163): return "if_icmpgt";
|
|
(164): return "if_icmple";
|
|
(165): return "if_acmpeq";
|
|
(166): return "if_acmpne";
|
|
(167): return "goto";
|
|
(168): return "jsr";
|
|
(169): return "ret";
|
|
(170): return "tableswitch";
|
|
(171): return "lookupswitch";
|
|
(172): return "ireturn";
|
|
(173): return "lreturn";
|
|
(174): return "freturn";
|
|
(175): return "dreturn";
|
|
(176): return "areturn";
|
|
(177): return "return";
|
|
(178): return "getstatic";
|
|
(179): return "putstatic";
|
|
(180): return "getfield";
|
|
(181): return "putfield";
|
|
(182): return "invokevirtual";
|
|
(183): return "invokespecial";
|
|
(184): return "invokestatic";
|
|
(185): return "invokeinterface";
|
|
(186): return "invokedynamic";
|
|
(187): return "new";
|
|
(188): return "newarray";
|
|
(189): return "anewarray";
|
|
(190): return "arraylength";
|
|
(191): return "athrow";
|
|
(192): return "checkcast";
|
|
(193): return "instanceof";
|
|
(194): return "monitorenter";
|
|
(195): return "monitorexit";
|
|
(196): return "wide";
|
|
(197): return "multianewarray";
|
|
(198): return "ifnull";
|
|
(199): return "ifnonnull";
|
|
(200): return "goto_w";
|
|
(201): return "jsr_w";
|
|
(202): return "breakpoint";
|
|
(254): return "impdep1";
|
|
(255): return "impdep2";
|
|
(_): return std::format("{:d} [Unknown]", value);
|
|
}
|
|
};
|
|
|
|
fn atype_fmt(auto atype) {
|
|
match(atype) {
|
|
(4): return "T_BOOLEAN";
|
|
(5): return "T_CHAR";
|
|
(6): return "T_FLOAT";
|
|
(7): return "T_DOUBLE";
|
|
(8): return "T_BYTE";
|
|
(9): return "T_SHORT";
|
|
(10): return "T_INT";
|
|
(11): return "T_LONG";
|
|
}
|
|
};
|
|
|
|
fn instruction_code_fmt(ref auto code) {
|
|
return fmt::byte_code_fmt(code.mnemonic);
|
|
};
|
|
|
|
fn attribute(auto info) {
|
|
return file.constant_pool[info.attribute_name_index-1].bytes;
|
|
};
|
|
|
|
fn verif_type_info(auto info) {
|
|
match(info.tag) {
|
|
(0): return "TOP";
|
|
(1): return "INTEGER";
|
|
(2): return "FLOAT";
|
|
(3): return "DOUBLE";
|
|
(4): return "LONG";
|
|
(5): return "NULL";
|
|
(6): return "UNINITIALIZED_THIS";
|
|
(7): return std::format("Object({})", fmt::const_ref(info.cpool_index));
|
|
(8): return std::format("Uninitialized({})", info.offset);
|
|
(_): return "Unknown";
|
|
}
|
|
};
|
|
|
|
fn stack_map_frame(auto frame) {
|
|
match(frame.frame_type) {
|
|
(0 ... 63): return std::format("SAME [{}]", frame.frame_type);
|
|
(64 ... 127): return std::format("SAME_LOCALS_1_STACK_ITEM [{}]", frame.frame_type);
|
|
(247): return std::format("SAME_LOCALS_1_STACK_ITEM_EXTENDED [{}]", frame.frame_type);
|
|
(248 ... 250): return std::format("CHOP [{}]", frame.frame_type);
|
|
(251): return std::format("SAME_FRAME_EXTENDED [{}]", frame.frame_type);
|
|
(252 ... 254): return std::format("APPEND [{}]", frame.frame_type);
|
|
(255): return std::format("FULL_FRAME [{}]", frame.frame_type);
|
|
}
|
|
};
|
|
|
|
fn element_value(auto element) {
|
|
match(element.tag) {
|
|
('B'): return std::format("byte [{:s}]", fmt::const_ref(element.const_value_index));
|
|
('C'): return std::format("char [{:s}]", fmt::const_ref(element.const_value_index));
|
|
('D'): return std::format("double [{:s}]", fmt::const_ref(element.const_value_index));
|
|
('F'): return std::format("float [{:s}]", fmt::const_ref(element.const_value_index));
|
|
('I'): return std::format("int [{:s}]", fmt::const_ref(element.const_value_index));
|
|
('J'): return std::format("long [{:s}]", fmt::const_ref(element.const_value_index));
|
|
('S'): return std::format("short [{:s}]", fmt::const_ref(element.const_value_index));
|
|
('Z'): return std::format("boolean [{:s}]", fmt::const_ref(element.const_value_index));
|
|
('s'): return std::format("String [{:s}]", fmt::const_ref(element.const_value_index));
|
|
('e'): return std::format("Enum [{:s}, {:s}]", fmt::const_ref(element.type_name_index), fmt::const_ref(element.const_name_index));
|
|
('c'): return std::format("Class [{:s}]", fmt::const_ref(element.class_info_index));
|
|
('@'): return std::format("Annotation [{:s}]", fmt::const_ref(element.annotation_value.type_index));
|
|
('['): return std::format("Array [{:s}]", fmt::const_ref(element.num_values));
|
|
}
|
|
};
|
|
}
|
|
|
|
enum major_version : u2 {
|
|
JDK_1_1 = 45,
|
|
JDK_1_2 = 46,
|
|
JDK_1_3 = 47,
|
|
JDK_1_4 = 48,
|
|
|
|
Java_SE_5_0 = 49,
|
|
Java_SE_6 = 50,
|
|
Java_SE_7 = 51,
|
|
Java_SE_8 = 52,
|
|
Java_SE_9 = 53,
|
|
Java_SE_10 = 54,
|
|
Java_SE_11 = 55,
|
|
Java_SE_12 = 56,
|
|
Java_SE_13 = 57,
|
|
Java_SE_14 = 58,
|
|
Java_SE_15 = 59,
|
|
Java_SE_16 = 60,
|
|
Java_SE_17 = 61,
|
|
};
|
|
|
|
bitfield access_flags_method {
|
|
ACC_PUBLIC : 1; // 0x0001
|
|
ACC_PRIVATE : 1; // 0x0002
|
|
ACC_PROTECTED : 1; // 0x0004
|
|
ACC_STATIC : 1; // 0x0008
|
|
ACC_FINAL : 1; // 0x0010
|
|
ACC_SYNCHRONIZED: 1; // 0x0020
|
|
ACC_BRIDGE : 1; // 0x0040
|
|
ACC_VARARGS : 1; // 0x0080
|
|
ACC_NATIVE : 1; // 0x0100
|
|
padding : 1; // 0x0200
|
|
ACC_ABSTRACT : 1; // 0x0400
|
|
ACC_STRICT : 1; // 0x0800
|
|
ACC_SYNTHETIC : 1; // 0x1000
|
|
padding : 1; // 0x2000
|
|
padding : 1; // 0x4000
|
|
padding : 1; // 0x8000
|
|
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
|
|
|
|
bitfield access_flags_field {
|
|
ACC_PUBLIC : 1; // 0x0001
|
|
ACC_PRIVATE : 1; // 0x0002
|
|
ACC_PROTECTED : 1; // 0x0004
|
|
ACC_STATIC : 1; // 0x0008
|
|
ACC_FINAL : 1; // 0x0010
|
|
padding : 1; // 0x0020
|
|
ACC_VOLATILE : 1; // 0x0040
|
|
ACC_TRANSIENT : 1; // 0x0080
|
|
padding : 1; // 0x0100
|
|
padding : 1; // 0x0200
|
|
padding : 1; // 0x0400
|
|
padding : 1; // 0x0800
|
|
ACC_SYNTHETIC : 1; // 0x1000
|
|
padding : 1; // 0x2000
|
|
ACC_ENUM : 1; // 0x4000
|
|
padding : 1; // 0x8000
|
|
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
|
|
|
|
bitfield access_flags_class {
|
|
ACC_PUBLIC : 1; // 0x0001
|
|
padding : 1; // 0x0002
|
|
padding : 1; // 0x0004
|
|
padding : 1; // 0x0008
|
|
ACC_FINAL : 1; // 0x0010
|
|
ACC_SUPER : 1; // 0x0020
|
|
padding : 1; // 0x0040
|
|
padding : 1; // 0x0080
|
|
padding : 1; // 0x0100
|
|
ACC_INTERFACE : 1; // 0x0200
|
|
ACC_ABSTRACT : 1; // 0x0400
|
|
padding : 1; // 0x0800
|
|
ACC_SYNTHETIC : 1; // 0x1000
|
|
ACC_ANNOTATION : 1; // 0x2000
|
|
ACC_ENUM : 1; // 0x4000
|
|
ACC_MODULE : 1; // 0x8000
|
|
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
|
|
|
|
bitfield access_flags_module {
|
|
padding : 1; // 0x0001
|
|
padding : 1; // 0x0002
|
|
padding : 1; // 0x0004
|
|
padding : 1; // 0x0008
|
|
padding : 1; // 0x0010
|
|
ACC_TRANSITIVE : 1; // 0x0020
|
|
ACC_STATIC_PHASE : 1; // 0x0040
|
|
padding : 1; // 0x0080
|
|
padding : 1; // 0x0100
|
|
padding : 1; // 0x0200
|
|
padding : 1; // 0x0400
|
|
padding : 1; // 0x0800
|
|
ACC_SYNTHETIC : 1; // 0x1000
|
|
padding : 1; // 0x2000
|
|
padding : 1; // 0x4000
|
|
ACC_MANDATED : 1; // 0x8000
|
|
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
|
|
|
|
using attribute_code;
|
|
|
|
struct attribute_constant_value {
|
|
cp_ref constantvalue_index;
|
|
} [[static]];
|
|
|
|
|
|
struct verification_type_info {
|
|
u1 tag;
|
|
match(tag) {
|
|
(0): { /* Top_variable_info */
|
|
}
|
|
(1): { /* Integer_variable_info */
|
|
}
|
|
(2): { /* Float_variable_info */
|
|
}
|
|
(3): { /* Long_variable_info */
|
|
}
|
|
(4): { /* Double_variable_info */
|
|
}
|
|
(5): { /* Null_variable_info */
|
|
}
|
|
(6): { /* UninitializedThis_variable_info */
|
|
}
|
|
(7): { /* Object_variable_info */
|
|
cp_ref cpool_index;
|
|
}
|
|
(8): { /* Uninitialized_variable_info */
|
|
u2 offset;
|
|
}
|
|
}
|
|
} [[format("fmt::verif_type_info")]];
|
|
|
|
struct same_locals_1_stack_item_frame {
|
|
verification_type_info stack[1];
|
|
};
|
|
|
|
struct same_locals_1_stack_item_frame_extended {
|
|
u2 offset_delta;
|
|
verification_type_info stack[1];
|
|
};
|
|
|
|
struct chop_frame {
|
|
u2 offset_delta;
|
|
};
|
|
|
|
struct same_frame_extended {
|
|
u2 offset_delta;
|
|
} [[static]];
|
|
|
|
struct append_frame<auto frame_type> {
|
|
u2 offset_delta;
|
|
verification_type_info locals[frame_type - 251];
|
|
};
|
|
|
|
struct full_frame {
|
|
u2 offset_delta;
|
|
u2 number_of_locals;
|
|
verification_type_info locals[number_of_locals];
|
|
u2 number_of_stack_items;
|
|
verification_type_info stack[number_of_stack_items];
|
|
};
|
|
|
|
struct stack_map_frame {
|
|
u1 frame_type;
|
|
match(frame_type) {
|
|
(0 ... 63): {} /* nothing */
|
|
(64 ... 127): same_locals_1_stack_item_frame child [[inline]];
|
|
(247): same_locals_1_stack_item_frame_extended child [[inline]];
|
|
(248 ... 250): chop_frame child [[inline]];
|
|
(251): same_frame_extended child [[inline]];
|
|
(252 ... 254): append_frame<frame_type> child [[inline]];
|
|
(255): full_frame child [[inline]];
|
|
}
|
|
} [[format("fmt::stack_map_frame")]];
|
|
|
|
struct same_frame {
|
|
u1 frame_type = SAME; /* 0-63 */
|
|
};
|
|
|
|
struct attribute_stack_map_table {
|
|
u2 number_of_entries;
|
|
stack_map_frame entries[number_of_entries];
|
|
};
|
|
|
|
struct attribute_exception {
|
|
u2 number_of_exceptions;
|
|
cp_ref exception_index_table[number_of_exceptions];
|
|
};
|
|
|
|
struct inner_class {
|
|
cp_ref inner_class_info_index;
|
|
u16 potential_outer_class_info_index [[hidden]];
|
|
if(potential_outer_class_info_index != 0) {
|
|
cp_ref outer_class_info_index @ addressof(potential_outer_class_info_index);
|
|
}
|
|
u16 potential_inner_name_index [[hidden]];
|
|
if(potential_inner_name_index != 0) {
|
|
cp_ref inner_name_index @ addressof(potential_inner_name_index);
|
|
}
|
|
u2 inner_class_access_flags;
|
|
};
|
|
|
|
struct attribute_inner_classes {
|
|
u2 number_of_classes;
|
|
inner_class classes[number_of_classes];
|
|
};
|
|
|
|
struct attribute_enclosing_method {
|
|
cp_ref class_index;
|
|
cp_ref method_index;
|
|
} [[static]];
|
|
|
|
struct attribute_synthetic {
|
|
};
|
|
|
|
struct attribute_signature {
|
|
cp_ref signature_index;
|
|
} [[static]];
|
|
|
|
struct attribute_source_file {
|
|
cp_ref sourcefile_index;
|
|
} [[static]];
|
|
|
|
struct attribute_source_debug_extension {
|
|
u1 debug_extension[attribute_length];
|
|
};
|
|
|
|
struct line_number_table_entry {
|
|
u2 start_pc;
|
|
u2 line_number;
|
|
} [[static]];
|
|
|
|
struct attribute_line_number_table {
|
|
u2 line_number_table_length;
|
|
line_number_table_entry line_number_table[line_number_table_length];
|
|
};
|
|
|
|
struct local_variable_table_entry {
|
|
u2 start_pc;
|
|
u2 length;
|
|
cp_ref name_index;
|
|
cp_ref descriptor_index;
|
|
u2 index;
|
|
} [[static]];
|
|
|
|
struct attribute_local_variable_table {
|
|
u2 local_variable_table_length;
|
|
local_variable_table_entry local_variable_table[local_variable_table_length];
|
|
};
|
|
|
|
struct local_variable_type_table_entry {
|
|
u2 start_pc;
|
|
u2 length;
|
|
cp_ref name_index;
|
|
cp_ref signature_index;
|
|
u2 index;
|
|
} [[static]];
|
|
|
|
struct attribute_local_variable_type_table {
|
|
u2 local_variable_type_table_length;
|
|
local_variable_type_table_entry local_variable_type_table[local_variable_type_table_length];
|
|
};
|
|
|
|
struct attribute_deprecated {
|
|
};
|
|
|
|
using annotation;
|
|
using element_value;
|
|
|
|
struct element_value {
|
|
char tag;
|
|
match(tag) {
|
|
('B' | 'C' | 'D' | 'F' | 'I' | 'J' | 'S' | 'Z' | 's'): {
|
|
cp_ref const_value_index;
|
|
}
|
|
('e'): {
|
|
cp_ref type_name_index;
|
|
cp_ref const_name_index;
|
|
}
|
|
('c'): {
|
|
cp_ref class_info_index;
|
|
}
|
|
('@'): {
|
|
annotation annotation_value;
|
|
}
|
|
('['): {
|
|
u2 num_values;
|
|
element_value values[num_values];
|
|
}
|
|
(_): {
|
|
std::error("Unknown element_value tag: %c", tag);
|
|
}
|
|
}
|
|
} [[format("fmt::element_value")]];
|
|
|
|
struct element_value_pair {
|
|
cp_ref element_name_index;
|
|
element_value value;
|
|
};
|
|
|
|
struct annotation {
|
|
cp_ref type_index;
|
|
u2 num_element_value_pairs;
|
|
element_value_pair element_value_pairs[num_element_value_pairs];
|
|
};
|
|
|
|
struct annotation_base {
|
|
u2 num_annotations;
|
|
annotation annotations[num_annotations];
|
|
};
|
|
|
|
struct attribute_runtime_visible_annotations {
|
|
annotation_base [[inline]];
|
|
};
|
|
|
|
struct attribute_runtime_invisible_annotations {
|
|
annotation_base [[inline]];
|
|
};
|
|
|
|
struct attribute_runtime_visible_parameter_annotations {
|
|
u1 num_parameters;
|
|
annotation_base parameter_annotations[num_parameters];
|
|
};
|
|
|
|
struct attribute_runtime_invisible_parameter_annotations {
|
|
u1 num_parameters;
|
|
annotation_base parameter_annotations[num_parameters];
|
|
};
|
|
|
|
struct path_element {
|
|
u1 type_path_kind;
|
|
u1 type_argument_index;
|
|
};
|
|
|
|
struct type_path {
|
|
u1 path_length;
|
|
path_element path[path_length];
|
|
};
|
|
|
|
struct localvar_target_entry {
|
|
u2 start_pc;
|
|
u2 length;
|
|
u2 index;
|
|
};
|
|
|
|
struct target_info<auto target_type> {
|
|
match(target_type) {
|
|
(0x00 | 0x01): { /* type_parameter_target */
|
|
u1 type_parameter_index;
|
|
}
|
|
(0x10): { /* supertype_target */
|
|
u2 supertype_index;
|
|
}
|
|
(0x11 | 0x12): { /* type_parameter_bound_target */
|
|
u1 type_parameter_index;
|
|
u1 bound_index;
|
|
}
|
|
(0x13 | 0x14 | 0x15): { /* empty_target */ }
|
|
(0x16): { /* formal_parameter_target */
|
|
u1 formal_parameter_index;
|
|
}
|
|
(0x17): { /* throws_target */
|
|
u2 throws_type_index;
|
|
}
|
|
(0x40 | 0x41): { /* localvar_target */
|
|
u2 table_length;
|
|
localvar_target_entry table[table_length];
|
|
}
|
|
(0x42): { /* catch_target */
|
|
u2 exception_table_index;
|
|
}
|
|
(0x43 | 0x44 | 0x45 | 0x46): { /* offset_target */
|
|
u2 offset;
|
|
}
|
|
(0x47 | 0x48 | 0x49 | 0x4A): { /* type_argument_target */
|
|
u2 offset;
|
|
u1 type_argument_index;
|
|
}
|
|
}
|
|
};
|
|
|
|
struct type_annotation {
|
|
u1 target_type;
|
|
target_info<target_type> target_info;
|
|
type_path type_path;
|
|
annotation annotation [[inline]];
|
|
};
|
|
|
|
struct attribute_runtime_visible_type_annotations {
|
|
u2 num_annotations;
|
|
type_annotation annotations[num_annotations];
|
|
};
|
|
|
|
struct attribute_runtime_invisible_type_annotations {
|
|
u2 num_annotations;
|
|
type_annotation annotations[num_annotations];
|
|
};
|
|
|
|
struct attribute_annotation_default {
|
|
element_value default_value;
|
|
};
|
|
|
|
struct bootstrap_method {
|
|
cp_ref bootstrap_method_ref;
|
|
u2 num_bootstrap_arguments;
|
|
cp_ref bootstrap_arguments[num_bootstrap_arguments];
|
|
};
|
|
|
|
struct attribute_bootstrap_methods {
|
|
u2 num_bootstrap_methods;
|
|
bootstrap_method bootstrap_methods[num_bootstrap_methods];
|
|
};
|
|
|
|
struct method_parameter {
|
|
u2 potential_name_index [[hidden]];
|
|
if (potential_name_index != 0) {
|
|
cp_ref name_index @ addressof(potential_name_index);
|
|
}
|
|
u2 access_flags;
|
|
};
|
|
|
|
struct attribute_method_parameters {
|
|
u1 parameters_count;
|
|
method_parameter parameters[parameters_count];
|
|
};
|
|
|
|
struct require {
|
|
cp_ref require_index;
|
|
access_flags_module require_flags;
|
|
u2 potential_require_version_index [[hidden]];
|
|
if (potential_require_version_index != 0) {
|
|
cp_ref require_version_index @ addressof(potential_require_version_index);
|
|
}
|
|
};
|
|
|
|
struct export {
|
|
cp_ref exports_index;
|
|
access_flags_module exports_flags;
|
|
u2 exports_to_count;
|
|
cp_ref exports_to_index[exports_to_count];
|
|
};
|
|
|
|
struct open {
|
|
cp_ref opens_index;
|
|
access_flags_module opens_flags;
|
|
u2 opens_to_count;
|
|
cp_ref opens_to_index[opens_to_count];
|
|
};
|
|
|
|
struct provide {
|
|
cp_ref provides_index;
|
|
u2 provides_with_count;
|
|
cp_ref provides_with_index[provides_with_count];
|
|
};
|
|
|
|
struct attribute_module {
|
|
cp_ref module_name_index;
|
|
u2 module_flags;
|
|
u2 potential_module_version_index [[hidden]];
|
|
if (potential_module_version_index != 0) {
|
|
cp_ref module_version_index @ addressof(potential_module_version_index);
|
|
}
|
|
u2 requires_count;
|
|
require requires[requires_count];
|
|
u2 exports_count;
|
|
export exports[exports_count];
|
|
u2 opens_count;
|
|
open opens[opens_count];
|
|
u2 uses_count;
|
|
cp_ref uses_index[uses_count];
|
|
u2 provides_count;
|
|
provide provides[provides_count];
|
|
};
|
|
|
|
struct attribute_module_packages {
|
|
u2 package_count;
|
|
cp_ref package_index[package_count];
|
|
};
|
|
|
|
struct attribute_module_main_class {
|
|
cp_ref main_class_index;
|
|
};
|
|
|
|
struct attribute_nest_host {
|
|
cp_ref host_class_index;
|
|
};
|
|
|
|
struct attribute_nest_members {
|
|
u2 number_of_classes;
|
|
cp_ref classes[number_of_classes];
|
|
};
|
|
|
|
using record_component_info;
|
|
|
|
struct attribute_record {
|
|
u2 component_count;
|
|
record_component_info components[component_count];
|
|
};
|
|
|
|
struct attribute_permitted_subclasses {
|
|
u2 number_of_classes;
|
|
cp_ref classes[number_of_classes];
|
|
};
|
|
|
|
struct attribute_info<auto constant_pool> {
|
|
cp_ref attribute_name_index;
|
|
u4 attribute_length;
|
|
match(constant_pool[attribute_name_index-1].bytes) {
|
|
("Code"): attribute_code child [[inline]];
|
|
("ConstantValue"): attribute_constant_value [[inline]];
|
|
("StackMapTable"): attribute_stack_map_table [[inline]];
|
|
("Exceptions"): attribute_exception [[inline]];
|
|
("InnerClasses"): attribute_inner_classes [[inline]];
|
|
("EnclosingMethod"): attribute_enclosing_method [[inline]];
|
|
("Synthetic"): attribute_synthetic [[inline]];
|
|
("Signature"): attribute_signature [[inline]];
|
|
("SourceFile"): attribute_source_file [[inline]];
|
|
("SourceDebugExtension"): attribute_source_debug_extension [[inline]];
|
|
("LineNumberTable"): attribute_line_number_table [[inline]];
|
|
("LocalVariableTable"): attribute_local_variable_table [[inline]];
|
|
("LocalVariableTypeTable"): attribute_local_variable_type_table [[inline]];
|
|
("Deprecated"): attribute_deprecated [[inline]];
|
|
("RuntimeVisibleAnnotations"): attribute_runtime_visible_annotations [[inline]];
|
|
("RuntimeInvisibleAnnotations"): attribute_runtime_invisible_annotations [[inline]];
|
|
("RuntimeVisibleParameterAnnotations"): attribute_runtime_visible_parameter_annotations [[inline]];
|
|
("RuntimeInvisibleParameterAnnotations"): attribute_runtime_invisible_parameter_annotations [[inline]];
|
|
("RuntimeVisibleTypeAnnotations"): attribute_runtime_visible_type_annotations [[inline]];
|
|
("RuntimeInvisibleTypeAnnotations"): attribute_runtime_invisible_type_annotations [[inline]];
|
|
("AnnotationDefault"): attribute_annotation_default [[inline]];
|
|
("BootstrapMethods"): attribute_bootstrap_methods [[inline]];
|
|
("MethodParameters"): attribute_method_parameters [[inline]];
|
|
("Module"): attribute_module [[inline]];
|
|
("ModulePackages"): attribute_module_packages [[inline]];
|
|
("ModuleMainClass"): attribute_module_main_class [[inline]];
|
|
("NestHost"): attribute_nest_host [[inline]];
|
|
("NestMembers"): attribute_nest_members [[inline]];
|
|
("Record"): attribute_record [[inline]];
|
|
(_): u1 info[attribute_length];
|
|
}
|
|
if(($-(addressof(this)+6)) != attribute_length) std::warning("Invalid attribute length at "
|
|
+ std::format("{:x}", addressof(this))
|
|
+ " " + std::string::to_string($-(addressof(this)+6)) + "!=" + std::string::to_string(attribute_length));
|
|
} [[format("fmt::attribute")]];
|
|
|
|
struct record_component_info {
|
|
cp_ref name_index;
|
|
cp_ref descriptor_index;
|
|
u2 attributes_count;
|
|
attribute_info<parent.parent.parent.constant_pool> attributes[attributes_count];
|
|
};
|
|
|
|
struct exception {
|
|
u2 start_pc;
|
|
u2 end_pc;
|
|
u2 handler_pc;
|
|
u2 catch_type;
|
|
} [[static]];
|
|
|
|
struct match_offset {
|
|
u4 match_case;
|
|
u4 offset;
|
|
};
|
|
|
|
struct instruction {
|
|
u1 mnemonic [[format("fmt::byte_code_fmt")]];
|
|
match(mnemonic) {
|
|
(0 ... 15 | 26 ... 53 | 59 ... 131 | 133 ... 152 | 172 ... 177 | 190 | 191 | 194 | 195): {}
|
|
(16): {
|
|
u1 byte;
|
|
}
|
|
(17): {
|
|
u2 value;
|
|
}
|
|
(18):{
|
|
u1 index [[format("fmt::const_ref_top")]];
|
|
}
|
|
(19|20 | 178 ... 184 | 187 | 189 | 192 | 193): {
|
|
cp_ref cp_index;
|
|
}
|
|
(21 ... 25 | 54 ... 58 | 169): {
|
|
u1 local_index;
|
|
}
|
|
(132): {
|
|
u1 local_index;
|
|
u1 const_;
|
|
}
|
|
(153 ... 168 | 198 | 199): {
|
|
u2 branch_offset;
|
|
}
|
|
(185): {
|
|
cp_ref index;
|
|
u1 count;
|
|
padding[1];
|
|
}
|
|
(186): {
|
|
cp_ref cp_index;
|
|
padding[2];
|
|
}
|
|
(188): {
|
|
u1 atype [[format("fmt::atype_fmt")]];
|
|
}
|
|
(196): {
|
|
u1 op_code [[format("fmt::byte_code_fmt")]];
|
|
u2 local_index;
|
|
if(op_code == 132){
|
|
u2 const_byte;
|
|
}
|
|
}
|
|
(197): {
|
|
cp_ref cp_index;
|
|
u1 dimensions;
|
|
}
|
|
(200 | 201): {
|
|
u4 branch_offset;
|
|
}
|
|
(170): {
|
|
padding[(4 - ($ - addressof(parent) -8) % 4) % 4];
|
|
u4 default_offset;
|
|
u4 low;
|
|
u4 high;
|
|
u4 jump_offset[high-low+1];
|
|
}
|
|
(171): {
|
|
padding[(4 - ($ - addressof(parent) -8) % 4) % 4];
|
|
u4 default_offset;
|
|
u4 npairs;
|
|
match_offset match_offsets[npairs];
|
|
}
|
|
}
|
|
} [[format("fmt::instruction_code_fmt")]];
|
|
|
|
|
|
struct attribute_code {
|
|
u2 max_stack;
|
|
u2 max_locals;
|
|
u4 code_length;
|
|
u4 target_addr = $ + code_length;
|
|
instruction code[while($ < target_addr)];
|
|
u2 exception_table_length;
|
|
exception exception_table[exception_table_length];
|
|
u2 attributes_count;
|
|
attribute_info<parent.parent.parent.constant_pool> attributes[attributes_count];
|
|
};
|
|
|
|
|
|
struct field_info {
|
|
access_flags_field access_flags;
|
|
cp_ref name_index;
|
|
cp_ref descriptor_index;
|
|
u2 attribute_count;
|
|
attribute_info<parent.constant_pool> attributes[attribute_count];
|
|
};
|
|
|
|
struct method_info {
|
|
access_flags_method access_flags;
|
|
cp_ref name_index;
|
|
cp_ref descriptor_index;
|
|
u2 attribute_count;
|
|
attribute_info<parent.constant_pool> attributes[attribute_count];
|
|
};
|
|
|
|
struct ClassFile {
|
|
u1 magic[4];
|
|
u2 minor_version;
|
|
major_version major_version;
|
|
u2 constant_pool_count;
|
|
cp_info constant_pool[constant_pool_count-1];
|
|
access_flags_class access_flags;
|
|
cp_ref this_class;
|
|
cp_ref super_class;
|
|
u2 interfaces_count;
|
|
cp_ref interfaces[interfaces_count];
|
|
u2 fields_count;
|
|
field_info fields[fields_count];
|
|
u2 methods_count;
|
|
method_info methods[methods_count];
|
|
u2 attributes_count;
|
|
attribute_info<constant_pool> attributes[attributes_count];
|
|
};
|
|
|
|
ClassFile file @ 0x0;
|