From c4da80f23cc88a52624e3bf672907c166933f9a7 Mon Sep 17 00:00:00 2001 From: VegOwOtenks Date: Fri, 15 Nov 2024 11:14:35 +0100 Subject: [PATCH] Preload java/lang/ref/Reference --- src/bytecode.rs | 2 + src/classstore.rs | 12 ++-- src/jvm.rs | 16 ++++- src/native_methods.rs | 152 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 173 insertions(+), 9 deletions(-) diff --git a/src/bytecode.rs b/src/bytecode.rs index b9ded4c..b3dcbb5 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -246,6 +246,7 @@ impl Bytecode { } 0xAC => (Instruction::ReturnInt(), 1), 0xAD => (Instruction::ReturnLong(), 1), + 0xAE => (Instruction::ReturnFloat(), 1), 0xAF => (Instruction::ReturnDouble(), 1), 0xB0 => (Instruction::ReturnReference(), 1), @@ -454,6 +455,7 @@ pub enum Instruction { LookupSwitch(i32, Box<[(i32, i32)]>) = 0xAB, // jump based on switch value ReturnInt() = 0xAC, // return integer from function ReturnLong() = 0xAD, // return long from function + ReturnFloat() = 0xAE, // return float from function ReturnDouble() = 0xAF, // return double from function ReturnReference() = 0xB0, // return top-ref from current function diff --git a/src/classstore.rs b/src/classstore.rs index e9dfc8d..3f37845 100644 --- a/src/classstore.rs +++ b/src/classstore.rs @@ -141,10 +141,14 @@ impl ClassStore { } pub fn are_types_compatible_0(&self, my_index: usize, other_name: &str) -> bool { - CompatibleTypesIterator::new(my_index, self) - .filter(|type_name| *type_name == other_name) - .next() - .is_some() + if my_index == self.class_idx_from_name(&other_name.to_string()).unwrap() { + true + } else { + CompatibleTypesIterator::new(my_index, self) + .filter(|type_name| *type_name == other_name) + .next() + .is_some() + } } pub fn are_types_compatible(&self, my_type: &AbstractTypeDescription, other_type: &AbstractTypeDescription) -> bool { diff --git a/src/jvm.rs b/src/jvm.rs index 917ae57..2774ae5 100644 --- a/src/jvm.rs +++ b/src/jvm.rs @@ -211,7 +211,8 @@ impl JVM { attributes: Box::new([]), }; - self.class_store.add_class(array_class_file, true).unwrap(); + let class_index = self.class_store.add_class(array_class_file, true).unwrap(); + self.class_store.set_class_objectref_by_index(class_index, array_class_object); self.class_store.put_array_class_ref( array_type_description, @@ -509,6 +510,7 @@ impl JVM { JVMCallbackOperation::ThrowException(exception) => { let mut is_handler_found = false; + let exception_type_index = self.heap_area.object_area.get_object_class_index(exception); while ! is_handler_found { is_handler_found = { let frame = { @@ -520,7 +522,6 @@ impl JVM { if method.is_native() { false } else { - let exception_type_index = self.heap_area.object_area.get_object_class_index(exception); class.is_method_bytecode_protected(method, frame.instruction_pointer as u16, exception_type_index, &self.class_store)? } }; @@ -2279,6 +2280,17 @@ impl JVM { return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Double(double))); } + Instruction::ReturnFloat() => { + match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) { + (0, AbstractTypeKind::Float()) => (), + _ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type))) + } + + let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?; + + return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Float(float))); + } + Instruction::ReturnInt() => { match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) { (_, AbstractTypeKind::Byte() | AbstractTypeKind::Boolean()| AbstractTypeKind::Int() | AbstractTypeKind::Char() | AbstractTypeKind::Short()) => (), diff --git a/src/native_methods.rs b/src/native_methods.rs index 42b3fd2..c22fbd0 100644 --- a/src/native_methods.rs +++ b/src/native_methods.rs @@ -455,6 +455,22 @@ impl JavaLangRuntime { } } +struct JavaLangSignal {} + +impl JavaLangSignal { + fn find_signal_0(jvm: &mut JVM) -> Result { + let frame = { + let frame_index = jvm.stack_frames.len() - 1; + &mut jvm.stack_frames[frame_index] + }; + let string_ref = frame.load_local_reference(0).unwrap(); + let rust_string = jvm.heap_area.decode_java_string(string_ref, &jvm.class_store); + + // TODO: Actually 'find' signals, HUP, INT and TERM + Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(-1))) + } +} + struct JavaLangStringUTF16 {} impl JavaLangStringUTF16 { @@ -466,6 +482,64 @@ impl JavaLangStringUTF16 { struct JavaLangSystem {} impl JavaLangSystem { + fn register_natives(jvm: &mut JVM) -> Result { + // Load class because it won't be loaded otherwise + let frame = { + let frame_index = jvm.stack_frames.len() - 1; + &mut jvm.stack_frames[frame_index] + }; + + let r#return = match frame.instruction_pointer { + 0 => { + Ok(JVMCallbackOperation::LoadClass("java/lang/ref/Reference".to_string())) + } + 1 => { + Ok(JVMCallbackOperation::InitClass("java/lang/ref/Reference".to_string())) + } + _ => { + Ok(JVMCallbackOperation::PopFrame()) + } + }; + + frame.instruction_pointer += 1; + + return r#return; + } + + fn set_err_0(jvm: &mut JVM) -> Result { + let frame = { + let frame_index = jvm.stack_frames.len() - 1; + &mut jvm.stack_frames[frame_index] + }; + let input_stream = frame.load_local_reference(0).unwrap(); + + // TODO: Bypass final + jvm.heap_area.static_area.set( + &String::from("java/lang/System"), + &String::from("err"), + FieldValue::Reference(input_stream) + )?; + + Ok(JVMCallbackOperation::PopFrame()) + } + + fn set_out_0(jvm: &mut JVM) -> Result { + let frame = { + let frame_index = jvm.stack_frames.len() - 1; + &mut jvm.stack_frames[frame_index] + }; + let input_stream = frame.load_local_reference(0).unwrap(); + + // TODO: Bypass final + jvm.heap_area.static_area.set( + &String::from("java/lang/System"), + &String::from("out"), + FieldValue::Reference(input_stream) + )?; + + Ok(JVMCallbackOperation::PopFrame()) + } + fn set_in_0(jvm: &mut JVM) -> Result { let frame = { let frame_index = jvm.stack_frames.len() - 1; @@ -1604,7 +1678,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul ]), return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()}, }, - ignore_call + JavaLangSystem::register_natives ), ( @@ -1628,7 +1702,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul ]), return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()}, }, - todo_call + JavaLangSystem::set_out_0 ), ( @@ -1640,7 +1714,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul ]), return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()}, }, - todo_call + JavaLangSystem::set_err_0 ), ( @@ -3846,6 +3920,78 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul }, ignore_call ), + + ( + "jdk/internal/misc/ScopedMemoryAccess", + "registerNatives", + MethodDescriptor { + argument_types: Box::new([ + ]), + return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() }, + }, + ignore_call + ), + + ( + "jdk/internal/misc/ScopedMemoryAccess", + "closeScope0", + MethodDescriptor { + argument_types: Box::new([ + AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("jdk/internal/foreign/MemorySessionImpl".to_string())}, + AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("jdk/internal/misc/ScopedMemoryAccess$ScopedAccessError".to_string())}, + ]), + return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() }, + }, + todo_call + ), + + ( + "java/lang/NullPointerException", + "getExtendedNPEMessage", + MethodDescriptor { + argument_types: Box::new([ + ]), + return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string()) }, + }, + todo_call + ), + + ( + "jdk/internal/misc/Signal", + "findSignal0", + MethodDescriptor { + argument_types: Box::new([ + AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())}, + ]), + return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() }, + }, + JavaLangSignal::find_signal_0 + ), + + ( + "jdk/internal/misc/Signal", + "handle0", + MethodDescriptor { + argument_types: Box::new([ + AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() }, + AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() }, + ]), + return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() }, + }, + todo_call + ), + + ( + "jdk/internal/misc/Signal", + "raise0", + MethodDescriptor { + argument_types: Box::new([ + AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() }, + ]), + return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() }, + }, + todo_call + ), ]; for (classname, methodname, methoddescriptor, binding) in native_mappings {