From 0128ea87db23bad858ad25d534390c9d599a586a Mon Sep 17 00:00:00 2001 From: Justus Garbe <55301990+Nowilltolife@users.noreply.github.com> Date: Fri, 19 May 2023 17:59:15 +0200 Subject: [PATCH] patterns/java_class: Added Java SE 20 Attributes, added value displaying (#113) greatly enchanced the java pattern --- patterns/java_class.hexpat | 956 +++++++++++++++++++++++++++---------- 1 file changed, 692 insertions(+), 264 deletions(-) diff --git a/patterns/java_class.hexpat b/patterns/java_class.hexpat index 2a696e6..0fa5334 100644 --- a/patterns/java_class.hexpat +++ b/patterns/java_class.hexpat @@ -1,13 +1,13 @@ #pragma endian big -#pragma MIME application/x-java-applet - +#pragma pattern_limit 100000000 +#include +#include #include #include #include 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 { + 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 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 { + 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_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 { + 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 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 attributes[attributes_count]; +}; + + +struct field_info { + access_flags_field access_flags; + cp_ref name_index; + cp_ref 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]; + access_flags_method access_flags; + cp_ref name_index; + cp_ref descriptor_index; + u2 attribute_count; + attribute_info 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 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); - } -}; \ No newline at end of file +ClassFile file @ 0x0; \ No newline at end of file