added constantvalue and code attribute
This commit is contained in:
parent
84a3c1e80c
commit
b06a20a7b1
7 changed files with 260 additions and 199 deletions
|
|
@ -5,4 +5,4 @@ edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
BIN
Dummy.class
BIN
Dummy.class
Binary file not shown.
|
|
@ -2,6 +2,9 @@ package dummy;
|
||||||
|
|
||||||
public class Dummy {
|
public class Dummy {
|
||||||
|
|
||||||
|
private final static String constant = "meh";
|
||||||
|
private final int integer = 57;
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public Dummy(String name) {
|
public Dummy(String name) {
|
||||||
|
|
|
||||||
23
src/io.rs
Normal file
23
src/io.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
pub(crate) fn read_u16(data: &[u8], pos: usize) -> u16 {
|
||||||
|
u16::from_be_bytes(data[pos..pos + 2].try_into().expect("slice with incorrect length"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_i32(data: &[u8], pos: usize) -> i32 {
|
||||||
|
i32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_u32(data: &[u8], pos: usize) -> u32 {
|
||||||
|
u32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_f32(data: &[u8], pos: usize) -> f32 {
|
||||||
|
f32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_i64(data: &[u8], pos: usize) -> i64 {
|
||||||
|
i64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn read_f64(data: &[u8], pos: usize) -> f64 {
|
||||||
|
f64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length"))
|
||||||
|
}
|
||||||
213
src/lib.rs
213
src/lib.rs
|
|
@ -1,56 +1,63 @@
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
mod io;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use crate::types::{Attribute, Class, Field, Method};
|
use crate::io::{read_f32, read_f64, read_i32, read_i64, read_u16, read_u32};
|
||||||
|
use crate::types::{AttributeType, Class, MethodCode, Exception, Field, Method};
|
||||||
|
|
||||||
pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
|
pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
|
||||||
check_magic(&bytecode);
|
check_magic(&bytecode);
|
||||||
|
|
||||||
let constant_pool_count = get_u16(&bytecode, 8);
|
let constant_pool_count = read_u16(&bytecode, 8);
|
||||||
let mut index = 10;
|
let mut index = 10;
|
||||||
let mut constant_pool: Vec<CpEntry> = vec![];
|
let mut constant_pool: Vec<CpEntry> = vec![];
|
||||||
for _ in 0..constant_pool_count - 1 {
|
for cp_index in 0..constant_pool_count - 1 {
|
||||||
constant_pool.push(read_constant_pool_entry(&mut index, &bytecode));
|
constant_pool.push(read_constant_pool_entry((cp_index + 1) as usize, &mut index, &bytecode));
|
||||||
}
|
}
|
||||||
|
|
||||||
let constant_pool = Rc::new(constant_pool);
|
let constant_pool = Rc::new(constant_pool);
|
||||||
|
|
||||||
let access_flags = get_u16(&bytecode, index);
|
let access_flags = read_u16(&bytecode, index);
|
||||||
let this_class = get_u16(&bytecode, index + 2);
|
let this_class = read_u16(&bytecode, index + 2);
|
||||||
let super_class = get_u16(&bytecode, index + 4);
|
let super_class = read_u16(&bytecode, index + 4);
|
||||||
|
|
||||||
let interfaces_count = get_u16(&bytecode, index + 6);
|
let interfaces_count = read_u16(&bytecode, index + 6);
|
||||||
index += 8;
|
index += 8;
|
||||||
let mut interfaces = vec![];
|
let mut interfaces = vec![];
|
||||||
for _ in 0..interfaces_count {
|
for _ in 0..interfaces_count {
|
||||||
interfaces.push(get_u16(&bytecode, index));
|
interfaces.push(read_u16(&bytecode, index));
|
||||||
index += 2;
|
index += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fields_count = get_u16(&bytecode, index);
|
let fields_count = read_u16(&bytecode, index);
|
||||||
index += 2;
|
index += 2;
|
||||||
let mut fields = vec![];
|
let mut fields = vec![];
|
||||||
for _ in 0..fields_count {
|
for _ in 0..fields_count {
|
||||||
fields.push(read_field(constant_pool.clone(), &mut index, &bytecode));
|
fields.push(read_field(constant_pool.clone(), &mut index, &bytecode));
|
||||||
}
|
}
|
||||||
|
|
||||||
let methods_count = get_u16(&bytecode, index);
|
let methods_count = read_u16(&bytecode, index);
|
||||||
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(constant_pool.clone(), &mut index, &bytecode));
|
methods.push(read_method(constant_pool.clone(), &mut index, &bytecode));
|
||||||
}
|
}
|
||||||
|
|
||||||
let attributes_count = get_u16(&bytecode, index);
|
let attributes_count = read_u16(&bytecode, index);
|
||||||
index += 2;
|
index += 2;
|
||||||
let mut attributes = vec![];
|
let mut attributes = vec![];
|
||||||
for _ in 0..attributes_count {
|
for _ in 0..attributes_count {
|
||||||
attributes.push(read_attribute(constant_pool.clone(), &bytecode, &mut index));
|
let some = read_attribute(constant_pool.clone(), &bytecode, &mut index);
|
||||||
|
if let Some(att) = some {
|
||||||
|
attributes.push(att);
|
||||||
|
} else {
|
||||||
|
panic!(); // bug/not-implemented
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Class {
|
Some(Class {
|
||||||
minor_version: get_u16(&bytecode, 4),
|
minor_version: read_u16(&bytecode, 4),
|
||||||
major_version: get_u16(&bytecode, 6),
|
major_version: read_u16(&bytecode, 6),
|
||||||
constant_pool,
|
constant_pool,
|
||||||
access_flags,
|
access_flags,
|
||||||
this_class,
|
this_class,
|
||||||
|
|
@ -68,68 +75,68 @@ fn check_magic(bytecode: &[u8]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_constant_pool_entry(index: &mut usize, bytecode: &[u8]) -> CpEntry {
|
fn read_constant_pool_entry(cp_index: usize, index: &mut usize, bytecode: &[u8]) -> CpEntry {
|
||||||
let tag = bytecode[*index];
|
let tag = bytecode[*index];
|
||||||
match tag {
|
match tag {
|
||||||
1 => {
|
1 => {
|
||||||
let len = get_u16(bytecode, *index + 1) as usize;
|
let len = read_u16(bytecode, *index + 1) as usize;
|
||||||
let utf: Vec<u8> = Vec::from(&bytecode[*index + 3..*index + 3 + len]);
|
let utf: Vec<u8> = Vec::from(&bytecode[*index + 3..*index + 3 + len]);
|
||||||
*index += len + 3;
|
*index += len + 3;
|
||||||
CpEntry::Utf8(String::from_utf8(utf).unwrap())
|
CpEntry::Utf8(cp_index, String::from_utf8(utf).unwrap())
|
||||||
}
|
}
|
||||||
3 => {
|
3 => {
|
||||||
let value = get_i32(bytecode, *index + 1);
|
let value = read_i32(bytecode, *index + 1);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::Integer(value)
|
CpEntry::Integer(cp_index, value)
|
||||||
}
|
}
|
||||||
4 => {
|
4 => {
|
||||||
let value = get_f32(bytecode, *index + 1);
|
let value = read_f32(bytecode, *index + 1);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::Float(value)
|
CpEntry::Float(cp_index, value)
|
||||||
}
|
}
|
||||||
5 => {
|
5 => {
|
||||||
let value = get_i64(bytecode, *index + 1);
|
let value = read_i64(bytecode, *index + 1);
|
||||||
*index += 9;
|
*index += 9;
|
||||||
CpEntry::Long(value)
|
CpEntry::Long(cp_index, value)
|
||||||
}
|
}
|
||||||
6 => {
|
6 => {
|
||||||
let value = get_f64(bytecode, *index + 1);
|
let value = read_f64(bytecode, *index + 1);
|
||||||
*index += 9;
|
*index += 9;
|
||||||
CpEntry::Double(value)
|
CpEntry::Double(cp_index, value)
|
||||||
}
|
}
|
||||||
7 => {
|
7 => {
|
||||||
let name_index = get_u16(bytecode, *index + 1);
|
let name_index = read_u16(bytecode, *index + 1);
|
||||||
*index += 3;
|
*index += 3;
|
||||||
CpEntry::ClassRef(name_index)
|
CpEntry::ClassRef(cp_index, name_index)
|
||||||
}
|
}
|
||||||
8 => {
|
8 => {
|
||||||
let string_index = get_u16(bytecode, *index + 1);
|
let string_index = read_u16(bytecode, *index + 1);
|
||||||
*index += 3;
|
*index += 3;
|
||||||
CpEntry::StringRef(string_index)
|
CpEntry::StringRef(cp_index, string_index)
|
||||||
}
|
}
|
||||||
9 => {
|
9 => {
|
||||||
let class_index = get_u16(bytecode, *index + 1);
|
let class_index = read_u16(bytecode, *index + 1);
|
||||||
let name_and_type_index = get_u16(bytecode, *index + 3);
|
let name_and_type_index = read_u16(bytecode, *index + 3);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::Fieldref(class_index, name_and_type_index)
|
CpEntry::Fieldref(cp_index, class_index, name_and_type_index)
|
||||||
}
|
}
|
||||||
10 => {
|
10 => {
|
||||||
let class_index = get_u16(bytecode, *index + 1);
|
let class_index = read_u16(bytecode, *index + 1);
|
||||||
let name_and_type_index = get_u16(bytecode, *index + 3);
|
let name_and_type_index = read_u16(bytecode, *index + 3);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::MethodRef(class_index, name_and_type_index)
|
CpEntry::MethodRef(cp_index, class_index, name_and_type_index)
|
||||||
}
|
}
|
||||||
11 => {
|
11 => {
|
||||||
let class_index = get_u16(bytecode, *index + 1);
|
let class_index = read_u16(bytecode, *index + 1);
|
||||||
let name_and_type_index = get_u16(bytecode, *index + 3);
|
let name_and_type_index = read_u16(bytecode, *index + 3);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::InterfaceMethodref(class_index, name_and_type_index)
|
CpEntry::InterfaceMethodref(cp_index, class_index, name_and_type_index)
|
||||||
}
|
}
|
||||||
12 => {
|
12 => {
|
||||||
let name_index = get_u16(bytecode, *index + 1) as usize;
|
let name_index = read_u16(bytecode, *index + 1) as usize;
|
||||||
let descriptor_index = get_u16(bytecode, *index + 3) as usize;
|
let descriptor_index = read_u16(bytecode, *index + 3) as usize;
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::NameAndType(name_index, descriptor_index)
|
CpEntry::NameAndType(cp_index, name_index, descriptor_index)
|
||||||
}
|
}
|
||||||
// 15 MethodHandle,
|
// 15 MethodHandle,
|
||||||
// 16 MethodType,
|
// 16 MethodType,
|
||||||
|
|
@ -142,14 +149,18 @@ fn read_constant_pool_entry(index: &mut usize, bytecode: &[u8]) -> CpEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_field(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Field {
|
fn read_field(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Field {
|
||||||
let access_flags = get_u16(bytecode, *index);
|
let access_flags = read_u16(bytecode, *index);
|
||||||
let name_index = get_u16(bytecode, *index + 2) as usize;
|
let name_index = read_u16(bytecode, *index + 2) as usize;
|
||||||
let descriptor_index = get_u16(bytecode, *index + 4) as usize;
|
let descriptor_index = read_u16(bytecode, *index + 4) as usize;
|
||||||
let attributes_count = get_u16(bytecode, *index + 6);
|
let attributes_count = read_u16(bytecode, *index + 6);
|
||||||
*index += 8;
|
*index += 8;
|
||||||
let mut attributes = vec![];
|
let mut attributes = vec![];
|
||||||
for _ in 0..attributes_count {
|
for _ in 0..attributes_count {
|
||||||
attributes.push(read_attribute(bytecode, index));
|
if let Some(att) = read_attribute(constant_pool.clone(), bytecode, index) {
|
||||||
|
attributes.push(att);
|
||||||
|
} else {
|
||||||
|
panic!(); // bug/not-implemented
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Field::new(
|
Field::new(
|
||||||
constant_pool,
|
constant_pool,
|
||||||
|
|
@ -161,16 +172,20 @@ fn read_field(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_method(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Method {
|
fn read_method(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Method {
|
||||||
let access_flags = get_u16(bytecode, *index);
|
let access_flags = read_u16(bytecode, *index);
|
||||||
let name_index = get_u16(bytecode, *index + 2) as usize;
|
let name_index = read_u16(bytecode, *index + 2) as usize;
|
||||||
let descriptor_index = get_u16(bytecode, *index + 4) as usize;
|
let descriptor_index = read_u16(bytecode, *index + 4) as usize;
|
||||||
let attributes_count = get_u16(bytecode, *index + 6);
|
let attributes_count = read_u16(bytecode, *index + 6);
|
||||||
*index += 8;
|
*index += 8;
|
||||||
|
|
||||||
let mut attributes = vec![];
|
let mut attributes = vec![];
|
||||||
for _ in 0..attributes_count {
|
for _ in 0..attributes_count {
|
||||||
attributes.push(read_attribute(bytecode, index));
|
if let Some(att) = read_attribute(constant_pool.clone(), bytecode, index) {
|
||||||
|
attributes.push(att);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Method::new (
|
|
||||||
|
Method::new(
|
||||||
constant_pool,
|
constant_pool,
|
||||||
access_flags,
|
access_flags,
|
||||||
name_index,
|
name_index,
|
||||||
|
|
@ -179,60 +194,64 @@ fn read_method(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_attribute(constant_pool: Rc<Vec<CpEntry>>, bytecode: &[u8], index: &mut usize) -> Attribute {
|
fn read_attribute(constant_pool: Rc<Vec<CpEntry>>, bytecode: &[u8], index: &mut usize) -> Option<AttributeType> {
|
||||||
let attribute_name_index = get_u16(bytecode, *index) as usize;
|
let attribute_name_index = read_u16(bytecode, *index) as usize;
|
||||||
*index += 2;
|
*index += 2;
|
||||||
let attribute_length = read_u32(bytecode, *index) as usize;
|
let attribute_length = read_u32(bytecode, *index) as usize;
|
||||||
*index += 4;
|
*index += 4;
|
||||||
let info: Vec<u8> = Vec::from(&bytecode[*index..*index + attribute_length]);
|
let info: Vec<u8> = Vec::from(&bytecode[*index..*index + attribute_length]);
|
||||||
*index += attribute_length;
|
*index += attribute_length;
|
||||||
|
|
||||||
Attribute {
|
|
||||||
attribute_name_index,
|
if let CpEntry::Utf8(_, s) = &constant_pool[attribute_name_index - 1] {
|
||||||
info,
|
// println!("{}", s);
|
||||||
|
return match s.as_str() {
|
||||||
|
"ConstantValue" => {
|
||||||
|
assert_eq!(info.len(), 2);
|
||||||
|
Some(AttributeType::ConstantValue(read_u16(&info, 0)))
|
||||||
|
}
|
||||||
|
"Code" => {
|
||||||
|
let max_stack = read_u16(&info, 0);
|
||||||
|
let max_locals = read_u16(&info, 2);
|
||||||
|
let code_length = read_u32(&info, 4) as usize;
|
||||||
|
let code = Vec::from(&info[8..8 + code_length]);
|
||||||
|
let exception_table_length = read_u16(&info, 8 + code_length) as usize;
|
||||||
|
|
||||||
|
let mut code_index = 10 + code_length;
|
||||||
|
let mut exception_table = vec![];
|
||||||
|
for _ in 0..exception_table_length {
|
||||||
|
exception_table.push(Exception::read(&info, code_index));
|
||||||
|
code_index += 8;
|
||||||
|
}
|
||||||
|
let attribute_count = read_u16(&info, code_index);
|
||||||
|
code_index += 2;
|
||||||
|
let mut code_attributes = vec![];
|
||||||
|
for _ in 0..attribute_count {
|
||||||
|
if let Some(att) = read_attribute(constant_pool.clone(), &info, &mut code_index) {
|
||||||
|
code_attributes.push(att);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(AttributeType::Code(MethodCode::new(max_stack, max_locals, code, exception_table, code_attributes)))
|
||||||
|
}
|
||||||
|
"SourceFile" => Some(AttributeType::SourceFile),
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
None
|
||||||
|
|
||||||
fn get_u16(data: &[u8], pos: usize) -> u16 {
|
|
||||||
u16::from_be_bytes(data[pos..pos + 2].try_into().expect("slice with incorrect length"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_i32(data: &[u8], pos: usize) -> i32 {
|
|
||||||
i32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_u32(data: &[u8], pos: usize) -> u32 {
|
|
||||||
u32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_f32(data: &[u8], pos: usize) -> f32 {
|
|
||||||
f32::from_be_bytes(data[pos..pos + 4].try_into().expect("slice with incorrect length"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_i64(data: &[u8], pos: usize) -> i64 {
|
|
||||||
i64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_f64(data: &[u8], pos: usize) -> f64 {
|
|
||||||
f64::from_be_bytes(data[pos..pos + 8].try_into().expect("slice with incorrect length"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum CpEntry {
|
pub enum CpEntry {
|
||||||
Utf8(String),
|
Utf8(usize, String),
|
||||||
Integer(i32),
|
Integer(usize, i32),
|
||||||
Float(f32),
|
Float(usize, f32),
|
||||||
Long(i64),
|
Long(usize, i64),
|
||||||
Double(f64),
|
Double(usize, f64),
|
||||||
ClassRef(u16),
|
ClassRef(usize, u16),
|
||||||
StringRef(u16),
|
StringRef(usize, u16),
|
||||||
Fieldref(u16, u16),
|
Fieldref(usize, u16, u16),
|
||||||
MethodRef(u16, u16),
|
MethodRef(usize, u16, u16),
|
||||||
InterfaceMethodref(u16, u16),
|
InterfaceMethodref(usize, u16, u16),
|
||||||
NameAndType(usize, usize),
|
NameAndType(usize, usize, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
128
src/types.rs
128
src/types.rs
|
|
@ -1,6 +1,5 @@
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use crate::CpEntry;
|
use crate::CpEntry;
|
||||||
use crate::CpEntry::NameAndType;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
//TODO create factory function
|
//TODO create factory function
|
||||||
|
|
@ -14,7 +13,7 @@ pub struct Class {
|
||||||
pub interfaces: Vec<u16>,
|
pub interfaces: Vec<u16>,
|
||||||
pub fields: Vec<Field>,
|
pub fields: Vec<Field>,
|
||||||
pub methods: Vec<Method>,
|
pub methods: Vec<Method>,
|
||||||
pub attributes: Vec<Attribute>,
|
pub attributes: Vec<AttributeType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Class {
|
impl Class {
|
||||||
|
|
@ -23,13 +22,19 @@ impl Class {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Method {
|
pub struct Method {
|
||||||
constant_pool: Rc<Vec<CpEntry>>,
|
constant_pool: Rc<Vec<CpEntry>>,
|
||||||
access_flags: u16,
|
access_flags: u16,
|
||||||
name_index: usize,
|
name_index: usize,
|
||||||
descriptor_index: usize,
|
descriptor_index: usize,
|
||||||
attributes: Vec<Attribute>,
|
attributes: Vec<AttributeType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Method {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Method {{access_flags: {}, name_index: {}, descriptor_index: {}, attributes: {:?} }}",
|
||||||
|
self.access_flags, self.name_index, self.descriptor_index, self.attributes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Method {
|
impl Method {
|
||||||
|
|
@ -37,16 +42,16 @@ impl Method {
|
||||||
access_flags: u16,
|
access_flags: u16,
|
||||||
name_index: usize,
|
name_index: usize,
|
||||||
descriptor_index: usize,
|
descriptor_index: usize,
|
||||||
attributes: Vec<Attribute>, ) -> Self {
|
attributes: Vec<AttributeType>, ) -> Self {
|
||||||
Method { constant_pool, access_flags, name_index, descriptor_index, attributes }
|
Method { constant_pool, access_flags, name_index, descriptor_index, attributes }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> String {
|
||||||
let mut full_name = get_modifier(self.access_flags);
|
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[&self.name_index - 1] {
|
||||||
full_name.push_str(s);
|
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[&self.descriptor_index - 1] {
|
||||||
full_name.push_str(s);
|
full_name.push_str(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,25 +59,34 @@ impl Method {
|
||||||
full_name
|
full_name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_code(&self) {
|
// pub fn get_code(&self) {
|
||||||
for att in &self.attributes {
|
// for att in &self.attributes {
|
||||||
if let CpEntry::Utf8(str) = &self.constant_pool[&att.attribute_name_index - 1] {
|
// if let CpEntry::Utf8(_, str) = &self.constant_pool[&att.attribute_name_index - 1] {
|
||||||
println!("{}", str);
|
// println!("{}", str);
|
||||||
if str == "Code" {
|
// if str == "Code" {
|
||||||
println!("{:?}", att.info);
|
// println!("{:?}", att.info);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
constant_pool: Rc<Vec<CpEntry>>,
|
constant_pool: Rc<Vec<CpEntry>>,
|
||||||
access_flags: u16,
|
access_flags: u16,
|
||||||
name_index: usize,
|
name_index: usize,
|
||||||
descriptor_index: usize,
|
descriptor_index: usize,
|
||||||
_attributes: Vec<Attribute>,
|
attributes: Vec<AttributeType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use crate::io::read_u16;
|
||||||
|
|
||||||
|
impl fmt::Debug for Field {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Field {{access_flags: {}, name_index: {}, descriptor_index: {}, attributes: {:?} }}",
|
||||||
|
self.access_flags, self.name_index, self.descriptor_index, self.attributes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Field {
|
impl Field {
|
||||||
|
|
@ -80,18 +94,18 @@ impl Field {
|
||||||
access_flags: u16,
|
access_flags: u16,
|
||||||
name_index: usize,
|
name_index: usize,
|
||||||
descriptor_index: usize,
|
descriptor_index: usize,
|
||||||
attributes: Vec<Attribute>, ) -> Self {
|
attributes: Vec<AttributeType>, ) -> 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 {
|
pub fn name(&self) -> String {
|
||||||
let mut full_name = get_modifier(self.access_flags);
|
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[&self.descriptor_index - 1] {
|
||||||
full_name.push_str(s);
|
full_name.push_str(s);
|
||||||
}
|
}
|
||||||
full_name.push(' ');
|
full_name.push(' ');
|
||||||
if let CpEntry::Utf8(s) = &self.constant_pool[&self.name_index - 1] {
|
if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.name_index - 1] {
|
||||||
full_name.push_str(s);
|
full_name.push_str(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,13 +113,6 @@ impl Field {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Attribute {
|
|
||||||
pub attribute_name_index: usize,
|
|
||||||
pub info: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const MODIFIERS: [(u16, &str); 12] = [
|
const MODIFIERS: [(u16, &str); 12] = [
|
||||||
(0x0001, "public "),
|
(0x0001, "public "),
|
||||||
(0x0002, "private "),
|
(0x0002, "private "),
|
||||||
|
|
@ -120,21 +127,19 @@ const MODIFIERS: [(u16, &str); 12] = [
|
||||||
(0x0400, "interface "),
|
(0x0400, "interface "),
|
||||||
(0x0800, "strict ")];
|
(0x0800, "strict ")];
|
||||||
|
|
||||||
pub fn get_modifier(value: u16) -> String {
|
pub fn get_modifier(modifier: u16) -> String {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
for m in MODIFIERS {
|
for m in MODIFIERS {
|
||||||
if value & m.0 == m.0 { output.push_str(m.1) }
|
if modifier & m.0 == m.0 { output.push_str(m.1) }
|
||||||
}
|
}
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
use std::cell::OnceCell;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use crate::types::AttributeType::{BootstrapMethods, Code, ConstantValue, NestHost, NestMembers, PermittedSubclasses, StackMapTable};
|
|
||||||
|
|
||||||
enum AttributeType {
|
#[derive(Debug)]
|
||||||
ConstantValue,
|
pub enum AttributeType {
|
||||||
Code,
|
ConstantValue(u16),
|
||||||
|
Code(MethodCode),
|
||||||
StackMapTable,
|
StackMapTable,
|
||||||
BootstrapMethods,
|
BootstrapMethods,
|
||||||
NestHost,
|
NestHost,
|
||||||
|
|
@ -165,16 +170,39 @@ enum AttributeType {
|
||||||
ModuleMainClass,
|
ModuleMainClass,
|
||||||
}
|
}
|
||||||
|
|
||||||
const cell: OnceCell<HashMap<&str, AttributeType>> = OnceCell::new();
|
#[derive(Debug)]
|
||||||
|
pub struct Exception {
|
||||||
|
pub start_pc: u16,
|
||||||
|
pub end_pc: u16,
|
||||||
|
pub handler_pc: u16,
|
||||||
|
pub catch_type: u16,
|
||||||
|
}
|
||||||
|
|
||||||
const value: &HashMap<&str, AttributeType> = cell.get_or_init(|| {
|
impl Exception {
|
||||||
let mut map = HashMap::with_capacity(18);
|
pub fn read(code: &[u8], index: usize) -> Self {
|
||||||
map.insert("ConstantValue", ConstantValue);
|
Self {
|
||||||
map.insert("Code", Code);
|
start_pc: read_u16(code, index),
|
||||||
map.insert("StackMapTable", StackMapTable);
|
end_pc: read_u16(code, index + 2),
|
||||||
map.insert("BootstrapMethods", BootstrapMethods);
|
handler_pc: read_u16(code, index + 4),
|
||||||
map.insert("NestHost", NestHost);
|
catch_type: read_u16(code, index + 6),
|
||||||
map.insert("NestMembers", NestMembers);
|
}
|
||||||
map.insert("PermittedSubclasses", PermittedSubclasses);
|
}
|
||||||
map
|
}
|
||||||
});
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MethodCode {
|
||||||
|
max_stack: u16,
|
||||||
|
max_locals: u16,
|
||||||
|
code: Vec<u8>,
|
||||||
|
exception_table: Vec<Exception>,
|
||||||
|
code_attributes: Vec<AttributeType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MethodCode {
|
||||||
|
pub(crate) fn new(max_stack: u16, max_locals: u16,
|
||||||
|
code: Vec<u8>,
|
||||||
|
exception_table: Vec<Exception>,
|
||||||
|
code_attributes: Vec<AttributeType>) -> Self {
|
||||||
|
Self { max_stack, max_locals, code, exception_table, code_attributes }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
mod test {
|
mod test {
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use classfile_reader::CpEntry::*;
|
use classfile_reader::CpEntry::*;
|
||||||
use classfile_reader::types::{Attribute, Class, Field, Method};
|
use classfile_reader::types::{AttributeType, Class, Field, Method};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn get_version() {
|
fn get_version() {
|
||||||
|
|
@ -25,43 +25,43 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn get_code() {
|
fn get_code() {
|
||||||
let class = get_class();
|
let class = get_class();
|
||||||
println!("{:?}", &class.methods[0].get_code());
|
// println!("{:?}", &class.methods[0].get_code());
|
||||||
println!("{:?}", &class.methods[1].get_code());
|
// println!("{:?}", &class.methods[1].get_code());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_class() -> Class {
|
fn get_class() -> Class {
|
||||||
let cp = Rc::new(vec![
|
let cp = Rc::new(vec![
|
||||||
MethodRef(6, 19),
|
MethodRef(1, 6, 19),
|
||||||
Fieldref(5, 20),
|
Fieldref(2, 5, 20),
|
||||||
Fieldref(21, 22),
|
Fieldref(3, 21, 22),
|
||||||
MethodRef(23, 24),
|
MethodRef(4, 23, 24),
|
||||||
ClassRef(25),
|
ClassRef(5, 25),
|
||||||
ClassRef(26),
|
ClassRef(6, 26),
|
||||||
Utf8("name".to_owned()),
|
Utf8(7, "name".to_owned()),
|
||||||
Utf8("Ljava/lang/String;".to_owned()),
|
Utf8(8, "Ljava/lang/String;".to_owned()),
|
||||||
Utf8("<init>".to_owned()),
|
Utf8(9, "<init>".to_owned()),
|
||||||
Utf8("(Ljava/lang/String;)V".to_owned()), //10
|
Utf8(10, "(Ljava/lang/String;)V".to_owned()), //10
|
||||||
Utf8("Code".to_owned()),
|
Utf8(11, "Code".to_owned()),
|
||||||
Utf8("LineNumberTable".to_owned()),
|
Utf8(12, "LineNumberTable".to_owned()),
|
||||||
Utf8("getName".to_owned()),
|
Utf8(13, "getName".to_owned()),
|
||||||
Utf8("()Ljava/lang/String;".to_owned()),
|
Utf8(14, "()Ljava/lang/String;".to_owned()),
|
||||||
Utf8("print".to_owned()),
|
Utf8(15, "print".to_owned()),
|
||||||
Utf8("()V".to_owned()),
|
Utf8(16, "()V".to_owned()),
|
||||||
Utf8("SourceFile".to_owned()),
|
Utf8(17, "SourceFile".to_owned()),
|
||||||
Utf8("Dummy.java".to_owned()),
|
Utf8(18, "Dummy.java".to_owned()),
|
||||||
NameAndType(9, 16),
|
NameAndType(19, 9, 16),
|
||||||
NameAndType(7, 8), //20
|
NameAndType(20, 7, 8), //20
|
||||||
ClassRef(27),
|
ClassRef(21, 27),
|
||||||
NameAndType(28, 29),
|
NameAndType(22, 28, 29),
|
||||||
ClassRef(30),
|
ClassRef(23, 30),
|
||||||
NameAndType(31, 10),
|
NameAndType(24, 31, 10),
|
||||||
Utf8("dummy/Dummy".to_owned()),
|
Utf8(25, "dummy/Dummy".to_owned()),
|
||||||
Utf8("java/lang/Object".to_owned()),
|
Utf8(26, "java/lang/Object".to_owned()),
|
||||||
Utf8("java/lang/System".to_owned()),
|
Utf8(27, "java/lang/System".to_owned()),
|
||||||
Utf8("out".to_owned()),
|
Utf8(28, "out".to_owned()),
|
||||||
Utf8("Ljava/io/PrintStream;".to_owned()),
|
Utf8(29, "Ljava/io/PrintStream;".to_owned()),
|
||||||
Utf8("java/io/PrintStream".to_owned()),
|
Utf8(30, "java/io/PrintStream".to_owned()),
|
||||||
Utf8("println".to_owned()),
|
Utf8(31, "println".to_owned()),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Class {
|
Class {
|
||||||
|
|
@ -74,27 +74,15 @@ mod test {
|
||||||
interfaces: vec![],
|
interfaces: vec![],
|
||||||
methods: vec![
|
methods: vec![
|
||||||
Method::new(
|
Method::new(
|
||||||
cp.clone(), 1, 9, 10, vec![Attribute {
|
cp.clone(), 1, 9, 10, vec![AttributeType::Deprecated
|
||||||
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(
|
Method::new(
|
||||||
cp.clone(), 1, 13, 14, vec![Attribute {
|
cp.clone(), 1, 13, 14, vec![AttributeType::Deprecated]),
|
||||||
attribute_name_index: 11,
|
Method::new(cp.clone(), 1, 15, 16, vec![AttributeType::Deprecated]),
|
||||||
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],
|
|
||||||
}],
|
|
||||||
),
|
|
||||||
Method::new(cp.clone(), 1, 15, 16, vec![Attribute {
|
|
||||||
attribute_name_index: 11,
|
|
||||||
info: vec![0, 2, 0, 1, 0, 0, 0, 11, 178, 0, 3, 42, 180, 0, 2, 182, 0, 4, 177, 0,
|
|
||||||
0, 0, 1, 0, 12, 0, 0, 0, 10, 0, 2, 0, 0, 0, 16, 0, 10, 0, 17],
|
|
||||||
}]),
|
|
||||||
],
|
],
|
||||||
fields: vec![Field::new(cp, 18, 7, 8, vec![])],
|
fields: vec![Field::new(cp, 18, 7, 8, vec![])],
|
||||||
attributes: vec![Attribute { attribute_name_index: 17, info: vec![0, 18] }],
|
attributes: vec![AttributeType::SourceFile],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Reference in a new issue