Entrypoint call entry methodgit add .

This commit is contained in:
VegOwOtenks 2024-09-02 11:28:00 +02:00
parent ea3666aad3
commit 2042007242
9 changed files with 573 additions and 119 deletions

View file

@ -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
};
}
}