Static object creation

This commit is contained in:
VegOwOtenks 2024-09-02 17:44:59 +02:00
parent 8642dcdd6a
commit 6c0fbd179a
6 changed files with 160 additions and 29 deletions

View file

@ -130,9 +130,33 @@ pub enum FieldAccessFlag {
Enum = 0x4000, // Declared as an element of an enum class. Enum = 0x4000, // Declared as an element of an enum class.
} }
pub struct FieldAccessFlagMask { #[derive(Clone, Copy)]
pub mask: u16 pub struct FieldAccessFlagMask {
} pub mask: u16
}
impl FieldAccessFlag {
pub fn discriminant(&self) -> u16 {
return match self {
Self::Public => 0x0001,
Self::Private => 0x0002,
Self::Protected => 0x0004,
Self::Static => 0x0008,
Self::Final => 0x0010,
Self::Volatile => 0x0040,
Self::Transient => 0x0080,
Self::Synthetic => 0x1000,
Self::Enum => 0x4000,
}
}
}
impl BitAnd<FieldAccessFlag> for FieldAccessFlagMask {
type Output=bool;
fn bitand(self, f: FieldAccessFlag) -> bool {
return (self.mask & f.discriminant()) != 0;
}
}
impl Debug for FieldAccessFlagMask { impl Debug for FieldAccessFlagMask {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {

View file

@ -266,10 +266,10 @@ impl JavaClassFile {
#[derive(Debug)] #[derive(Debug)]
pub struct FieldInfo { pub struct FieldInfo {
access_flags: FieldAccessFlagMask, pub access_flags: FieldAccessFlagMask,
name: String, pub name: String,
descriptor: AbstractTypeDescription, pub descriptor: AbstractTypeDescription,
attributes: Box<[AttributeInfo]>, pub attributes: Box<[AttributeInfo]>,
} }
impl FieldInfo { impl FieldInfo {
@ -535,11 +535,15 @@ impl NestMembersAttributeData {
pub enum AttributeData { pub enum AttributeData {
Code(CodeAttributeData), Code(CodeAttributeData),
Signature(SignatureAttributeData), Signature(SignatureAttributeData),
Synthetic(),
Exceptions(ExceptionAttributeData),
NestMembers(NestMembersAttributeData), NestMembers(NestMembersAttributeData),
SourceFile(SourceFileAttributeData), SourceFile(SourceFileAttributeData),
InnerClasses(InnerClassesAttributeData), InnerClasses(InnerClassesAttributeData),
ConstantValue(ConstantValueAttributeData), ConstantValue(ConstantValueAttributeData),
DebugExtension(DebugExtensionAttributeData),
LineNumberTable(LineNumberTableAttributeData), LineNumberTable(LineNumberTableAttributeData),
EnclosingMethod(EnclosingMethodAttributeData),
Unknown(UnknownAttributeData), Unknown(UnknownAttributeData),
} }
@ -564,7 +568,7 @@ impl AttributeInfo {
fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>, allow_code_attr: bool) -> Result<Self, Error> { 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_name_index: u16 = read_u16(reader)? - 1;
let _attribute_byte_size: usize = read_u32(reader)?.try_into()?; let attribute_byte_size: usize = read_u32(reader)?.try_into()?;
let data = { let data = {
let name_entry = &pool[attribute_name_index as usize]; let name_entry = &pool[attribute_name_index as usize];
@ -574,35 +578,47 @@ impl AttributeInfo {
}; };
match &utf8[..] { match &utf8[..] {
"ConstantValue" => AttributeData::ConstantValue( "ConstantValue" => AttributeData::ConstantValue(
ConstantValueAttributeData { ConstantValueAttributeData {
constant_value_index: read_u16(reader)?, constant_value_index: read_u16(reader)?,
} }
), ),
"LineNumberTable" => AttributeData::LineNumberTable( "LineNumberTable" => AttributeData::LineNumberTable(
LineNumberTableAttributeData::from_reader(reader)? LineNumberTableAttributeData::from_reader(reader)?
), ),
"Code" => if allow_code_attr { "Code" => if allow_code_attr {
AttributeData::Code( AttributeData::Code(
CodeAttributeData::from_reader(reader, pool)? CodeAttributeData::from_reader(reader, pool)?
) )
} else { } else {
return Err(Error::BadFileError("Nested Code attributes are forbidden.".to_string())); return Err(Error::BadFileError("Nested Code attributes are forbidden.".to_string()));
}, },
"SourceFile" => AttributeData::SourceFile(SourceFileAttributeData::from_reader(reader)?), "SourceFile" => AttributeData::SourceFile(SourceFileAttributeData::from_reader(reader)?),
"Signature" => AttributeData::Signature(SignatureAttributeData::from_reader(reader)?), "Signature" => AttributeData::Signature(SignatureAttributeData::from_reader(reader)?),
"InnerClasses" => AttributeData::InnerClasses(InnerClassesAttributeData::from_reader(reader)?), "InnerClasses" => AttributeData::InnerClasses(InnerClassesAttributeData::from_reader(reader)?),
"NestMembers" => AttributeData::NestMembers(NestMembersAttributeData::from_reader(reader)?), "NestMembers" => AttributeData::NestMembers(NestMembersAttributeData::from_reader(reader)?),
"Exceptions" => AttributeData::Exceptions(ExceptionAttributeData::from_reader(reader)?),
"EnclosingMethod" => AttributeData::EnclosingMethod(EnclosingMethodAttributeData {class_index: read_u16(reader)?, method_index: read_u16(reader)?}),
"Synthetic" => AttributeData::Synthetic(),
"DebugExtension" => AttributeData::DebugExtension(
DebugExtensionAttributeData {
utf8: std::str::from_utf8(&(read_buffer(reader, attribute_byte_size)?))?.to_string(),
}
),
&_ => AttributeData::Unknown( &_ => AttributeData::Unknown(
UnknownAttributeData { UnknownAttributeData {
info: read_buffer(reader, _attribute_byte_size)?, info: read_buffer(reader, attribute_byte_size)?,
} }
) )
} }
@ -617,8 +633,42 @@ impl AttributeInfo {
} }
} }
#[derive(Debug)]
pub struct DebugExtensionAttributeData {
utf8: String,
}
#[derive(Debug)]
pub struct EnclosingMethodAttributeData {
class_index: u16,
method_index: u16,
}
// for use on methods, what exception can be thrown by this
#[derive(Debug)]
pub struct ExceptionAttributeData {
exception_indices: Box<[u16]>,
}
impl ExceptionAttributeData {
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
let length = read_u16(reader)?;
let mut exception_vector = Vec::with_capacity(length as usize);
for _ in 0..length {
exception_vector.push(read_u16(reader)?);
}
Ok(
ExceptionAttributeData {
exception_indices: exception_vector.into_boxed_slice()
}
)
}
}
#[repr(u8)] #[repr(u8)]
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq, Clone)]
pub enum AbstractTypeKind { pub enum AbstractTypeKind {
Void() = b'V', // void Void() = b'V', // void
Byte() = b'B', // signed byte Byte() = b'B', // signed byte
@ -649,7 +699,7 @@ impl Into<String> for &AbstractTypeKind {
} }
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq, Clone)]
pub struct AbstractTypeDescription { pub struct AbstractTypeDescription {
pub array_level: u8, pub array_level: u8,
pub kind: AbstractTypeKind, pub kind: AbstractTypeKind,

View file

@ -1,7 +1,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::accessmasks::FieldAccessFlag;
use crate::stackframe::Value; use crate::stackframe::Value;
use crate::classfile::{ AbstractTypeDescription, MethodInfo }; use crate::classfile::{ JavaClassFile, AbstractTypeDescription, MethodInfo };
#[derive(Debug)] #[derive(Debug)]
pub struct HeapArea { pub struct HeapArea {
@ -54,13 +55,46 @@ pub struct StaticArea {
static_objects: HashMap<String, StaticObject>, static_objects: HashMap<String, StaticObject>,
} }
impl StaticArea {
pub fn make(&mut self, class: &JavaClassFile, class_index: usize) {
let mut fields = Vec::new();
for field in &class.fields {
if field.access_flags & FieldAccessFlag::Static {
fields.push(
StaticField {
name: field.name.clone(),
type_description: field.descriptor.clone(),
value: Value::default_for(field.descriptor),
}
)
}
}
let new_object = StaticObject {
class_index,
fields: fields.into_boxed_slice(),
methods: Box::new([]),
};
let _ = self.static_objects.insert(class.get_classname().unwrap(), new_object);
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct StaticObject { pub struct StaticObject {
pub class_index: usize, pub class_index: usize,
pub fields: Box<[ObjectField]>, pub fields: Box<[StaticField]>,
pub methods: Box<[MethodInfo]>, pub methods: Box<[MethodInfo]>,
} }
#[derive(Debug)]
pub struct StaticField {
pub name: String,
pub type_description: AbstractTypeDescription,
pub value: Value,
}
#[derive(Debug)] #[derive(Debug)]
pub struct ObjectField { pub struct ObjectField {
pub type_description: AbstractTypeDescription, pub type_description: AbstractTypeDescription,

View file

@ -161,7 +161,7 @@ impl JVM {
}, },
JVMCallbackOperation::InitClass(name) => { JVMCallbackOperation::InitClass(name) => {
self.init_class(*self.class_store.class_idx_from_name(&name).unwrap()); self.init_class(*self.class_store.class_idx_from_name(&name).unwrap())?;
} }
} }
} }
@ -169,14 +169,19 @@ impl JVM {
Ok(()) Ok(())
} }
pub fn init_class(&mut self, class_idx: usize) { pub fn init_class(&mut self, class_idx: usize) -> Result<(), Error> {
let class_file = self.class_store.class_file_from_idx(class_idx).unwrap(); let class_file = self.class_store.class_file_from_idx(class_idx).unwrap();
let clinit_idx = class_file.find_method_index(&"<clinit>".to_string()); let clinit_idx = class_file.find_method_index(&"<clinit>".to_string());
// TODO: ConstantValue Attributes (final)
// TODO: Static Stuff // TODO: Static Stuff
self.heap_area.static_area.make(class_file, class_idx);
// TODO: ConstantValue Attributes (final)
// TODO: Push clinit function
self.class_store.set_init(class_idx, true); self.class_store.set_init(class_idx, true);
Ok(())
} }
fn prepare_invoke_static(&mut self, class_index: usize, method_name: &String, arguments: &[Value]) -> Result<(), Error> { fn prepare_invoke_static(&mut self, class_index: usize, method_name: &String, arguments: &[Value]) -> Result<(), Error> {

View file

@ -26,5 +26,6 @@ fn main() {
Err(e) => println!("{:#?}", e), Err(e) => println!("{:#?}", e),
}; };
println!("{:#?}", jvm.stack_frames); println!("{:#?}", jvm);
//println!("{:#?}", JavaClassFile::new(&mut File::open("java/Class.class").unwrap()));
} }

View file

@ -1,4 +1,4 @@
use crate::classfile::{ JavaClassFile, AttributeData }; use crate::classfile::{ JavaClassFile, AttributeData, AbstractTypeDescription };
use crate::heap_area::ObjectReference; use crate::heap_area::ObjectReference;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -18,6 +18,23 @@ pub enum Value {
Empty(), Empty(),
} }
impl Value {
fn default_for(t: AbstractTypeDescription) -> Self {
match t {
AbstractTypeDescription::Void() => unreachable!(),
AbstractTypeDescription::Byte() => Value::Byte(0),
AbstractTypeDescription::Char() => Value::Char(0),
AbstractTypeDescription::Double() => Value::Double(0),
AbstractTypeDescription::Float() => ,
AbstractTypeDescription::Int() => ,
AbstractTypeDescription::Long() => ,
AbstractTypeDescription::Classname(String) => ,
AbstractTypeDescription::Short() => ,
AbstractTypeDescription::Boolean() => ,
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct OperandStack { pub struct OperandStack {
stack: Box<[Value]>, stack: Box<[Value]>,