More Bytecode and Attributes support
This commit is contained in:
parent
8a79a28b5f
commit
b751fc3588
3 changed files with 274 additions and 22 deletions
225
src/classfile.rs
225
src/classfile.rs
|
@ -3,6 +3,7 @@ use std::error::Error as ErrorTrait;
|
|||
use core::fmt::{Display, Formatter, Debug};
|
||||
use core::str::Utf8Error;
|
||||
|
||||
use crate::bytecode::Bytecode;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
|
@ -135,7 +136,7 @@ impl JavaClassFile {
|
|||
|
||||
methods_vec.into_boxed_slice()
|
||||
};
|
||||
let attributes = AttributeInfo::array_from_reader(reader, &constant_pool)?;
|
||||
let attributes = AttributeInfo::array_from_reader(reader, &constant_pool, true)?;
|
||||
|
||||
Ok(
|
||||
JavaClassFile {
|
||||
|
@ -472,7 +473,7 @@ impl FieldInfo {
|
|||
access_flags: AccessFlagMask { mask: read_u16(reader)? },
|
||||
name_index: read_u16(reader)?,
|
||||
descriptor_index: read_u16(reader)?,
|
||||
attributes: AttributeInfo::array_from_reader(reader, pool)?,
|
||||
attributes: AttributeInfo::array_from_reader(reader, pool, true)?,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -530,11 +531,178 @@ impl LineNumberTableAttributeData {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ExceptionTableEntry {
|
||||
start_pc: u16,
|
||||
end_pc: u16,
|
||||
handler_pc: u16,
|
||||
catch_type: u16,
|
||||
}
|
||||
|
||||
impl ExceptionTableEntry {
|
||||
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
|
||||
Ok(
|
||||
ExceptionTableEntry {
|
||||
start_pc: read_u16(reader)?,
|
||||
end_pc: read_u16(reader)?,
|
||||
handler_pc: read_u16(reader)?,
|
||||
catch_type: read_u16(reader)?,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CodeAttributeData {
|
||||
max_stack: u16,
|
||||
max_locals: u16,
|
||||
code: Bytecode,
|
||||
exception_table: Box<[ExceptionTableEntry]>,
|
||||
attributes: Box<[AttributeInfo]>,
|
||||
}
|
||||
|
||||
impl CodeAttributeData {
|
||||
fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>) -> Result<Self, Error> {
|
||||
let max_stack = read_u16(reader)?;
|
||||
let max_locals = read_u16(reader)?;
|
||||
|
||||
let code_length = read_u32(reader)?;
|
||||
let code = read_buffer(reader, code_length.try_into()?)?;
|
||||
|
||||
let exception_length = read_u16(reader)?;
|
||||
let exception_table = {
|
||||
let mut v = Vec::with_capacity(exception_length.into());
|
||||
|
||||
for _i in 0..exception_length {
|
||||
v.push(ExceptionTableEntry::from_reader(reader)?);
|
||||
}
|
||||
|
||||
v.into_boxed_slice()
|
||||
};
|
||||
|
||||
let attributes = AttributeInfo::array_from_reader(reader, pool, false)?;
|
||||
|
||||
Ok(
|
||||
CodeAttributeData {
|
||||
max_stack,
|
||||
max_locals,
|
||||
code: Bytecode { code },
|
||||
exception_table,
|
||||
attributes
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SourceFileAttributeData {
|
||||
source_file_index: u16,
|
||||
}
|
||||
|
||||
impl SourceFileAttributeData {
|
||||
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
|
||||
Ok(
|
||||
SourceFileAttributeData {
|
||||
source_file_index: read_u16(reader)?,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SignatureAttributeData {
|
||||
signature_index: u16,
|
||||
}
|
||||
|
||||
impl SignatureAttributeData {
|
||||
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
|
||||
Ok(
|
||||
SignatureAttributeData {
|
||||
signature_index: read_u16(reader)?,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InnerClassesAttributeEntry {
|
||||
inner_class_info_index: u16,
|
||||
outer_class_info_index: u16,
|
||||
inner_name_index: u16,
|
||||
outer_name_index: u16,
|
||||
}
|
||||
|
||||
impl InnerClassesAttributeEntry {
|
||||
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
|
||||
Ok(
|
||||
InnerClassesAttributeEntry {
|
||||
inner_class_info_index: read_u16(reader)?,
|
||||
outer_class_info_index: read_u16(reader)?,
|
||||
inner_name_index: read_u16(reader)?,
|
||||
outer_name_index: read_u16(reader)?,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InnerClassesAttributeData {
|
||||
classes: Box<[InnerClassesAttributeEntry]>
|
||||
}
|
||||
|
||||
impl InnerClassesAttributeData {
|
||||
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
|
||||
Ok(
|
||||
InnerClassesAttributeData {
|
||||
classes: {
|
||||
let length = read_u16(reader)?;
|
||||
let mut v = Vec::with_capacity(length.into());
|
||||
|
||||
for _i in 0..length {
|
||||
v.push(InnerClassesAttributeEntry::from_reader(reader)?);
|
||||
}
|
||||
|
||||
v.into_boxed_slice()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NestMembersAttributeData {
|
||||
class_indices: Box<[u16]>
|
||||
}
|
||||
|
||||
impl NestMembersAttributeData {
|
||||
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
|
||||
Ok(
|
||||
NestMembersAttributeData {
|
||||
class_indices: {
|
||||
let length = read_u16(reader)?;
|
||||
let mut v = Vec::with_capacity(length.into());
|
||||
|
||||
for _i in 0..length {
|
||||
v.push(read_u16(reader)?);
|
||||
}
|
||||
|
||||
v.into_boxed_slice()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AttributeData {
|
||||
Code(CodeAttributeData),
|
||||
Signature(SignatureAttributeData),
|
||||
NestMembers(NestMembersAttributeData),
|
||||
SourceFile(SourceFileAttributeData),
|
||||
InnerClasses(InnerClassesAttributeData),
|
||||
ConstantValue(ConstantValueAttributeData),
|
||||
LineNumberTable(LineNumberTableAttributeData),
|
||||
UnknownAttribute(UnknownAttributeData),
|
||||
Unknown(UnknownAttributeData),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -544,22 +712,21 @@ pub struct AttributeInfo {
|
|||
}
|
||||
|
||||
impl AttributeInfo {
|
||||
fn array_from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>) -> Result<Box<[Self]>, Error> {
|
||||
fn array_from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>, allow_code_attr: bool) -> Result<Box<[Self]>, Error> {
|
||||
let length = read_u16(reader)?;
|
||||
let mut attr_vec = Vec::with_capacity(length.into());
|
||||
|
||||
for _i in 0..length {
|
||||
let attribute = AttributeInfo::from_reader(reader, &pool)?;
|
||||
println!("{:#?}", attribute);
|
||||
let attribute = AttributeInfo::from_reader(reader, &pool, allow_code_attr)?;
|
||||
attr_vec.push(attribute);
|
||||
}
|
||||
|
||||
Ok(attr_vec.into_boxed_slice())
|
||||
}
|
||||
|
||||
fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>) -> Result<Self, Error> {
|
||||
let attribute_name_index: u16 = read_u16(reader)?;
|
||||
let attribute_byte_size: usize = read_u32(reader)?.try_into()?;
|
||||
fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>, allow_code_attr: bool) -> Result<Self, Error> {
|
||||
let attribute_name_index: u16 = read_u16(reader)? - 1;
|
||||
let _attribute_byte_size: usize = read_u32(reader)?.try_into()?;
|
||||
|
||||
let data = {
|
||||
let name_entry = &pool[attribute_name_index as usize];
|
||||
|
@ -569,19 +736,35 @@ impl AttributeInfo {
|
|||
};
|
||||
|
||||
match &utf8[..] {
|
||||
// "ConstantValue" => AttributeData::ConstantValue(
|
||||
// ConstantValueAttributeData {
|
||||
// constant_value_index: read_u16(reader)?,
|
||||
// }
|
||||
// ),
|
||||
//
|
||||
// "LineNumberTable" => AttributeData::LineNumberTable(
|
||||
// LineNumberTableAttributeData::from_reader(reader)?
|
||||
// ),
|
||||
"ConstantValue" => AttributeData::ConstantValue(
|
||||
ConstantValueAttributeData {
|
||||
constant_value_index: read_u16(reader)?,
|
||||
}
|
||||
),
|
||||
|
||||
&_ => AttributeData::UnknownAttribute(
|
||||
"LineNumberTable" => AttributeData::LineNumberTable(
|
||||
LineNumberTableAttributeData::from_reader(reader)?
|
||||
),
|
||||
|
||||
"Code" => if allow_code_attr {
|
||||
AttributeData::Code(
|
||||
CodeAttributeData::from_reader(reader, pool)?
|
||||
)
|
||||
} else {
|
||||
return Err(Error::BadFileError("Nested Code attributes are forbidden.".to_string()));
|
||||
},
|
||||
|
||||
"SourceFile" => AttributeData::SourceFile(SourceFileAttributeData::from_reader(reader)?),
|
||||
|
||||
"Signature" => AttributeData::Signature(SignatureAttributeData::from_reader(reader)?),
|
||||
|
||||
"InnerClasses" => AttributeData::InnerClasses(InnerClassesAttributeData::from_reader(reader)?),
|
||||
|
||||
"NestMembers" => AttributeData::NestMembers(NestMembersAttributeData::from_reader(reader)?),
|
||||
|
||||
&_ => AttributeData::Unknown(
|
||||
UnknownAttributeData {
|
||||
info: read_buffer(reader, attribute_byte_size)?,
|
||||
info: read_buffer(reader, _attribute_byte_size)?,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -611,7 +794,7 @@ impl MethodInfo {
|
|||
access_flags: AccessFlagMask { mask: read_u16(reader)? },
|
||||
name_index: read_u16(reader)?,
|
||||
descriptor_index: read_u16(reader)?,
|
||||
attributes: AttributeInfo::array_from_reader(reader, pool)?
|
||||
attributes: AttributeInfo::array_from_reader(reader, pool, true)?
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue