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
|
||||
|
||||
[dependencies]
|
||||
[dependencies]
|
||||
BIN
Dummy.class
BIN
Dummy.class
Binary file not shown.
|
|
@ -2,6 +2,9 @@ package dummy;
|
|||
|
||||
public class Dummy {
|
||||
|
||||
private final static String constant = "meh";
|
||||
private final int integer = 57;
|
||||
|
||||
private final 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;
|
||||
mod io;
|
||||
|
||||
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> {
|
||||
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 constant_pool: Vec<CpEntry> = vec![];
|
||||
for _ in 0..constant_pool_count - 1 {
|
||||
constant_pool.push(read_constant_pool_entry(&mut index, &bytecode));
|
||||
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 constant_pool = Rc::new(constant_pool);
|
||||
|
||||
let access_flags = get_u16(&bytecode, index);
|
||||
let this_class = get_u16(&bytecode, index + 2);
|
||||
let super_class = get_u16(&bytecode, index + 4);
|
||||
let access_flags = read_u16(&bytecode, index);
|
||||
let this_class = read_u16(&bytecode, index + 2);
|
||||
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;
|
||||
let mut interfaces = vec![];
|
||||
for _ in 0..interfaces_count {
|
||||
interfaces.push(get_u16(&bytecode, index));
|
||||
interfaces.push(read_u16(&bytecode, index));
|
||||
index += 2;
|
||||
}
|
||||
|
||||
let fields_count = get_u16(&bytecode, index);
|
||||
let fields_count = read_u16(&bytecode, index);
|
||||
index += 2;
|
||||
let mut fields = vec![];
|
||||
for _ in 0..fields_count {
|
||||
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;
|
||||
let mut methods = vec![];
|
||||
for _ in 0..methods_count {
|
||||
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;
|
||||
let mut attributes = vec![];
|
||||
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 {
|
||||
minor_version: get_u16(&bytecode, 4),
|
||||
major_version: get_u16(&bytecode, 6),
|
||||
minor_version: read_u16(&bytecode, 4),
|
||||
major_version: read_u16(&bytecode, 6),
|
||||
constant_pool,
|
||||
access_flags,
|
||||
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];
|
||||
match tag {
|
||||
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]);
|
||||
*index += len + 3;
|
||||
CpEntry::Utf8(String::from_utf8(utf).unwrap())
|
||||
CpEntry::Utf8(cp_index, String::from_utf8(utf).unwrap())
|
||||
}
|
||||
3 => {
|
||||
let value = get_i32(bytecode, *index + 1);
|
||||
let value = read_i32(bytecode, *index + 1);
|
||||
*index += 5;
|
||||
CpEntry::Integer(value)
|
||||
CpEntry::Integer(cp_index, value)
|
||||
}
|
||||
4 => {
|
||||
let value = get_f32(bytecode, *index + 1);
|
||||
let value = read_f32(bytecode, *index + 1);
|
||||
*index += 5;
|
||||
CpEntry::Float(value)
|
||||
CpEntry::Float(cp_index, value)
|
||||
}
|
||||
5 => {
|
||||
let value = get_i64(bytecode, *index + 1);
|
||||
let value = read_i64(bytecode, *index + 1);
|
||||
*index += 9;
|
||||
CpEntry::Long(value)
|
||||
CpEntry::Long(cp_index, value)
|
||||
}
|
||||
6 => {
|
||||
let value = get_f64(bytecode, *index + 1);
|
||||
let value = read_f64(bytecode, *index + 1);
|
||||
*index += 9;
|
||||
CpEntry::Double(value)
|
||||
CpEntry::Double(cp_index, value)
|
||||
}
|
||||
7 => {
|
||||
let name_index = get_u16(bytecode, *index + 1);
|
||||
let name_index = read_u16(bytecode, *index + 1);
|
||||
*index += 3;
|
||||
CpEntry::ClassRef(name_index)
|
||||
CpEntry::ClassRef(cp_index, name_index)
|
||||
}
|
||||
8 => {
|
||||
let string_index = get_u16(bytecode, *index + 1);
|
||||
let string_index = read_u16(bytecode, *index + 1);
|
||||
*index += 3;
|
||||
CpEntry::StringRef(string_index)
|
||||
CpEntry::StringRef(cp_index, string_index)
|
||||
}
|
||||
9 => {
|
||||
let class_index = get_u16(bytecode, *index + 1);
|
||||
let name_and_type_index = get_u16(bytecode, *index + 3);
|
||||
let class_index = read_u16(bytecode, *index + 1);
|
||||
let name_and_type_index = read_u16(bytecode, *index + 3);
|
||||
*index += 5;
|
||||
CpEntry::Fieldref(class_index, name_and_type_index)
|
||||
CpEntry::Fieldref(cp_index, class_index, name_and_type_index)
|
||||
}
|
||||
10 => {
|
||||
let class_index = get_u16(bytecode, *index + 1);
|
||||
let name_and_type_index = get_u16(bytecode, *index + 3);
|
||||
let class_index = read_u16(bytecode, *index + 1);
|
||||
let name_and_type_index = read_u16(bytecode, *index + 3);
|
||||
*index += 5;
|
||||
CpEntry::MethodRef(class_index, name_and_type_index)
|
||||
CpEntry::MethodRef(cp_index, class_index, name_and_type_index)
|
||||
}
|
||||
11 => {
|
||||
let class_index = get_u16(bytecode, *index + 1);
|
||||
let name_and_type_index = get_u16(bytecode, *index + 3);
|
||||
let class_index = read_u16(bytecode, *index + 1);
|
||||
let name_and_type_index = read_u16(bytecode, *index + 3);
|
||||
*index += 5;
|
||||
CpEntry::InterfaceMethodref(class_index, name_and_type_index)
|
||||
CpEntry::InterfaceMethodref(cp_index, class_index, name_and_type_index)
|
||||
}
|
||||
12 => {
|
||||
let name_index = get_u16(bytecode, *index + 1) as usize;
|
||||
let descriptor_index = get_u16(bytecode, *index + 3) as usize;
|
||||
let name_index = read_u16(bytecode, *index + 1) as usize;
|
||||
let descriptor_index = read_u16(bytecode, *index + 3) as usize;
|
||||
*index += 5;
|
||||
CpEntry::NameAndType(name_index, descriptor_index)
|
||||
CpEntry::NameAndType(cp_index, name_index, descriptor_index)
|
||||
}
|
||||
// 15 MethodHandle,
|
||||
// 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 {
|
||||
let access_flags = get_u16(bytecode, *index);
|
||||
let name_index = get_u16(bytecode, *index + 2) as usize;
|
||||
let descriptor_index = get_u16(bytecode, *index + 4) as usize;
|
||||
let attributes_count = get_u16(bytecode, *index + 6);
|
||||
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;
|
||||
let attributes_count = read_u16(bytecode, *index + 6);
|
||||
*index += 8;
|
||||
let mut attributes = vec![];
|
||||
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(
|
||||
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 {
|
||||
let access_flags = get_u16(bytecode, *index);
|
||||
let name_index = get_u16(bytecode, *index + 2) as usize;
|
||||
let descriptor_index = get_u16(bytecode, *index + 4) as usize;
|
||||
let attributes_count = get_u16(bytecode, *index + 6);
|
||||
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;
|
||||
let attributes_count = read_u16(bytecode, *index + 6);
|
||||
*index += 8;
|
||||
|
||||
let mut attributes = vec![];
|
||||
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,
|
||||
access_flags,
|
||||
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 {
|
||||
let attribute_name_index = get_u16(bytecode, *index) as usize;
|
||||
fn read_attribute(constant_pool: Rc<Vec<CpEntry>>, bytecode: &[u8], index: &mut usize) -> Option<AttributeType> {
|
||||
let attribute_name_index = read_u16(bytecode, *index) as usize;
|
||||
*index += 2;
|
||||
let attribute_length = read_u32(bytecode, *index) as usize;
|
||||
*index += 4;
|
||||
let info: Vec<u8> = Vec::from(&bytecode[*index..*index + attribute_length]);
|
||||
*index += attribute_length;
|
||||
|
||||
Attribute {
|
||||
attribute_name_index,
|
||||
info,
|
||||
|
||||
if let CpEntry::Utf8(_, s) = &constant_pool[attribute_name_index - 1] {
|
||||
// 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
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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"))
|
||||
None
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CpEntry {
|
||||
Utf8(String),
|
||||
Integer(i32),
|
||||
Float(f32),
|
||||
Long(i64),
|
||||
Double(f64),
|
||||
ClassRef(u16),
|
||||
StringRef(u16),
|
||||
Fieldref(u16, u16),
|
||||
MethodRef(u16, u16),
|
||||
InterfaceMethodref(u16, u16),
|
||||
NameAndType(usize, usize),
|
||||
Utf8(usize, String),
|
||||
Integer(usize, i32),
|
||||
Float(usize, f32),
|
||||
Long(usize, i64),
|
||||
Double(usize, f64),
|
||||
ClassRef(usize, u16),
|
||||
StringRef(usize, u16),
|
||||
Fieldref(usize, u16, u16),
|
||||
MethodRef(usize, u16, u16),
|
||||
InterfaceMethodref(usize, u16, u16),
|
||||
NameAndType(usize, usize, usize),
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
128
src/types.rs
128
src/types.rs
|
|
@ -1,6 +1,5 @@
|
|||
use std::rc::Rc;
|
||||
use crate::CpEntry;
|
||||
use crate::CpEntry::NameAndType;
|
||||
|
||||
#[derive(Debug)]
|
||||
//TODO create factory function
|
||||
|
|
@ -14,7 +13,7 @@ pub struct Class {
|
|||
pub interfaces: Vec<u16>,
|
||||
pub fields: Vec<Field>,
|
||||
pub methods: Vec<Method>,
|
||||
pub attributes: Vec<Attribute>,
|
||||
pub attributes: Vec<AttributeType>,
|
||||
}
|
||||
|
||||
impl Class {
|
||||
|
|
@ -23,13 +22,19 @@ impl Class {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Method {
|
||||
constant_pool: Rc<Vec<CpEntry>>,
|
||||
access_flags: u16,
|
||||
name_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 {
|
||||
|
|
@ -37,16 +42,16 @@ impl Method {
|
|||
access_flags: u16,
|
||||
name_index: usize,
|
||||
descriptor_index: usize,
|
||||
attributes: Vec<Attribute>, ) -> Self {
|
||||
attributes: Vec<AttributeType>, ) -> Self {
|
||||
Method { constant_pool, access_flags, name_index, descriptor_index, attributes }
|
||||
}
|
||||
|
||||
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[&self.name_index - 1] {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -54,25 +59,34 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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)]
|
||||
pub struct Field {
|
||||
constant_pool: Rc<Vec<CpEntry>>,
|
||||
access_flags: u16,
|
||||
name_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 {
|
||||
|
|
@ -80,18 +94,18 @@ impl Field {
|
|||
access_flags: u16,
|
||||
name_index: usize,
|
||||
descriptor_index: usize,
|
||||
attributes: Vec<Attribute>, ) -> Self {
|
||||
Field { constant_pool, access_flags, name_index, descriptor_index, _attributes: attributes }
|
||||
attributes: Vec<AttributeType>, ) -> Self {
|
||||
Field { constant_pool, access_flags, name_index, descriptor_index, attributes: attributes }
|
||||
}
|
||||
|
||||
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[&self.descriptor_index - 1] {
|
||||
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[&self.name_index - 1] {
|
||||
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] = [
|
||||
(0x0001, "public "),
|
||||
(0x0002, "private "),
|
||||
|
|
@ -120,21 +127,19 @@ const MODIFIERS: [(u16, &str); 12] = [
|
|||
(0x0400, "interface "),
|
||||
(0x0800, "strict ")];
|
||||
|
||||
pub fn get_modifier(value: u16) -> String {
|
||||
pub fn get_modifier(modifier: u16) -> String {
|
||||
let mut output = String::new();
|
||||
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
|
||||
}
|
||||
|
||||
use std::cell::OnceCell;
|
||||
use std::collections::HashMap;
|
||||
use crate::types::AttributeType::{BootstrapMethods, Code, ConstantValue, NestHost, NestMembers, PermittedSubclasses, StackMapTable};
|
||||
|
||||
enum AttributeType {
|
||||
ConstantValue,
|
||||
Code,
|
||||
#[derive(Debug)]
|
||||
pub enum AttributeType {
|
||||
ConstantValue(u16),
|
||||
Code(MethodCode),
|
||||
StackMapTable,
|
||||
BootstrapMethods,
|
||||
NestHost,
|
||||
|
|
@ -165,16 +170,39 @@ enum AttributeType {
|
|||
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(|| {
|
||||
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
|
||||
});
|
||||
impl Exception {
|
||||
pub fn read(code: &[u8], index: usize) -> Self {
|
||||
Self {
|
||||
start_pc: read_u16(code, index),
|
||||
end_pc: read_u16(code, index + 2),
|
||||
handler_pc: read_u16(code, index + 4),
|
||||
catch_type: read_u16(code, index + 6),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
use std::rc::Rc;
|
||||
use classfile_reader::CpEntry::*;
|
||||
use classfile_reader::types::{Attribute, Class, Field, Method};
|
||||
use classfile_reader::types::{AttributeType, Class, Field, Method};
|
||||
|
||||
#[test]
|
||||
fn get_version() {
|
||||
|
|
@ -25,43 +25,43 @@ mod test {
|
|||
#[test]
|
||||
fn get_code() {
|
||||
let class = get_class();
|
||||
println!("{:?}", &class.methods[0].get_code());
|
||||
println!("{:?}", &class.methods[1].get_code());
|
||||
// println!("{:?}", &class.methods[0].get_code());
|
||||
// println!("{:?}", &class.methods[1].get_code());
|
||||
}
|
||||
|
||||
fn get_class() -> Class {
|
||||
let cp = Rc::new(vec![
|
||||
MethodRef(6, 19),
|
||||
Fieldref(5, 20),
|
||||
Fieldref(21, 22),
|
||||
MethodRef(23, 24),
|
||||
ClassRef(25),
|
||||
ClassRef(26),
|
||||
Utf8("name".to_owned()),
|
||||
Utf8("Ljava/lang/String;".to_owned()),
|
||||
Utf8("<init>".to_owned()),
|
||||
Utf8("(Ljava/lang/String;)V".to_owned()), //10
|
||||
Utf8("Code".to_owned()),
|
||||
Utf8("LineNumberTable".to_owned()),
|
||||
Utf8("getName".to_owned()),
|
||||
Utf8("()Ljava/lang/String;".to_owned()),
|
||||
Utf8("print".to_owned()),
|
||||
Utf8("()V".to_owned()),
|
||||
Utf8("SourceFile".to_owned()),
|
||||
Utf8("Dummy.java".to_owned()),
|
||||
NameAndType(9, 16),
|
||||
NameAndType(7, 8), //20
|
||||
ClassRef(27),
|
||||
NameAndType(28, 29),
|
||||
ClassRef(30),
|
||||
NameAndType(31, 10),
|
||||
Utf8("dummy/Dummy".to_owned()),
|
||||
Utf8("java/lang/Object".to_owned()),
|
||||
Utf8("java/lang/System".to_owned()),
|
||||
Utf8("out".to_owned()),
|
||||
Utf8("Ljava/io/PrintStream;".to_owned()),
|
||||
Utf8("java/io/PrintStream".to_owned()),
|
||||
Utf8("println".to_owned()),
|
||||
MethodRef(1, 6, 19),
|
||||
Fieldref(2, 5, 20),
|
||||
Fieldref(3, 21, 22),
|
||||
MethodRef(4, 23, 24),
|
||||
ClassRef(5, 25),
|
||||
ClassRef(6, 26),
|
||||
Utf8(7, "name".to_owned()),
|
||||
Utf8(8, "Ljava/lang/String;".to_owned()),
|
||||
Utf8(9, "<init>".to_owned()),
|
||||
Utf8(10, "(Ljava/lang/String;)V".to_owned()), //10
|
||||
Utf8(11, "Code".to_owned()),
|
||||
Utf8(12, "LineNumberTable".to_owned()),
|
||||
Utf8(13, "getName".to_owned()),
|
||||
Utf8(14, "()Ljava/lang/String;".to_owned()),
|
||||
Utf8(15, "print".to_owned()),
|
||||
Utf8(16, "()V".to_owned()),
|
||||
Utf8(17, "SourceFile".to_owned()),
|
||||
Utf8(18, "Dummy.java".to_owned()),
|
||||
NameAndType(19, 9, 16),
|
||||
NameAndType(20, 7, 8), //20
|
||||
ClassRef(21, 27),
|
||||
NameAndType(22, 28, 29),
|
||||
ClassRef(23, 30),
|
||||
NameAndType(24, 31, 10),
|
||||
Utf8(25, "dummy/Dummy".to_owned()),
|
||||
Utf8(26, "java/lang/Object".to_owned()),
|
||||
Utf8(27, "java/lang/System".to_owned()),
|
||||
Utf8(28, "out".to_owned()),
|
||||
Utf8(29, "Ljava/io/PrintStream;".to_owned()),
|
||||
Utf8(30, "java/io/PrintStream".to_owned()),
|
||||
Utf8(31, "println".to_owned()),
|
||||
]);
|
||||
|
||||
Class {
|
||||
|
|
@ -74,27 +74,15 @@ mod test {
|
|||
interfaces: vec![],
|
||||
methods: vec![
|
||||
Method::new(
|
||||
cp.clone(), 1, 9, 10, vec![Attribute {
|
||||
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],
|
||||
}],
|
||||
cp.clone(), 1, 9, 10, vec![AttributeType::Deprecated
|
||||
],
|
||||
),
|
||||
Method::new(
|
||||
cp.clone(), 1, 13, 14, vec![Attribute {
|
||||
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],
|
||||
}],
|
||||
),
|
||||
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],
|
||||
}]),
|
||||
cp.clone(), 1, 13, 14, vec![AttributeType::Deprecated]),
|
||||
Method::new(cp.clone(), 1, 15, 16, vec![AttributeType::Deprecated]),
|
||||
],
|
||||
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