diff --git a/src/bytecode.rs b/src/bytecode.rs index 7e41d6a..c188b84 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -102,7 +102,6 @@ impl Bytecode { 0x6D => (Instruction::DivideLong(), 1), 0x6E => (Instruction::DivideFloat(), 1), - 0x70 => (Instruction::ModuloInt(), 1), 0x74 => (Instruction::NegateInt(), 1), 0x75 => (Instruction::NegateLong(), 1), 0x78 => (Instruction::ArithmeticShiftIntLeft(), 1), @@ -387,7 +386,6 @@ pub enum Instruction { DivideLong() = 0x6D, // long division DivideFloat() = 0x6E, // float division - ModuloInt() = 0x70, // modulo NegateInt() = 0x74, // arithmetic negation NegateLong() = 0x75, // arithmetic negation ArithmeticShiftIntLeft() = 0x78, // shift int left, preserve sign diff --git a/src/classfile.rs b/src/classfile.rs index 4ce88d9..8e0cf65 100644 --- a/src/classfile.rs +++ b/src/classfile.rs @@ -375,15 +375,6 @@ impl JavaClassFile { return Ok((class_name, method_name, method_descriptor)); } - - pub fn gather_methodref_compatible(&self, methodref_index: u16) -> Result<(&String, &String, &String), Error> { - return match self.pool_entry(methodref_index) { - Ok(ConstantPoolInfo::MethodRef(_)) => self.gather_methodref(methodref_index), - Ok(ConstantPoolInfo::InterfaceMethodRef(_)) => self.gather_interfacemethodref(methodref_index), - Err(i) => Err(i), - _ => unreachable!() - } - } pub fn sourcefile(&self) -> Result, Error> { match (&self.attributes).into_iter() @@ -400,23 +391,6 @@ impl JavaClassFile { }, } } - - pub fn is_method_bytecode_protected(&self, method: &MethodInfo, instruction_pointer: u16, exception: crate::heap_area::ObjectReference) -> bool { - let code_attribute = method.get_code_attribute().unwrap(); - - for exception_entry in &code_attribute.exception_table { - if exception_entry.start_pc <= instruction_pointer && exception_entry.end_pc > instruction_pointer { - if exception_entry.catch_type == 0 { - return true; - } else { - // Check catch-type - todo!() - } - } - } - - false - } } #[derive(Debug)] @@ -526,10 +500,10 @@ impl LineNumberTableAttributeData { #[derive(Debug)] pub struct ExceptionTableEntry { - pub start_pc: u16, - pub end_pc: u16, - pub handler_pc: u16, - pub catch_type: u16, + start_pc: u16, + end_pc: u16, + handler_pc: u16, + catch_type: u16, } impl ExceptionTableEntry { @@ -543,10 +517,6 @@ impl ExceptionTableEntry { } ) } - - fn catches_in(&self, instruction_pointer: u16) -> bool { - return self.start_pc <= instruction_pointer && self.end_pc > instruction_pointer - } } #[derive(Debug)] @@ -1158,20 +1128,6 @@ impl MethodInfo { None }; } - - pub fn is_native(&self) -> bool { - return self.access_flags & MethodAccessFlag::Native; - } - - pub fn get_protected_handler_pc(&self, instruction_pointer: u16) -> Option { - for exception_entry in &self.get_code_attribute()?.exception_table { - if exception_entry.catches_in(instruction_pointer) { - return Some(exception_entry.handler_pc) - } - } - - None - } } diff --git a/src/jvm.rs b/src/jvm.rs index 558a734..3f24b01 100644 --- a/src/jvm.rs +++ b/src/jvm.rs @@ -1,4 +1,3 @@ -use crate::classfile::ExceptionTableEntry; use core::fmt::{Display, Formatter}; use std::collections::VecDeque; @@ -10,7 +9,7 @@ use crate::classfile; use crate::classfile::{ JavaClassFile, FieldInfo, MethodInfo, MethodDescriptor, AbstractTypeDescription, AbstractTypeKind, AttributeInfo, AttributeData, CodeAttributeData, ConstantValueAttributeData }; use crate::classstore; use crate::classstore::ClassStore; -use crate::constantpool::{ ConstantClassInfo, ConstantInterfaceMethodRefInfo, ConstantMethodRefInfo, ConstantNameAndTypeInfo, ConstantPoolInfo, ConstantUtf8Info}; +use crate::constantpool::{ ConstantPoolInfo, ConstantClassInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantNameAndTypeInfo}; use crate::heap_area::{ HeapArea, FieldValue, ObjectReference, CompartmentEntry }; use crate::iterators::{ ClassMethodIterator, ClassFieldIterator }; use crate::native_methods; @@ -260,12 +259,7 @@ impl JVM { ConstantPoolInfo::Class(ConstantClassInfo { name_index: 18 }), ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "java/lang/System".to_string() }), ConstantPoolInfo::NameAndType(ConstantNameAndTypeInfo { name_index: 20, descriptor_index: 13 }), - ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "initPhase1".to_string() }), // 20 - ConstantPoolInfo::InterfaceMethodRef(ConstantInterfaceMethodRefInfo { class_index: 22, name_and_type_index: 24}), - ConstantPoolInfo::Class(ConstantClassInfo { name_index: 23 }), - ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "java/lang/Throwable".to_string() }), - ConstantPoolInfo::NameAndType(ConstantNameAndTypeInfo { name_index: 25, descriptor_index: 13 }), - ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "printStackTrace".to_string() }), // 25 + ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "initPhase1".to_string() }), ] ), access_flags: ClassAccessFlagMask { mask: ClassAccessFlag::Super.discriminant() }, @@ -315,24 +309,9 @@ impl JVM { 0xB8_u8.to_be(), // invokestatic 0x04_u16.to_be_bytes()[0], // index 4 into the constant 0x04_u16.to_be_bytes()[1], // pool - - 0xB1_u8.to_be(), // returnvoid - // index 14 - - 0xB9_u8.to_be(), // invokeinterface - 21_u16.to_be_bytes()[0], // index 21 constant - 21_u16.to_be_bytes()[1], // index 21 constant - 0x00_u8.to_be(), // constant 0 ]), }, - exception_table: Box::new([ - ExceptionTableEntry { - start_pc: 0, - end_pc: u16::MAX, - handler_pc: 14, - catch_type: 0, // Catchall - } - ]), + exception_table: Box::new([]), attributes: Box::new([]), } ) @@ -481,43 +460,6 @@ impl JVM { JVMCallbackOperation::MakeArrayClass(component_class_ref, component_descriptor) => { self.make_array_class(component_class_ref, component_descriptor); } - - JVMCallbackOperation::ThrowException(exception) => { - let mut is_handler_found = false; - while ! is_handler_found { - is_handler_found = { - let frame = { - let frame_index = self.stack_frames.len() - 1; - &mut self.stack_frames[frame_index] - }; - let class = self.class_store.class_file_from_idx(frame.class_index).unwrap(); - let method = &class.methods[frame.method_index as usize]; - if method.is_native() { - false - } else { - class.is_method_bytecode_protected(method, frame.instruction_pointer as u16, exception) - } - }; - - if ! is_handler_found { - self.stack_frames.pop(); - } - } - - if is_handler_found { - let frame = { - let frame_index = self.stack_frames.len() - 1; - &mut self.stack_frames[frame_index] - }; - let class = self.class_store.class_file_from_idx(frame.class_index).unwrap(); - let method = &class.methods[frame.method_index as usize]; - frame.operand_stack.clear(); - wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(exception)))?; - frame.instruction_pointer = method.get_protected_handler_pc(frame.instruction_pointer as u16).unwrap() as u32; - } else { - unreachable!() - } - } } } @@ -1403,7 +1345,7 @@ impl JVM { }, Instruction::InvokeStatic(methodref_index) => { - let (supplied_class_name, supplied_method_name, supplied_descriptor_string) = class.gather_methodref_compatible(methodref_index)?; + let (supplied_class_name, supplied_method_name, supplied_descriptor_string) = class.gather_methodref(methodref_index)?; if ! self.class_store.have_class(supplied_class_name) { // rewind the bytecode offset, I'll need to execute this instruction again @@ -1842,15 +1784,6 @@ impl JVM { wrap_stackframe_error(class, method, frame.operand_stack.push_long(result))?; } - Instruction::ModuloInt() => { - let int_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - let int_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; - - let modulo = int_2.wrapping_rem(int_1); - - wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(modulo)))?; - } - Instruction::NegateInt() => { let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; let negated = -int; @@ -2029,7 +1962,6 @@ impl JVM { match expected_field_descriptor.as_str() { "Z" => FieldValue::Boolean(i != 0), "B" => FieldValue::Byte(i as i8), - "C" => FieldValue::Char(i as u16), _ => FieldValue::Int(i) } } @@ -2136,7 +2068,7 @@ impl JVM { _ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type))) } - let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?; + let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?; return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(int))); } @@ -2349,10 +2281,7 @@ impl JVM { Instruction::ThrowException() => { let exception = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?; if exception == ObjectReference::NULL { - // TODO: Throw NullPointerException - } else { - // TODO: Check throwable instance - return Ok(JVMCallbackOperation::ThrowException(exception)); + } } @@ -2383,7 +2312,6 @@ pub enum JVMCallbackOperation { LoadClass(String), InitClass(String), MakeArrayClass(ObjectReference, AbstractTypeDescription), - ThrowException(ObjectReference), } fn load_local_reference(class: &JavaClassFile, method: &MethodInfo, frame: &mut StackFrame, index: usize) -> Result<(), Error> { @@ -2439,8 +2367,8 @@ fn fill_arguments(class: &JavaClassFile, method: &MethodInfo, arguments: &mut Ve wrap_stackframe_error( class, method, - stack.pop_int_compatible(0) - )? + stack.pop_char(0) + )? as i32 ) ) }, diff --git a/src/native_methods.rs b/src/native_methods.rs index f49ffd8..350fb9d 100644 --- a/src/native_methods.rs +++ b/src/native_methods.rs @@ -461,14 +461,6 @@ impl JavaLangThrowable { } } -struct JdkInternalMiscCDS {} - -impl JdkInternalMiscCDS { - fn get_cds_config_status(_jvm: &mut JVM) -> Result { - return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(0))); - } -} - struct JdkInternalMiscUnsafe {} impl JdkInternalMiscUnsafe { @@ -2957,185 +2949,6 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul }, JavaLangThrowable::fill_in_stacktrace ), - - ( - "java/lang/invoke/MethodHandle", - "invokeExact", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - }, - todo_call - ), - - ( - "java/lang/invoke/MethodHandle", - "invoke", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - }, - todo_call - ), - - ( - "java/lang/invoke/MethodHandle", - "invokeBasic", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - }, - todo_call - ), - - ( - "java/lang/invoke/MethodHandle", - "linkToVirtual", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - }, - todo_call - ), - - ( - "java/lang/invoke/MethodHandle", - "linkToStatic", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - }, - todo_call - ), - - ( - "java/lang/invoke/MethodHandle", - "linkToSpecial", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - }, - todo_call - ), - - ( - "java/lang/invoke/MethodHandle", - "linkToInterface", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - }, - todo_call - ), - - ( - "java/lang/invoke/MethodHandle", - "linkToNative", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())}, - }, - todo_call - ), - - ( - "jdk/internal/misc/CDS", - "getCDSConfigStatus", - MethodDescriptor { - argument_types: Box::new([ - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() }, - }, - JdkInternalMiscCDS::get_cds_config_status - ), - - ( - "jdk/internal/misc/CDS", - "logLambdaFormInvoker", - 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::Void() }, - }, - todo_call - ), - - ( - "jdk/internal/misc/CDS", - "initializeFromArchive", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Class".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() }, - }, - ignore_call // TODO: idk - ), - - ( - "jdk/internal/misc/CDS", - "defineArchivedModules", - MethodDescriptor { - argument_types: Box::new([ - AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/ClassLoader".to_string())}, - AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/ClassLoader".to_string())}, - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() }, - }, - todo_call - ), - - ( - "jdk/internal/misc/CDS", - "getRandomSeedForDumping", - MethodDescriptor { - argument_types: Box::new([ - ]), - return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() }, - }, - todo_call - ), - - ( - "jdk/internal/misc/CDS", - "dumpClassList", - 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::Void() }, - }, - todo_call - ), - - ( - "jdk/internal/misc/CDS", - "dumpDynamicArchive", - 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::Void() }, - }, - todo_call - ), ]; for (classname, methodname, methoddescriptor, binding) in native_mappings { diff --git a/src/stackframe.rs b/src/stackframe.rs index a18f82b..2c31173 100644 --- a/src/stackframe.rs +++ b/src/stackframe.rs @@ -8,7 +8,7 @@ pub enum StackValue { Boolean(bool), Byte(i8), Char(u16), - Short(i16), + Short(u16), Int(i32), Float(f32), Reference(ObjectReference), @@ -47,10 +47,6 @@ impl OperandStack { } } - pub fn clear(&mut self) -> () { - self.depth = 0 - } - pub fn push(&mut self, value: StackValue) -> Result<(), Error> { if self.depth as usize == self.stack.len() { return Err(Error::PushError(format!("Trying to push onto full operand stack, capacity: {}, value: {:?}", self.depth, value))) @@ -102,15 +98,9 @@ impl OperandStack { self.push_long(l) } - FieldValue::Char(c) => { - self.push(StackValue::Char(c)) - } - - FieldValue::Short(s) => { - self.push(StackValue::Short(s)) - } - FieldValue::Double(d) => { - self.push_double(d) + _ => { + println!("{value:?}"); + todo!(); } } } @@ -197,7 +187,7 @@ impl OperandStack { } } - pub fn pop_short(&mut self, index: usize) -> Result { + pub fn pop_short(&mut self, index: usize) -> Result { let absolute_index = self.depth as usize - 1 - index; let value = self.stack[absolute_index]; self.depth -= 1; @@ -224,7 +214,6 @@ impl OperandStack { match value { StackValue::Int(i) => Ok(i), StackValue::Byte(b) => Ok(b as i32), - StackValue::Char(c) => Ok(c as i32), _ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Int-compatible but found '{:?}'", index, value))) } }