diff --git a/jclass/src/error.rs b/jclass/src/error.rs index 9956e134..61296c55 100644 --- a/jclass/src/error.rs +++ b/jclass/src/error.rs @@ -1,6 +1,6 @@ +use crate::error::ErrorKind::{InvalidInput, Io}; use std::fmt::{Debug, Display, Formatter}; use std::{error::Error as StdError, io, result}; -use crate::error::ErrorKind::{InvalidInput, Io}; pub type Result = result::Result; diff --git a/src/main.rs b/src/main.rs index 6dbe936c..81462727 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,8 @@ use std::process; use vm::vm::VM; fn print_usage() -> Result<(), String> { - let current_exe = env::current_exe().map_err( - |err| format!("Failed to get the current executable path: {}", err))?; + let current_exe = env::current_exe() + .map_err(|err| format!("Failed to get the current executable path: {}", err))?; let file_name = current_exe .file_name() .and_then(|name| name.to_str()) diff --git a/tests/integration_test.rs b/tests/integration_test.rs index 88497e9a..73ec16aa 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -1,4 +1,3 @@ - use vm::vm::VM; #[test] diff --git a/vm/src/class_loader.rs b/vm/src/class_loader.rs index 196cd62c..f1b0a243 100644 --- a/vm/src/class_loader.rs +++ b/vm/src/class_loader.rs @@ -1,15 +1,15 @@ -use std::collections::HashMap; -use std::fs::File; -use std::io::Read; -use jclass::attributes::Attribute; -use jclass::class_file::{parse, ClassFile}; -use jclass::constant_pool::ConstantPool::{Methodref, NameAndType, Utf8}; -use jclass::attributes::Attribute::Code; -use crate::error::{Result, Error, ErrorKind}; +use crate::error::{Error, ErrorKind, Result}; use crate::method_area::java_class::{JavaClass, Methods}; use crate::method_area::java_method::JavaMethod; use crate::method_area::method_area::MethodArea; use crate::method_area::signature::Signature; +use jclass::attributes::Attribute; +use jclass::attributes::Attribute::Code; +use jclass::class_file::{parse, ClassFile}; +use jclass::constant_pool::ConstantPool::{Methodref, NameAndType, Utf8}; +use std::collections::HashMap; +use std::fs::File; +use std::io::Read; #[derive(Debug)] pub struct ClassLoader { @@ -28,7 +28,9 @@ impl ClassLoader { let java_class = Self::to_java_class(class_file)?; - Ok(Self { method_area: MethodArea::new(java_class) }) + Ok(Self { + method_area: MethodArea::new(java_class), + }) } fn to_java_class(class_file: ClassFile) -> Result { @@ -45,64 +47,107 @@ impl ClassLoader { for method in methods.iter() { let method_name = Self::get_cpool_string(class_file, method.name_index() as usize) .ok_or(Error::new_constant_pool("Error getting method name"))?; - let method_signature = Self::get_cpool_string(class_file, method.descriptor_index() as usize) - .ok_or(Error::new_constant_pool("Error getting method method_signature"))?; + let method_signature = + Self::get_cpool_string(class_file, method.descriptor_index() as usize).ok_or( + Error::new_constant_pool("Error getting method method_signature"), + )?; let code = Self::get_cpool_code_attribute(method.attributes()) .ok_or(Error::new_constant_pool("Error getting method code"))?; let key_signature = method_name + ":" + method_signature.as_str(); - method_by_signature.insert(key_signature.clone(), JavaMethod::new(Signature::from_str(method_signature.as_str())?, code.0, code.1, code.2)); - - let cpool_index = Self::get_cpool_method_index(class_file, method.name_index(), method.descriptor_index()); + method_by_signature.insert( + key_signature.clone(), + JavaMethod::new( + Signature::from_str(method_signature.as_str())?, + code.0, + code.1, + code.2, + ), + ); + + let cpool_index = Self::get_cpool_method_index( + class_file, + method.name_index(), + method.descriptor_index(), + ); if let Some(index) = cpool_index { methodsignature_by_cpoolindex.insert(index, key_signature); } } - Ok(Methods::new(methodsignature_by_cpoolindex, method_by_signature)) + Ok(Methods::new( + methodsignature_by_cpoolindex, + method_by_signature, + )) } fn get_cpool_string(class_file: &ClassFile, index: usize) -> Option { let constant_pool = class_file.constant_pool(); - constant_pool.get(index) - .and_then(|item| match item { - Utf8 { value } => Some(value.clone()), - _ => None - }) + constant_pool.get(index).and_then(|item| match item { + Utf8 { value } => Some(value.clone()), + _ => None, + }) } - fn get_cpool_method_index(class_file: &ClassFile, name_index_to_find: u16, signature_index: u16) -> Option { + fn get_cpool_method_index( + class_file: &ClassFile, + name_index_to_find: u16, + signature_index: u16, + ) -> Option { let constant_pool = class_file.constant_pool(); - let found_name_and_type_index = constant_pool.iter() - .enumerate() - .find_map(|index| if let NameAndType { name_index, descriptor_index } = *index.1 { + let found_name_and_type_index = constant_pool.iter().enumerate().find_map(|index| { + if let NameAndType { + name_index, + descriptor_index, + } = *index.1 + { if name_index == name_index_to_find && descriptor_index == signature_index { Some(index.0) - } else { None } - } else { None })? as u16; + } else { + None + } + } else { + None + } + })? as u16; let this_class_index = class_file.this_class(); - constant_pool.iter() - .enumerate() - .find_map(|index| if let Methodref { class_index, name_and_type_index } = *index.1 { - if class_index == this_class_index && name_and_type_index == found_name_and_type_index { + constant_pool.iter().enumerate().find_map(|index| { + if let Methodref { + class_index, + name_and_type_index, + } = *index.1 + { + if class_index == this_class_index + && name_and_type_index == found_name_and_type_index + { Some(index.0 as u16) - } else { None } - } else { None }) - } - - fn get_cpool_code_attribute(attributes: &Vec) -> Option<(u16, u16, Vec)> { - attributes.iter() - .find_map(|item| { - if let Code { max_stack, max_locals, code, .. } = item { - Some((*max_stack, *max_locals, code.clone())) } else { None } - }) + } else { + None + } + }) + } + + fn get_cpool_code_attribute(attributes: &Vec) -> Option<(u16, u16, Vec)> { + attributes.iter().find_map(|item| { + if let Code { + max_stack, + max_locals, + code, + .. + } = item + { + Some((*max_stack, *max_locals, code.clone())) + } else { + None + } + }) } pub fn method_area(&self) -> &MethodArea { diff --git a/vm/src/error.rs b/vm/src/error.rs index 0b36fda7..c0d183c0 100644 --- a/vm/src/error.rs +++ b/vm/src/error.rs @@ -1,6 +1,6 @@ -use std::{io, result}; -use std::fmt::{Debug, Display, Formatter}; use crate::error::ErrorKind::{ClassFile, ConstantPool, Execution, Io}; +use std::fmt::{Debug, Display, Formatter}; +use std::{io, result}; pub type Result = result::Result; diff --git a/vm/src/execution_engine/engine.rs b/vm/src/execution_engine/engine.rs index 543dec9a..1a0d41e6 100644 --- a/vm/src/execution_engine/engine.rs +++ b/vm/src/execution_engine/engine.rs @@ -12,7 +12,8 @@ impl<'a> Engine<'a> { let mut last_value: Option = None; while !stack_frames.is_empty() { - let stack_frame = stack_frames.last_mut() + let stack_frame = stack_frames + .last_mut() .ok_or(Error::new_execution("Error getting stack frame"))?; match stack_frame.get_bytecode_byte() { @@ -76,7 +77,6 @@ impl<'a> Engine<'a> { stack_frame.incr_pc(); let pos = stack_frame.get_bytecode_byte() as usize; - let val = stack_frame.get_local(pos); stack_frame.push(val); @@ -167,7 +167,6 @@ impl<'a> Engine<'a> { println!("ISUB -> {a} - {b} = {result}"); } 104 => { - let b = stack_frame.pop(); let a = stack_frame.pop(); let result = a * b; @@ -259,8 +258,6 @@ impl<'a> Engine<'a> { } else { stack_frame.advance_pc(3); } - - } 162 => { println!("IF_ICMPGE"); @@ -304,23 +301,36 @@ impl<'a> Engine<'a> { stack_frame.advance_pc(offset); } 172 => { - println!("IRETURN -> locals={:?}, operand_stack={:?}", stack_frame.locals, stack_frame.operand_stack); + println!( + "IRETURN -> locals={:?}, operand_stack={:?}", + stack_frame.locals, stack_frame.operand_stack + ); let ret = stack_frame.pop(); stack_frames.pop(); - stack_frames.last_mut() + stack_frames + .last_mut() .ok_or(Error::new_execution("Error getting stack last value"))? .push(ret); } 177 => { - println!("RETURN -> locals={:?}, operand_stack={:?}", stack_frame.locals, stack_frame.operand_stack); - last_value = stack_frames.last() + println!( + "RETURN -> locals={:?}, operand_stack={:?}", + stack_frame.locals, stack_frame.operand_stack + ); + last_value = stack_frames + .last() .ok_or(Error::new_execution("Error getting stack last value"))? - .locals.last().copied(); + .locals + .last() + .copied(); stack_frames.pop(); // Return from method, pop the current frame - // add more logic here + // add more logic here } 184 => { - println!("INVOKESTATIC -> locals={:?}, operand_stack={:?}", stack_frame.locals, stack_frame.operand_stack); + println!( + "INVOKESTATIC -> locals={:?}, operand_stack={:?}", + stack_frame.locals, stack_frame.operand_stack + ); stack_frame.incr_pc(); let high = stack_frame.get_bytecode_byte() as u16; @@ -328,7 +338,9 @@ impl<'a> Engine<'a> { stack_frame.incr_pc(); let low = stack_frame.get_bytecode_byte() as u16; let methodref_constpool_index = (high << 8) | low; - let static_method = self.method_area.get_method_by_cpool_index(methodref_constpool_index)?; + let static_method = self + .method_area + .get_method_by_cpool_index(methodref_constpool_index)?; let mut next_frame = static_method.new_stack_frame(); let arg_num = static_method.get_signature().get_arg_num(); diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 11c2f33c..97390720 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -1,8 +1,7 @@ - -pub mod vm; mod error; mod stack; +pub mod vm; mod class_loader; -mod method_area; mod execution_engine; +mod method_area; diff --git a/vm/src/method_area/java_class.rs b/vm/src/method_area/java_class.rs index d3f22063..7b8e85e4 100644 --- a/vm/src/method_area/java_class.rs +++ b/vm/src/method_area/java_class.rs @@ -1,6 +1,5 @@ -use std::collections::HashMap; use crate::method_area::java_method::JavaMethod; - +use std::collections::HashMap; #[derive(Debug)] pub(crate) struct JavaClass { @@ -13,7 +12,6 @@ pub(crate) struct Methods { pub(crate) method_by_signature: HashMap, } - impl JavaClass { pub fn new(methods: Methods) -> Self { Self { methods } @@ -21,7 +19,13 @@ impl JavaClass { } impl Methods { - pub fn new(methodsignature_by_cpoolindex: HashMap, method_by_signature: HashMap) -> Self { - Self { methodsignature_by_cpoolindex, method_by_signature } + pub fn new( + methodsignature_by_cpoolindex: HashMap, + method_by_signature: HashMap, + ) -> Self { + Self { + methodsignature_by_cpoolindex, + method_by_signature, + } } } diff --git a/vm/src/method_area/java_method.rs b/vm/src/method_area/java_method.rs index 941d7042..f65da797 100644 --- a/vm/src/method_area/java_method.rs +++ b/vm/src/method_area/java_method.rs @@ -1,8 +1,6 @@ - use crate::method_area::signature::Signature; use crate::stack::stack_frame::StackFrame; - #[derive(Debug)] pub(crate) struct JavaMethod { signature: Signature, @@ -13,7 +11,12 @@ pub(crate) struct JavaMethod { impl JavaMethod { pub fn new(signature: Signature, max_stack: u16, max_locals: u16, bytecode: Vec) -> Self { - Self { signature, max_stack, max_locals, bytecode } + Self { + signature, + max_stack, + max_locals, + bytecode, + } } pub fn new_stack_frame(&self) -> StackFrame { diff --git a/vm/src/method_area/method_area.rs b/vm/src/method_area/method_area.rs index 97e5c1ff..3caa00d9 100644 --- a/vm/src/method_area/method_area.rs +++ b/vm/src/method_area/method_area.rs @@ -12,19 +12,41 @@ impl MethodArea { Self { loaded_class } } - pub(crate) fn get_method_by_name_signature(&self, method_name_signature: &str) -> crate::error::Result<&JavaMethod> { //todo add class name - if let Some(found) = self.loaded_class.methods.method_by_signature.get(method_name_signature) { + pub(crate) fn get_method_by_name_signature( + &self, + method_name_signature: &str, + ) -> crate::error::Result<&JavaMethod> { + //todo add class name + if let Some(found) = self + .loaded_class + .methods + .method_by_signature + .get(method_name_signature) + { return Ok(found); } - Err(Error::new_constant_pool("Error getting method by name from methods map")) + Err(Error::new_constant_pool( + "Error getting method by name from methods map", + )) } - pub(crate) fn get_method_by_cpool_index(&self, cpool_index: u16) -> crate::error::Result<&JavaMethod> { //todo add class name - if let Some(found_signature) = self.loaded_class.methods.methodsignature_by_cpoolindex.get(&cpool_index) { - return self.get_method_by_name_signature(found_signature) + pub(crate) fn get_method_by_cpool_index( + &self, + cpool_index: u16, + ) -> crate::error::Result<&JavaMethod> { + //todo add class name + if let Some(found_signature) = self + .loaded_class + .methods + .methodsignature_by_cpoolindex + .get(&cpool_index) + { + return self.get_method_by_name_signature(found_signature); } - Err(Error::new_constant_pool("Error getting method by name from methods map")) + Err(Error::new_constant_pool( + "Error getting method by name from methods map", + )) } } diff --git a/vm/src/method_area/mod.rs b/vm/src/method_area/mod.rs index 88a1f858..c3d82f7f 100644 --- a/vm/src/method_area/mod.rs +++ b/vm/src/method_area/mod.rs @@ -1,5 +1,4 @@ - -pub(crate) mod java_method; -pub(crate) mod signature; pub(crate) mod java_class; +pub(crate) mod java_method; pub(crate) mod method_area; +pub(crate) mod signature; diff --git a/vm/src/method_area/signature.rs b/vm/src/method_area/signature.rs index 7d2405a1..d0d8a68a 100644 --- a/vm/src/method_area/signature.rs +++ b/vm/src/method_area/signature.rs @@ -1,6 +1,5 @@ use crate::error::Error; - #[derive(Debug)] pub(crate) struct Signature { #[allow(dead_code)] @@ -29,7 +28,13 @@ pub(crate) enum SignatureType { impl Signature { pub fn from_str(signature: &str) -> crate::error::Result { Self::count_symbols_between_parentheses(signature) - .and_then(|arg_num| Some(Self { parameter_types: vec![], return_type: SignatureType::Void, arg_num })) + .and_then(|arg_num| { + Some(Self { + parameter_types: vec![], + return_type: SignatureType::Void, + arg_num, + }) + }) .ok_or(Error::new_constant_pool("Error parsing signature")) } @@ -37,7 +42,8 @@ impl Signature { self.arg_num } - fn count_symbols_between_parentheses(s: &str) -> Option { //todo: remove this workaround + fn count_symbols_between_parentheses(s: &str) -> Option { + //todo: remove this workaround let open_index = s.find('(')?; let close_index = s.find(')')?; diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 51c4862a..a706738a 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -1,7 +1,6 @@ use crate::class_loader::ClassLoader; use crate::execution_engine::engine::Engine; - #[derive(Debug)] pub struct VM { class_loader: ClassLoader, @@ -14,7 +13,9 @@ impl VM { } pub fn run(&self) -> crate::error::Result> { - let main_method = self.class_loader.method_area() + let main_method = self + .class_loader + .method_area() .get_method_by_name_signature("main:([Ljava/lang/String;)V")?; let engine = Engine::new(&self.class_loader.method_area());