mirror of
https://github.com/WerWolv/ImHex-Patterns.git
synced 2026-03-28 07:47:02 -05:00
patterns/java_class: Added Java SE 20 Attributes, added value displaying (#113)
greatly enchanced the java pattern
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
#pragma endian big
|
||||
#pragma MIME application/x-java-applet
|
||||
|
||||
#pragma pattern_limit 100000000
|
||||
#include <std/string.pat>
|
||||
#include <std/math.pat>
|
||||
#include <std/core.pat>
|
||||
#include <std/io.pat>
|
||||
#include <std/sys.pat>
|
||||
|
||||
using BitfieldOrder = std::core::BitfieldOrder;
|
||||
|
||||
// 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;
|
||||
@@ -15,24 +15,182 @@ 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,
|
||||
CONSTANT_Module = 19,
|
||||
CONSTANT_Package = 20
|
||||
};
|
||||
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 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,
|
||||
@@ -55,143 +213,6 @@ enum major_version : u2 {
|
||||
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;
|
||||
};
|
||||
|
||||
// Tag == CONSTANT_Module
|
||||
struct CONSTANT_Module_info {
|
||||
u2 name_index;
|
||||
};
|
||||
|
||||
// Tag == CONSTANT_Package
|
||||
struct CONSTANT_Package_info {
|
||||
u2 name_index;
|
||||
};
|
||||
|
||||
// All 8-byte constants take up two entries in the constant_pool table of the class file
|
||||
u1 padding_entry_flag = 0;
|
||||
|
||||
struct cp_info {
|
||||
if (padding_entry_flag == 0) {
|
||||
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]];
|
||||
padding_entry_flag = 1;
|
||||
}
|
||||
else if (tag == cp_tag::CONSTANT_Double) {
|
||||
CONSTANT_Double_info info [[inline]];
|
||||
padding_entry_flag = 1;
|
||||
}
|
||||
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]];
|
||||
else if (tag == cp_tag::CONSTANT_Module)
|
||||
CONSTANT_Module_info info [[inline]];
|
||||
else if (tag == cp_tag::CONSTANT_Package)
|
||||
CONSTANT_Package_info info [[inline]];
|
||||
} else {
|
||||
padding_entry_flag = 0;
|
||||
}
|
||||
};
|
||||
|
||||
bitfield access_flags_method {
|
||||
ACC_PUBLIC : 1; // 0x0001
|
||||
ACC_PRIVATE : 1; // 0x0002
|
||||
@@ -249,122 +270,529 @@ bitfield access_flags_class {
|
||||
ACC_MODULE : 1; // 0x8000
|
||||
} [[bitfield_order(BitfieldOrder::LeastToMostSignificant, 16)]];
|
||||
|
||||
struct attribute_info {
|
||||
u2 attribute_name_info;
|
||||
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;
|
||||
|
||||
u4 attribute_length;
|
||||
struct attribute_constant_value {
|
||||
cp_ref constantvalue_index;
|
||||
} [[static]];
|
||||
|
||||
u1 info[attribute_length];
|
||||
|
||||
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 field_info {
|
||||
access_flags_field access_flags;
|
||||
u2 name_index;
|
||||
u2 descriptor_index;
|
||||
struct same_locals_1_stack_item_frame_extended {
|
||||
u2 offset_delta;
|
||||
verification_type_info stack[1];
|
||||
};
|
||||
|
||||
u2 attribute_count;
|
||||
attribute_info attributes[attribute_count];
|
||||
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 __ [[hidden]];
|
||||
if(__ != 0) {
|
||||
cp_ref outer_class_info_index @ addressof(__);
|
||||
}
|
||||
u16 ___ [[hidden]];
|
||||
if(___ != 0) {
|
||||
cp_ref inner_name_index @ addressof(___);
|
||||
}
|
||||
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 name_index [[hidden]];
|
||||
if (name_index != 0) {
|
||||
cp_ref name_index @ addressof(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 require_version_index [[hidden]];
|
||||
if (require_version_index != 0) {
|
||||
cp_ref require_version_index @ addressof(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 module_version_index [[hidden]];
|
||||
if (module_version_index != 0) {
|
||||
cp_ref module_version_index @ addressof(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 attribute_code {
|
||||
u2 max_stack;
|
||||
u2 max_locals;
|
||||
u4 code_length;
|
||||
u1 code[code_length];
|
||||
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;
|
||||
u2 name_index;
|
||||
u2 descriptor_index;
|
||||
u2 attributes_count;
|
||||
attribute_info attributes[attributes_count];
|
||||
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 {
|
||||
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];
|
||||
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 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 field_string = " ";
|
||||
|
||||
if (class_file.fields[i].access_flags.ACC_PUBLIC)
|
||||
field_string = field_string + "public ";
|
||||
if (class_file.fields[i].access_flags.ACC_PRIVATE)
|
||||
field_string = field_string + "private ";
|
||||
if (class_file.fields[i].access_flags.ACC_PROTECTED)
|
||||
field_string = field_string + "protected ";
|
||||
if (class_file.fields[i].access_flags.ACC_STATIC)
|
||||
field_string = field_string + "static ";
|
||||
if (class_file.fields[i].access_flags.ACC_FINAL)
|
||||
field_string = field_string + "final ";
|
||||
if (class_file.fields[i].access_flags.ACC_VOLATILE)
|
||||
field_string = field_string + "volatile ";
|
||||
if (class_file.fields[i].access_flags.ACC_TRANSIENT)
|
||||
field_string = field_string + "transient ";
|
||||
if (class_file.fields[i].access_flags.ACC_ENUM)
|
||||
field_string = field_string + "enum ";
|
||||
|
||||
field_string = field_string + class_file.constant_pool[class_file.fields[i].name_index - 1].info.bytes;
|
||||
field_string = field_string + " [ " + class_file.constant_pool[class_file.fields[i].descriptor_index - 1].info.bytes + " ]";
|
||||
|
||||
std::print("{}", field_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);
|
||||
}
|
||||
};
|
||||
ClassFile file @ 0x0;
|
||||
Reference in New Issue
Block a user