diff --git a/src/lib.rs b/src/lib.rs index 8393fea..6ed50c8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ pub fn get_class(bytecode: Vec) -> Option { index += 2; let mut attributes = vec![]; for _ in 0..attributes_count { - attributes.push(read_attribute(&bytecode, &mut index)); + attributes.push(read_attribute(constant_pool.clone(), &bytecode, &mut index)); } Some(Class { @@ -126,8 +126,8 @@ fn read_constant_pool_entry(index: &mut usize, bytecode: &[u8]) -> CpEntry { CpEntry::InterfaceMethodref(class_index, name_and_type_index) } 12 => { - let name_index = get_u16(bytecode, *index + 1); - let descriptor_index = get_u16(bytecode, *index + 3); + let name_index = get_u16(bytecode, *index + 1) as usize; + let descriptor_index = get_u16(bytecode, *index + 3) as usize; *index += 5; CpEntry::NameAndType(name_index, descriptor_index) } @@ -179,8 +179,8 @@ fn read_method(constant_pool: Rc>, index: &mut usize, bytecode: &[u ) } -fn read_attribute(bytecode: &[u8], index: &mut usize) -> Attribute { - let attribute_name_index = get_u16(bytecode, *index); +fn read_attribute(constant_pool: Rc>, bytecode: &[u8], index: &mut usize) -> Attribute { + let attribute_name_index = get_u16(bytecode, *index) as usize; *index += 2; let attribute_length = read_u32(bytecode, *index) as usize; *index += 4; @@ -229,7 +229,7 @@ pub enum CpEntry { Fieldref(u16, u16), MethodRef(u16, u16), InterfaceMethodref(u16, u16), - NameAndType(u16, u16), + NameAndType(usize, usize), } diff --git a/src/types.rs b/src/types.rs index 8627b42..7c8b358 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,5 +1,6 @@ use std::rc::Rc; use crate::CpEntry; +use crate::CpEntry::NameAndType; #[derive(Debug)] //TODO create factory function @@ -28,7 +29,7 @@ pub struct Method { access_flags: u16, name_index: usize, descriptor_index: usize, - _attributes: Vec, + attributes: Vec, } impl Method { @@ -37,7 +38,7 @@ impl Method { name_index: usize, descriptor_index: usize, attributes: Vec, ) -> Self { - Method { constant_pool, access_flags, name_index, descriptor_index, _attributes:attributes } + Method { constant_pool, access_flags, name_index, descriptor_index, attributes } } pub fn name(&self) -> String { @@ -52,6 +53,17 @@ impl Method { full_name } + + pub fn get_code(&self) { + for att in &self.attributes { + if let CpEntry::Utf8(str) = &self.constant_pool[&att.attribute_name_index - 1] { + println!("{}", str); + if str == "Code" { + println!("{:?}", att.info); + } + } + } + } } #[derive(Debug)] @@ -69,7 +81,7 @@ impl Field { name_index: usize, descriptor_index: usize, attributes: Vec, ) -> Self { - Field { constant_pool, access_flags, name_index, descriptor_index, _attributes:attributes } + Field { constant_pool, access_flags, name_index, descriptor_index, _attributes: attributes } } pub fn name(&self) -> String { @@ -89,7 +101,7 @@ impl Field { #[derive(Debug)] pub struct Attribute { - pub attribute_name_index: u16, + pub attribute_name_index: usize, pub info: Vec, } @@ -114,4 +126,55 @@ pub fn get_modifier(value: u16) -> String { if value & m.0 == m.0 { output.push_str(m.1) } } output -} \ No newline at end of file +} + +use std::cell::OnceCell; +use std::collections::HashMap; +use crate::types::AttributeType::{BootstrapMethods, Code, ConstantValue, NestHost, NestMembers, PermittedSubclasses, StackMapTable}; + +enum AttributeType { + ConstantValue, + Code, + StackMapTable, + BootstrapMethods, + NestHost, + NestMembers, + PermittedSubclasses, + Exceptions, + InnerClasses, + EnclosingMethod, + Synthetic, + Signature, + Record, + SourceFile, + LineNumberTable, + LocalVariableTable, + LocalVariableTypeTable, + SourceDebugExtension, + Deprecated, + RuntimeVisibleAnnotations, + RuntimeInvisibleAnnotations, + RuntimeVisibleParameterAnnotations, + RuntimeInvisibleParameterAnnotations, + RuntimeVisibleTypeAnnotations, + RuntimeInvisibleTypeAnnotations, + AnnotationDefault, + MethodParameters, + Module, + ModulePackages, + ModuleMainClass, +} + +const cell: OnceCell> = OnceCell::new(); + +const value: &HashMap<&str, AttributeType> = cell.get_or_init(|| { + let mut map = HashMap::with_capacity(18); + map.insert("ConstantValue", ConstantValue); + map.insert("Code", Code); + map.insert("StackMapTable", StackMapTable); + map.insert("BootstrapMethods", BootstrapMethods); + map.insert("NestHost", NestHost); + map.insert("NestMembers", NestMembers); + map.insert("PermittedSubclasses", PermittedSubclasses); + map +}); \ No newline at end of file diff --git a/tests/class_tests.rs b/tests/class_tests.rs index d93cede..87ada89 100644 --- a/tests/class_tests.rs +++ b/tests/class_tests.rs @@ -14,7 +14,6 @@ mod test { assert_eq!("public (Ljava/lang/String;)V", &class.methods[0].name()); assert_eq!("public getName()Ljava/lang/String;", &class.methods[1].name()); assert_eq!("public print()V", &class.methods[2].name()); - } #[test] @@ -23,6 +22,13 @@ mod test { assert_eq!("private final Ljava/lang/String; name", &class.fields[0].name()) } + #[test] + fn get_code() { + let class = get_class(); + println!("{:?}", &class.methods[0].get_code()); + println!("{:?}", &class.methods[1].get_code()); + } + fn get_class() -> Class { let cp = Rc::new(vec![ MethodRef(6, 19), @@ -69,14 +75,14 @@ mod test { methods: vec![ Method::new( cp.clone(), 1, 9, 10, vec![Attribute { - attribute_name_index: 18, + attribute_name_index: 11, info: vec![0, 2, 0, 2, 0, 0, 0, 10, 42, 183, 0, 1, 42, 43, 181, 0, 2, 177, 0, 0, 0, 1, 0, 12, 0, 0, 0, 14, 0, 3, 0, 0, 0, 7, 0, 4, 0, 8, 0, 9, 0, 9], }], ), Method::new( cp.clone(), 1, 13, 14, vec![Attribute { - attribute_name_index: 18, + attribute_name_index: 11, info: vec![0, 1, 0, 1, 0, 0, 0, 5, 42, 180, 0, 2, 176, 0, 0, 0, 1, 0, 12, 0, 0, 0, 6, 0, 1, 0, 0, 0, 12], }],