Files
ImHex-Patterns/patterns/java_class.hexpat
2021-11-21 10:51:56 +01:00

339 lines
11 KiB
Plaintext

#pragma endian big
#pragma MIME application/x-java-applet
// The Java documentations use the number of bytes instead of the number of bits for its type names
using u1 = u8;
using u2 = u16;
using u4 = u32;
using f4 = float;
using f8 = double;
enum cp_tag : u8 {
CONSTANT_Utf8 = 1,
CONSTANT_Integer = 3,
CONSTANT_Float = 4,
CONSTANT_Long = 5,
CONSTANT_Double = 6,
CONSTANT_Class = 7,
CONSTANT_String = 8,
CONSTANT_Fieldref = 9,
CONSTANT_Methodref = 10,
CONSTANT_InterfaceMethodref = 11,
CONSTANT_NameAndType = 12,
CONSTANT_MethodHandle = 15,
CONSTANT_MethodType = 16,
CONSTANT_InvokeDynamic = 18
};
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_0 = 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,
};
// Tag == CONSTANT_Utf8
struct CONSTANT_Utf8_info {
u2 length;
char bytes[length]; // u1 in documentation. Changed to char to improve readability
};
// Tag == CONSTANT_Integer
struct CONSTANT_Integer_info {
u4 bytes;
};
// Tag == CONSTANT_Float
struct CONSTANT_Float_info {
f4 bytes; // u4 in documentation. Changed to f4 to improve readablilty
};
// Tag == CONSTANT_Long
struct CONSTANT_Long_info {
u4 high_bytes;
u4 low_bytes;
};
// Tag == CONSTANT_Double
struct CONSTANT_Double_info {
u4 high_bytes;
u4 low_bytes;
};
// Tag == CONSTANT_Class
struct CONSTANT_Class_info {
u2 name_index;
};
// Tag == CONSTANT_String
struct CONSTANT_String_info {
u2 string_index;
};
// Tag == CONSTANT_Fieldref
struct CONSTANT_Fieldref_info {
u2 class_index;
u2 name_and_type_index;
};
// Tag == CONSTANT_Methodref
struct CONSTANT_Methodref_info {
u2 class_index;
u2 name_and_type_index;
};
// Tag == CONSTANT_InterfaceMethodref
struct CONSTANT_InterfaceMethodref_info {
u2 class_index;
u2 name_and_type_index;
};
// Tag == CONSTANT_NameAndType
struct CONSTANT_NameAndType_info {
u2 name_index;
u2 descriptor_index;
};
// Tag == CONSTANT_MethodHandle
struct CONSTANT_MethodHandle_info {
u1 reference_kind;
u2 reference_index;
};
// Tag == CONSTANT_MethodType
struct CONSTANT_MethodType_info {
u2 descriptor_index;
};
// Tag == CONSTANT_InvokeDynamic
struct CONSTANT_InvokeDynamic_info {
u2 bootstrap_method_attr_index;
u2 name_and_type_index;
};
struct cp_info {
cp_tag tag;
if (tag == cp_tag::CONSTANT_Utf8)
CONSTANT_Utf8_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Integer)
CONSTANT_Integer_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Float)
CONSTANT_Float_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Long)
CONSTANT_Long_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Double)
CONSTANT_Double_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Class)
CONSTANT_Class_info info [[inline]];
else if (tag == cp_tag::CONSTANT_String)
CONSTANT_String_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Fieldref)
CONSTANT_Fieldref_info info [[inline]];
else if (tag == cp_tag::CONSTANT_Methodref)
CONSTANT_Methodref_info info [[inline]];
else if (tag == cp_tag::CONSTANT_InterfaceMethodref)
CONSTANT_InterfaceMethodref_info info [[inline]];
else if (tag == cp_tag::CONSTANT_NameAndType)
CONSTANT_NameAndType_info info [[inline]];
else if (tag == cp_tag::CONSTANT_MethodHandle)
CONSTANT_MethodHandle_info info [[inline]];
else if (tag == cp_tag::CONSTANT_MethodType)
CONSTANT_MethodType_info info [[inline]];
else if (tag == cp_tag::CONSTANT_InvokeDynamic)
CONSTANT_InvokeDynamic_info info [[inline]];
};
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 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 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
padding : 1; // 0x8000
};
struct attribute_info {
u2 attribute_name_info;
u4 attribute_length;
u1 info[attribute_length];
};
struct field_info {
access_flags_field access_flags;
u2 name_index;
u2 descriptor_index;
u2 attribute_count;
attribute_info attributes[attribute_count];
};
struct method_info {
access_flags_method access_flags;
u2 name_index;
u2 descriptor_index;
u2 attributes_count;
attribute_info attributes[attributes_count];
};
struct ClassFile {
u4 magic;
u2 minor_version;
major_version major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count - 1];
access_flags_class access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attribute_count;
attribute_info attributes[attribute_count];
};
ClassFile class_file @ 0x00;
fn main() {
std::assert(class_file.magic == 0xCAFEBABE, "File is not a valid Java Class file! Invalid header magic");
std::print("Fields:");
for (le u16 i = 0, i < class_file.fields_count, i = i + 1) {
str method_string = " ";
if (class_file.fields[i].access_flags.ACC_PUBLIC)
method_string = method_string + "public ";
if (class_file.fields[i].access_flags.ACC_PRIVATE)
method_string = method_string + "private ";
if (class_file.fields[i].access_flags.ACC_PROTECTED)
method_string = method_string + "protected ";
if (class_file.fields[i].access_flags.ACC_STATIC)
method_string = method_string + "static ";
if (class_file.fields[i].access_flags.ACC_FINAL)
method_string = method_string + "final ";
if (class_file.fields[i].access_flags.ACC_VOLATILE)
method_string = method_string + "volatile ";
if (class_file.fields[i].access_flags.ACC_NATIVE)
method_string = method_string + "native ";
if (class_file.fields[i].access_flags.ACC_TRANSIENT)
method_string = method_string + "transient ";
if (class_file.fields[i].access_flags.ACC_ENUM)
method_string = method_string + "enum ";
method_string = method_string + class_file.constant_pool[class_file.fields[i].name_index - 1].info.bytes;
method_string = method_string + " [ " + class_file.constant_pool[class_file.fields[i].descriptor_index - 1].info.bytes + " ]";
std::print("{}", method_string);
}
std::print("Methods:");
for (le u16 i = 0, i < class_file.methods_count, i = i + 1) {
str method_string = " ";
if (class_file.methods[i].access_flags.ACC_PUBLIC)
method_string = method_string + "public ";
if (class_file.methods[i].access_flags.ACC_PRIVATE)
method_string = method_string + "private ";
if (class_file.methods[i].access_flags.ACC_PROTECTED)
method_string = method_string + "protected ";
if (class_file.methods[i].access_flags.ACC_STATIC)
method_string = method_string + "static ";
if (class_file.methods[i].access_flags.ACC_FINAL)
method_string = method_string + "final ";
if (class_file.methods[i].access_flags.ACC_SYNCHRONIZED)
method_string = method_string + "synchronized ";
if (class_file.methods[i].access_flags.ACC_NATIVE)
method_string = method_string + "native ";
if (class_file.methods[i].access_flags.ACC_ABSTRACT)
method_string = method_string + "abstract ";
if (class_file.methods[i].access_flags.ACC_STRICT)
method_string = method_string + "strictfp ";
method_string = method_string + class_file.constant_pool[class_file.methods[i].name_index - 1].info.bytes;
method_string = method_string + " [ " + class_file.constant_pool[class_file.methods[i].descriptor_index - 1].info.bytes + " ]";
std::print("{}", method_string);
}
std::print("Class Attributes:");
for (le u16 i = 0, i < class_file.attribute_count, i = i + 1) {
std::print(" {}", class_file.constant_pool[class_file.attributes[i].attribute_name_info - 1].info.bytes);
}
};