diff --git a/Dummy.class b/Dummy.class index 2c18fc4..8294f5e 100644 Binary files a/Dummy.class and b/Dummy.class differ diff --git a/Dummy.java b/Dummy.java index 6b17104..cbd4532 100644 --- a/Dummy.java +++ b/Dummy.java @@ -1,6 +1,8 @@ public class Dummy { - public static int get(){ - return 42; + private final static double answer = 42.0; + + public static double get(){ + return answer; } } diff --git a/src/lib.rs b/src/lib.rs index e3eeec6..057222b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,10 +11,14 @@ pub fn get_class(bytecode: Vec) -> Option { check_magic(&bytecode); let constant_pool_count = read_u16(&bytecode, 8); + // println!("cp count: {}", constant_pool_count); let mut index = 10; - let mut constant_pool: Vec = vec![]; - for cp_index in 0..constant_pool_count - 1 { - constant_pool.push(read_constant_pool_entry((cp_index + 1) as usize, &mut index, &bytecode)); + let mut constant_pool: HashMap = HashMap::with_capacity(constant_pool_count as usize); + let mut cp_index: usize = 1; + for _ in 1..constant_pool_count - 1 + { + constant_pool.insert(cp_index, read_constant_pool_entry(&mut cp_index, &mut index, &bytecode)); + cp_index += 1; } let constant_pool = Rc::new(constant_pool); @@ -78,68 +82,73 @@ fn check_magic(bytecode: &[u8]) { } } -fn read_constant_pool_entry(cp_index: usize, index: &mut usize, bytecode: &[u8]) -> CpEntry { +fn read_constant_pool_entry(cp_index: &mut usize, index: &mut usize, bytecode: &[u8]) -> CpEntry { let tag = bytecode[*index]; + // println!("#{}: {}", cp_index, tag); match tag { 1 => { let len = read_u16(bytecode, *index + 1) as usize; let utf: Vec = Vec::from(&bytecode[*index + 3..*index + 3 + len]); *index += len + 3; - CpEntry::Utf8(cp_index, String::from_utf8(utf).unwrap()) + CpEntry::Utf8(*cp_index, String::from_utf8(utf).unwrap()) } 3 => { let value = read_i32(bytecode, *index + 1); *index += 5; - CpEntry::Integer(cp_index, value) + CpEntry::Integer(*cp_index, value) } 4 => { let value = read_f32(bytecode, *index + 1); *index += 5; - CpEntry::Float(cp_index, value) + CpEntry::Float(*cp_index, value) } 5 => { let value = read_i64(bytecode, *index + 1); *index += 9; - CpEntry::Long(cp_index, value) + let r = CpEntry::Long(*cp_index, value); + *cp_index += 1; + r } 6 => { let value = read_f64(bytecode, *index + 1); *index += 9; - CpEntry::Double(cp_index, value) + let r = CpEntry::Double(*cp_index, value); + *cp_index += 1; + r } 7 => { let name_index = read_u16(bytecode, *index + 1); *index += 3; - CpEntry::ClassRef(cp_index, name_index) + CpEntry::ClassRef(*cp_index, name_index) } 8 => { let string_index = read_u16(bytecode, *index + 1); *index += 3; - CpEntry::StringRef(cp_index, string_index) + CpEntry::StringRef(*cp_index, string_index) } 9 => { let class_index = read_u16(bytecode, *index + 1); let name_and_type_index = read_u16(bytecode, *index + 3); *index += 5; - CpEntry::Fieldref(cp_index, class_index, name_and_type_index) + CpEntry::Fieldref(*cp_index, class_index, name_and_type_index) } 10 => { let class_index = read_u16(bytecode, *index + 1); let name_and_type_index = read_u16(bytecode, *index + 3); *index += 5; - CpEntry::MethodRef(cp_index, class_index, name_and_type_index) + CpEntry::MethodRef(*cp_index, class_index, name_and_type_index) } 11 => { let class_index = read_u16(bytecode, *index + 1); let name_and_type_index = read_u16(bytecode, *index + 3); *index += 5; - CpEntry::InterfaceMethodref(cp_index, class_index, name_and_type_index) + CpEntry::InterfaceMethodref(*cp_index, class_index, name_and_type_index) } 12 => { let name_index = read_u16(bytecode, *index + 1) as usize; let descriptor_index = read_u16(bytecode, *index + 3) as usize; *index += 5; - CpEntry::NameAndType(cp_index, name_index, descriptor_index) + CpEntry::NameAndType(*cp_index, name_index, descriptor_index) } // 15 MethodHandle, // 16 MethodType, @@ -147,11 +156,12 @@ fn read_constant_pool_entry(cp_index: usize, index: &mut usize, bytecode: &[u8]) // 18 InvokeDynamic, // 19 Module, // 20 Package, - _ => panic!() + + _ => panic!("cp entry type not recognized") } } -fn read_field(constant_pool: Rc>, index: &mut usize, bytecode: &[u8]) -> Field { +fn read_field(constant_pool: Rc>, index: &mut usize, bytecode: &[u8]) -> Field { let access_flags = read_u16(bytecode, *index); let name_index = read_u16(bytecode, *index + 2) as usize; let descriptor_index = read_u16(bytecode, *index + 4) as usize; @@ -162,7 +172,7 @@ fn read_field(constant_pool: Rc>, index: &mut usize, bytecode: &[u8 if let Some(att) = read_attribute(constant_pool.clone(), bytecode, index) { attributes.insert(att.0, att.1); } else { - panic!(); // bug/not-implemented + panic!("attribute not recognized"); // bug/not-implemented } } Field::new( @@ -174,7 +184,7 @@ fn read_field(constant_pool: Rc>, index: &mut usize, bytecode: &[u8 ) } -fn read_method(constant_pool: Rc>, index: &mut usize, bytecode: &[u8]) -> Method { +fn read_method(constant_pool: Rc>, index: &mut usize, bytecode: &[u8]) -> Method { let access_flags = read_u16(bytecode, *index); let name_index = read_u16(bytecode, *index + 2) as usize; let descriptor_index = read_u16(bytecode, *index + 4) as usize; @@ -197,7 +207,7 @@ fn read_method(constant_pool: Rc>, index: &mut usize, bytecode: &[u ) } -fn read_attribute(constant_pool: Rc>, bytecode: &[u8], index: &mut usize) -> Option<(String, AttributeType)> { +fn read_attribute(constant_pool: Rc>, bytecode: &[u8], index: &mut usize) -> Option<(String, AttributeType)> { let attribute_name_index = read_u16(bytecode, *index) as usize; *index += 2; let attribute_length = read_u32(bytecode, *index) as usize; @@ -206,8 +216,8 @@ fn read_attribute(constant_pool: Rc>, bytecode: &[u8], index: &mut *index += attribute_length; - if let CpEntry::Utf8(_, s) = &constant_pool[attribute_name_index - 1] { - // println!("{}", s); + if let CpEntry::Utf8(_, s) = &constant_pool.get(&attribute_name_index).unwrap() { + // println!("Att [{}]", s); return match s.as_str() { "ConstantValue" => { assert_eq!(info.len(), 2); @@ -237,6 +247,7 @@ fn read_attribute(constant_pool: Rc>, bytecode: &[u8], index: &mut Some(("Code".into(), AttributeType::Code(MethodCode::new(max_stack, max_locals, code, exception_table, code_attributes)))) } "SourceFile" => Some(("SourceFile".into(), AttributeType::SourceFile)), + "LineNumberTable" => Some(("SourceFile".into(), AttributeType::LineNumberTable)), _ => None }; } diff --git a/src/main.rs b/src/main.rs index 37a303f..cef4a18 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ use std::io::Read; fn main() { let bytecode = read_class_file("./Dummy.class"); if let Some(class) = classfile_reader::get_class(bytecode){ + println!("{:?}", class); let ret = class.execute("public static get()I"); println!("{:?}", ret); } diff --git a/src/types.rs b/src/types.rs index ab7daff..525a27a 100644 --- a/src/types.rs +++ b/src/types.rs @@ -7,7 +7,7 @@ use crate::{CpEntry, opcodes}; pub struct Class { pub minor_version: u16, pub major_version: u16, - pub constant_pool: Rc>, + pub constant_pool: Rc>, pub access_flags: u16, pub this_class: u16, pub super_class: u16, @@ -29,7 +29,7 @@ impl Class { } pub struct Method { - constant_pool: Rc>, + constant_pool: Rc>, access_flags: u16, name_index: usize, descriptor_index: usize, @@ -44,7 +44,7 @@ impl fmt::Debug for Method { } impl Method { - pub fn new(constant_pool: Rc>, + pub fn new(constant_pool: Rc>, access_flags: u16, name_index: usize, descriptor_index: usize, @@ -54,10 +54,10 @@ impl Method { pub fn name(&self) -> String { let mut full_name = get_modifier(self.access_flags); - if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.name_index - 1] { + if let CpEntry::Utf8(_, s) = &self.constant_pool.get(&self.name_index).unwrap() { full_name.push_str(s); } - if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.descriptor_index - 1] { + if let CpEntry::Utf8(_, s) = &self.constant_pool.get(&self.descriptor_index).unwrap() { full_name.push_str(s); } @@ -76,10 +76,10 @@ impl Method { pc += 1; let c = code.opcodes[pc] as i32; stack.push(Value::I32(c)); - }, + } &opcodes::ireturn => { return stack.pop(); - }, + } //TODO implement all opcodes _ => {} } @@ -91,7 +91,7 @@ impl Method { } pub struct Field { - constant_pool: Rc>, + constant_pool: Rc>, access_flags: u16, name_index: usize, descriptor_index: usize, @@ -110,7 +110,7 @@ impl fmt::Debug for Field { } impl Field { - pub fn new(constant_pool: Rc>, + pub fn new(constant_pool: Rc>, access_flags: u16, name_index: usize, descriptor_index: usize, @@ -121,11 +121,11 @@ impl Field { pub fn name(&self) -> String { let mut full_name = get_modifier(self.access_flags); - if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.descriptor_index - 1] { + if let CpEntry::Utf8(_, s) = &self.constant_pool.get(&self.descriptor_index).unwrap() { full_name.push_str(s); } full_name.push(' '); - if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.name_index - 1] { + if let CpEntry::Utf8(_, s) = &self.constant_pool.get(&self.name_index).unwrap() { full_name.push_str(s); }