Entrypoint call entry methodgit add .
This commit is contained in:
parent
ea3666aad3
commit
2042007242
9 changed files with 573 additions and 119 deletions
160
src/classfile.rs
160
src/classfile.rs
|
@ -1,11 +1,12 @@
|
|||
use std::io::Read;
|
||||
use std::error::Error as ErrorTrait;
|
||||
use core::fmt::{Display, Formatter, Debug};
|
||||
use core::mem::{ discriminant, Discriminant };
|
||||
use core::str::Utf8Error;
|
||||
|
||||
use crate::accessmasks::*;
|
||||
use crate::bytecode::Bytecode;
|
||||
use crate::constantpool::{ ConstantPoolInfo, ConstantUtf8Info };
|
||||
use crate::constantpool::{ ConstantPoolInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantClassInfo, ConstantNameAndTypeInfo };
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
|
@ -173,7 +174,7 @@ impl JavaClassFile {
|
|||
let name_entry = pool_entry(&self.constant_pool, class_info_entry.name_index.into())?;
|
||||
let name_entry = match name_entry {
|
||||
ConstantPoolInfo::Utf8(utf8data) => utf8data,
|
||||
_ => return Err(Error::BadFileError(format!("Invalid name_index class_info from this_class, expected index to Utf8 but found {:?}", name_entry)))
|
||||
_ => return Err(Error::BadFileError(format!("Invalid class_info.name_index from this_class, expected index to Utf8 but found {:?}", name_entry)))
|
||||
};
|
||||
|
||||
return Ok(name_entry.utf8.clone());
|
||||
|
@ -190,6 +191,77 @@ impl JavaClassFile {
|
|||
|
||||
return None;
|
||||
}
|
||||
|
||||
pub fn typed_pool_entry(&self, index: u16, variant: Discriminant<ConstantPoolInfo>) -> Result<&ConstantPoolInfo, Error> {
|
||||
let pool_entry = &self.constant_pool[(index - 1) as usize];
|
||||
|
||||
if discriminant(pool_entry) != variant {
|
||||
return Err(Error::BadFileError(format!("Expected constant pool entry {} in class {} to be of type {:#?} but found {:#?}", index, self.get_classname()?, variant, discriminant(pool_entry))));
|
||||
}
|
||||
|
||||
return Ok(pool_entry);
|
||||
}
|
||||
|
||||
pub fn pool_methodref_entry(&self, index: u16) -> Result<&ConstantMethodRefInfo, Error> {
|
||||
let pool_entry = self.typed_pool_entry(
|
||||
index,
|
||||
discriminant(
|
||||
&ConstantPoolInfo::MethodRef(
|
||||
ConstantMethodRefInfo {
|
||||
class_index: 0,
|
||||
name_and_type_index: 0
|
||||
}
|
||||
)
|
||||
)
|
||||
)?;
|
||||
|
||||
let methodref_entry = match pool_entry {
|
||||
ConstantPoolInfo::MethodRef(data) => data,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
return Ok(methodref_entry);
|
||||
}
|
||||
|
||||
pub fn pool_class_entry(&self, index: u16) -> Result<&ConstantClassInfo, Error> {
|
||||
let pool_entry = self.typed_pool_entry(index, discriminant(&ConstantPoolInfo::Class(ConstantClassInfo {name_index: 0})))?;
|
||||
|
||||
return match pool_entry {
|
||||
ConstantPoolInfo::Class(data) => Ok(data),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn pool_utf8_entry(&self, index: u16) -> Result<&ConstantUtf8Info, Error> {
|
||||
let pool_entry = self.typed_pool_entry(index, discriminant(&ConstantPoolInfo::Utf8(ConstantUtf8Info {utf8: "".to_string()})))?;
|
||||
|
||||
return match pool_entry {
|
||||
ConstantPoolInfo::Utf8(data) => Ok(data),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn pool_nameandtype_entry(&self, index: u16) -> Result<&ConstantNameAndTypeInfo, Error> {
|
||||
let pool_entry = self.typed_pool_entry(index, discriminant(&ConstantPoolInfo::NameAndType(ConstantNameAndTypeInfo {name_index: 0, descriptor_index: 0})))?;
|
||||
|
||||
return match pool_entry {
|
||||
ConstantPoolInfo::NameAndType(data) => Ok(data),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn gather_methodref(&self, index: u16) -> Result<(&String, &String, &String), Error> {
|
||||
let methodref = self.pool_methodref_entry(index)?;
|
||||
let class_entry = self.pool_class_entry(methodref.class_index)?;
|
||||
let class_name_entry = self.pool_utf8_entry(class_entry.name_index)?;
|
||||
let name_and_type_entry = self.pool_nameandtype_entry(methodref.name_and_type_index)?;
|
||||
|
||||
let class_name = &class_name_entry.utf8;
|
||||
let method_name = &self.pool_utf8_entry(name_and_type_entry.name_index)?.utf8;
|
||||
let method_descriptor = &self.pool_utf8_entry(name_and_type_entry.descriptor_index)?.utf8;
|
||||
|
||||
return Ok((class_name, method_name, method_descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -352,7 +424,7 @@ impl CodeAttributeData {
|
|||
CodeAttributeData {
|
||||
max_stack,
|
||||
max_locals,
|
||||
code: Bytecode { code },
|
||||
code: Bytecode { bytes: code },
|
||||
exception_table,
|
||||
attributes
|
||||
}
|
||||
|
@ -546,7 +618,7 @@ impl AttributeInfo {
|
|||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum AbstractTypeKind {
|
||||
Void() = b'V', // void
|
||||
Byte() = b'B', // signed byte
|
||||
|
@ -560,10 +632,43 @@ pub enum AbstractTypeKind {
|
|||
Boolean() = b'Z', // true or false
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
impl Into<String> for &AbstractTypeKind {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
AbstractTypeKind::Void() => "V".to_string(),
|
||||
AbstractTypeKind::Byte() => "B".to_string(),
|
||||
AbstractTypeKind::Char() => "C".to_string(),
|
||||
AbstractTypeKind::Double() => "D".to_string(),
|
||||
AbstractTypeKind::Float() => "F".to_string(),
|
||||
AbstractTypeKind::Int() => "I".to_string(),
|
||||
AbstractTypeKind::Long() => "J".to_string(),
|
||||
AbstractTypeKind::Classname(name) => "L".to_string() + &name + ";",
|
||||
AbstractTypeKind::Short() => "S".to_string(),
|
||||
AbstractTypeKind::Boolean() => "Z".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct AbstractTypeDescription {
|
||||
array_level: u8,
|
||||
kind: AbstractTypeKind,
|
||||
pub array_level: u8,
|
||||
pub kind: AbstractTypeKind,
|
||||
}
|
||||
|
||||
impl Into<String> for &AbstractTypeDescription {
|
||||
fn into(self) -> String {
|
||||
let name_len = match self.kind {
|
||||
AbstractTypeKind::Classname(ref s) => 2 + s.len(),
|
||||
_ => 1,
|
||||
};
|
||||
let mut s = String::with_capacity(self.array_level as usize + name_len);
|
||||
|
||||
s.push_str(&"[".repeat(self.array_level as usize));
|
||||
let kind_string: String = (&self.kind).into();
|
||||
s.push_str(&kind_string);
|
||||
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl AbstractTypeDescription {
|
||||
|
@ -606,10 +711,28 @@ impl AbstractTypeDescription {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub struct MethodDescriptor {
|
||||
argument_types: Box<[AbstractTypeDescription]>,
|
||||
return_type: AbstractTypeDescription,
|
||||
pub argument_types: Box<[AbstractTypeDescription]>,
|
||||
pub return_type: AbstractTypeDescription,
|
||||
}
|
||||
|
||||
impl MethodDescriptor {
|
||||
pub fn source_string(&self) -> String {
|
||||
let mut s = "".to_string();
|
||||
|
||||
s += "(";
|
||||
for argument_type in &self.argument_types {
|
||||
let arg_string: String = argument_type.into();
|
||||
s.push_str(&arg_string);
|
||||
}
|
||||
s += ")";
|
||||
|
||||
let return_string: String = (&self.return_type).into();
|
||||
s.push_str(&return_string);
|
||||
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&String> for MethodDescriptor {
|
||||
|
@ -651,6 +774,12 @@ impl TryFrom<&String> for MethodDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
impl Into<String> for &MethodDescriptor {
|
||||
fn into(self) -> String {
|
||||
return self.source_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MethodInfo {
|
||||
pub access_flags: MethodAccessFlagMask,
|
||||
|
@ -703,6 +832,17 @@ impl MethodInfo {
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_code_attribute(&self) -> Option<&CodeAttributeData> {
|
||||
return if self.code_attribute_index != self.attributes.len() {
|
||||
match &self.attributes[self.code_attribute_index].data {
|
||||
AttributeData::Code(data) => Some(data),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue