added get_names for methods
This commit is contained in:
parent
739ea7da3e
commit
724b2f3eaa
3 changed files with 132 additions and 12 deletions
24
src/lib.rs
24
src/lib.rs
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
use crate::types::{CpEntry, Class, Field, Attribute, Method};
|
use crate::types::{CpEntry, Class, Field, Attribute, Method};
|
||||||
|
|
||||||
pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
|
pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
|
||||||
|
|
@ -12,6 +13,8 @@ pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
|
||||||
constant_pool.push(read_constant_pool_entry(&mut index, &bytecode));
|
constant_pool.push(read_constant_pool_entry(&mut index, &bytecode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let constant_pool = Rc::new(constant_pool);
|
||||||
|
|
||||||
let access_flags = get_u16(&bytecode, index);
|
let access_flags = get_u16(&bytecode, index);
|
||||||
let this_class = get_u16(&bytecode, index + 2);
|
let this_class = get_u16(&bytecode, index + 2);
|
||||||
let super_class = get_u16(&bytecode, index + 4);
|
let super_class = get_u16(&bytecode, index + 4);
|
||||||
|
|
@ -35,7 +38,7 @@ pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
|
||||||
index += 2;
|
index += 2;
|
||||||
let mut methods = vec![];
|
let mut methods = vec![];
|
||||||
for _ in 0..methods_count {
|
for _ in 0..methods_count {
|
||||||
methods.push(read_method(&mut index, &bytecode));
|
methods.push(read_method(constant_pool.clone(), &mut index, &bytecode));
|
||||||
}
|
}
|
||||||
|
|
||||||
let attributes_count = get_u16(&bytecode, index);
|
let attributes_count = get_u16(&bytecode, index);
|
||||||
|
|
@ -61,7 +64,7 @@ pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
|
||||||
|
|
||||||
fn check_magic(bytecode: &Vec<u8>) {
|
fn check_magic(bytecode: &Vec<u8>) {
|
||||||
if &bytecode[0..4] != [0xCA, 0xFE, 0xBA, 0xBE] {
|
if &bytecode[0..4] != [0xCA, 0xFE, 0xBA, 0xBE] {
|
||||||
panic!(); //must never happen
|
panic!("Invalid class file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,12 +100,12 @@ fn read_constant_pool_entry(index: &mut usize, bytecode: &Vec<u8>) -> CpEntry {
|
||||||
7 => {
|
7 => {
|
||||||
let name_index = get_u16(bytecode, *index + 1);
|
let name_index = get_u16(bytecode, *index + 1);
|
||||||
*index += 3;
|
*index += 3;
|
||||||
CpEntry::Class(name_index)
|
CpEntry::ClassRef(name_index)
|
||||||
}
|
}
|
||||||
8 => {
|
8 => {
|
||||||
let string_index = get_u16(bytecode, *index + 1);
|
let string_index = get_u16(bytecode, *index + 1);
|
||||||
*index += 3;
|
*index += 3;
|
||||||
CpEntry::String(string_index)
|
CpEntry::StringRef(string_index)
|
||||||
}
|
}
|
||||||
9 => {
|
9 => {
|
||||||
let class_index = get_u16(bytecode, *index + 1);
|
let class_index = get_u16(bytecode, *index + 1);
|
||||||
|
|
@ -127,7 +130,13 @@ fn read_constant_pool_entry(index: &mut usize, bytecode: &Vec<u8>) -> CpEntry {
|
||||||
let descriptor_index = get_u16(bytecode, *index + 3);
|
let descriptor_index = get_u16(bytecode, *index + 3);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::NameAndType(name_index, descriptor_index)
|
CpEntry::NameAndType(name_index, descriptor_index)
|
||||||
}
|
},
|
||||||
|
// 15 MethodHandle,
|
||||||
|
// 16 MethodType,
|
||||||
|
// 17 Dynamic,
|
||||||
|
// 18 InvokeDynamic,
|
||||||
|
// 19 Module,
|
||||||
|
// 20 Package,
|
||||||
_ => panic!()
|
_ => panic!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,9 +160,9 @@ fn read_field(index: &mut usize, bytecode: &Vec<u8>) -> Field {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_method(index: &mut usize, bytecode: &Vec<u8>) -> Method {
|
fn read_method(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &Vec<u8>) -> Method {
|
||||||
let access_flags = get_u16(bytecode, *index);
|
let access_flags = get_u16(bytecode, *index);
|
||||||
let name_index = get_u16(bytecode, *index + 2);
|
let name_index = get_u16(bytecode, *index + 2) as usize;
|
||||||
let descriptor_index = get_u16(bytecode, *index + 4);
|
let descriptor_index = get_u16(bytecode, *index + 4);
|
||||||
let attributes_count = get_u16(bytecode, *index + 6);
|
let attributes_count = get_u16(bytecode, *index + 6);
|
||||||
*index += 8;
|
*index += 8;
|
||||||
|
|
@ -162,6 +171,7 @@ fn read_method(index: &mut usize, bytecode: &Vec<u8>) -> Method {
|
||||||
attributes.push(read_attribute(bytecode, index));
|
attributes.push(read_attribute(bytecode, index));
|
||||||
}
|
}
|
||||||
Method {
|
Method {
|
||||||
|
constant_pool,
|
||||||
access_flags,
|
access_flags,
|
||||||
name_index,
|
name_index,
|
||||||
descriptor_index,
|
descriptor_index,
|
||||||
|
|
|
||||||
33
src/types.rs
33
src/types.rs
|
|
@ -1,9 +1,12 @@
|
||||||
|
use std::rc::Rc;
|
||||||
|
use crate::types::CpEntry::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
//TODO create factory function
|
//TODO create factory function
|
||||||
pub struct Class {
|
pub struct Class {
|
||||||
pub minor_version: u16,
|
pub minor_version: u16,
|
||||||
pub major_version: u16,
|
pub major_version: u16,
|
||||||
pub constant_pool: Vec<CpEntry>,
|
pub constant_pool: Rc<Vec<CpEntry>>,
|
||||||
pub access_flags: u16,
|
pub access_flags: u16,
|
||||||
pub this_class: u16,
|
pub this_class: u16,
|
||||||
pub super_class: u16,
|
pub super_class: u16,
|
||||||
|
|
@ -13,6 +16,16 @@ pub struct Class {
|
||||||
pub attributes: Vec<Attribute>,
|
pub attributes: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Class {
|
||||||
|
pub fn get_version(&self) -> (u16, u16) {
|
||||||
|
(self.major_version, self.minor_version)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_methods(&self) -> &Vec<Method> {
|
||||||
|
&self.methods
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CpEntry {
|
pub enum CpEntry {
|
||||||
|
|
@ -21,8 +34,8 @@ pub enum CpEntry {
|
||||||
Float(f32),
|
Float(f32),
|
||||||
Long(i64),
|
Long(i64),
|
||||||
Double(f64),
|
Double(f64),
|
||||||
Class(u16),
|
ClassRef(u16),
|
||||||
String(u16),
|
StringRef(u16),
|
||||||
Fieldref(u16, u16),
|
Fieldref(u16, u16),
|
||||||
MethodRef(u16, u16),
|
MethodRef(u16, u16),
|
||||||
InterfaceMethodref(u16, u16),
|
InterfaceMethodref(u16, u16),
|
||||||
|
|
@ -45,10 +58,20 @@ pub struct Attribute {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Method{
|
pub struct Method {
|
||||||
|
pub constant_pool: Rc<Vec<CpEntry>>,
|
||||||
pub access_flags: u16,
|
pub access_flags: u16,
|
||||||
pub name_index: u16,
|
pub name_index: usize,
|
||||||
pub descriptor_index: u16,
|
pub descriptor_index: u16,
|
||||||
pub attributes_count: u16,
|
pub attributes_count: u16,
|
||||||
pub attributes: Vec<Attribute>,
|
pub attributes: Vec<Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Method {
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
if let Utf8(s) = &self.constant_pool[self.name_index - 1] {
|
||||||
|
return &s;
|
||||||
|
}
|
||||||
|
panic!() // name must be utf8
|
||||||
|
}
|
||||||
|
}
|
||||||
87
tests/class_tests.rs
Normal file
87
tests/class_tests.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
use std::rc::Rc;
|
||||||
|
use classfile_reader::types::{Attribute, Class, Field, Method};
|
||||||
|
use classfile_reader::types::CpEntry::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_version() {
|
||||||
|
assert_eq!((55, 0), get_class().get_version());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_methods() {
|
||||||
|
for m in get_class().get_methods() {
|
||||||
|
println!("{}", m.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_class() -> Class {
|
||||||
|
let cp = Rc::new(vec![MethodRef(2, 3),
|
||||||
|
ClassRef(4),
|
||||||
|
NameAndType(5, 6),
|
||||||
|
Utf8("java/lang/Object".to_owned()),
|
||||||
|
Utf8("<init>".to_owned()),
|
||||||
|
Utf8("()V".to_owned()),
|
||||||
|
Fieldref(8, 9),
|
||||||
|
ClassRef(10),
|
||||||
|
NameAndType(11, 12),
|
||||||
|
Utf8("com/github/shautvast/reflective/MetaField".to_owned()),
|
||||||
|
Utf8("name".to_owned()),
|
||||||
|
Utf8("Ljava/lang/String;".to_owned()),
|
||||||
|
Fieldref(8, 14),
|
||||||
|
NameAndType(15, 16),
|
||||||
|
Utf8("modifiers".to_owned()),
|
||||||
|
Utf8("I".to_owned()),
|
||||||
|
Utf8("(Ljava/lang/String;I)V".to_owned()),
|
||||||
|
Utf8("Code".to_owned()),
|
||||||
|
Utf8("LineNumberTable".to_owned()),
|
||||||
|
Utf8("LocalVariableTable".to_owned()),
|
||||||
|
Utf8("this".to_owned()),
|
||||||
|
Utf8("Lcom/github/shautvast/reflective/MetaField;".to_owned()),
|
||||||
|
Utf8("getName".to_owned()),
|
||||||
|
Utf8("()Ljava/lang/String;".to_owned()),
|
||||||
|
Utf8("getModifiers".to_owned()),
|
||||||
|
Utf8("()I".to_owned()),
|
||||||
|
Utf8("SourceFile".to_owned()),
|
||||||
|
Utf8("MetaField.java".to_owned())]);
|
||||||
|
|
||||||
|
Class {
|
||||||
|
minor_version: 0,
|
||||||
|
major_version: 55,
|
||||||
|
constant_pool: cp.clone(),
|
||||||
|
interfaces: vec![],
|
||||||
|
super_class: 2,
|
||||||
|
access_flags: 33,
|
||||||
|
this_class: 8,
|
||||||
|
methods: vec![
|
||||||
|
Method {
|
||||||
|
constant_pool: cp.clone(),
|
||||||
|
access_flags: 1,
|
||||||
|
name_index: 5,
|
||||||
|
descriptor_index: 17,
|
||||||
|
attributes_count: 1,
|
||||||
|
attributes: vec![Attribute {
|
||||||
|
attribute_name_index: 18,
|
||||||
|
info: vec![0, 2, 0, 3, 0, 0, 0, 15, 42, 183, 0, 1, 42, 43, 181, 0, 7, 42, 28,
|
||||||
|
181, 0, 13, 177, 0, 0, 0, 2, 0, 19, 0, 0, 0,
|
||||||
|
18, 0, 4, 0, 0, 0, 8, 0, 4, 0, 9, 0, 9, 0, 10, 0, 14, 0, 11, 0, 20, 0, 0,
|
||||||
|
0, 32, 0, 3, 0, 0, 0, 15, 0, 21, 0, 22, 0, 0, 0, 0, 0, 15, 0, 11,
|
||||||
|
0, 12, 0, 1, 0, 0, 0, 15, 0, 15, 0, 16, 0, 2],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
Method {
|
||||||
|
constant_pool: cp,
|
||||||
|
access_flags: 1,
|
||||||
|
name_index: 23,
|
||||||
|
descriptor_index: 24,
|
||||||
|
attributes_count: 1,
|
||||||
|
attributes: vec![Attribute {
|
||||||
|
attribute_name_index: 18,
|
||||||
|
info: vec![0, 1, 0, 1, 0, 0, 0, 5, 42, 180, 0, 7, 176, 0, 0, 0, 2, 0, 19, 0, 0, 0, 6, 0,
|
||||||
|
1, 0, 0, 0, 14, 0, 20, 0, 0, 0, 12, 0, 1, 0, 0, 0, 5, 0, 21, 0, 22, 0, 0],
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
fields: vec![Field { access_flags: 18, name_index: 11, descriptor_index: 12, attributes_count: 0, attributes: vec![] },
|
||||||
|
Field { access_flags: 18, name_index: 15, descriptor_index: 16, attributes_count: 0, attributes: vec![] }],
|
||||||
|
attributes: vec![Attribute { attribute_name_index: 27, info: vec![0, 28] }],
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue