Native Unsafe:: methods, main loading, stuff!

This commit is contained in:
VegOwOtenks 2024-11-19 15:37:28 +01:00
parent 90e244c964
commit fba596ce5a
8 changed files with 242 additions and 22 deletions

View file

@ -119,6 +119,7 @@ impl Bytecode {
0x80 => (Instruction::OrInt(), 1),
0x82 => (Instruction::XorInt(), 1),
0x83 => (Instruction::XorLong(), 1),
0x84 => (Instruction::IncrementLocalInt(self.bytes[offset+1], i8::from_be_bytes([self.bytes[offset+2]])), 3),
0x85 => (Instruction::ConvertIntToLong(), 1),
@ -416,6 +417,7 @@ pub enum Instruction {
OrInt() = 0x80, // value, value => or
XorInt() = 0x82, // value, value => xor
XorLong() = 0x83, // value, value => xor
IncrementLocalInt(u8, i8) = 0x84, // increment local variable by constant i8
ConvertIntToLong() = 0x85, // convert int on stack to long

View file

@ -6,9 +6,8 @@ use core::str::Utf8Error;
use crate::accessmasks::*;
use crate::bytecode::Bytecode;
use crate::classstore::ClassStore;
use crate::constantpool::{ ConstantFieldRefInfo, ConstantPoolInfo, ConstantUtf8Info, ConstantInterfaceMethodRefInfo, ConstantStringInfo, ConstantMethodRefInfo, ConstantFloatInfo, ConstantClassInfo, ConstantNameAndTypeInfo, ConstantIntegerInfo, ConstantLongInfo };
use crate::constantpool::*;
use crate::constantpool::ConstantDoubleInfo;
use crate::heap_area::ObjectReference;
#[derive(Debug)]
pub enum Error {
@ -240,6 +239,17 @@ impl JavaClassFile {
return Ok(methodref_entry);
}
pub fn pool_methodhandle_entry(&self, index: u16) -> Result<&ConstantMethodHandleInfo, Error> {
let pool_entry = self.pool_entry(index)?;
let methodhandle_entry = match pool_entry {
ConstantPoolInfo::MethodHandle(data) => data,
_ => unreachable!(),
};
return Ok(methodhandle_entry);
}
pub fn pool_fieldref_entry(&self, index: u16) -> Result<&ConstantFieldRefInfo, Error> {
let pool_entry = self.pool_entry(index)?;
@ -429,6 +439,7 @@ impl JavaClassFile {
Ok(false)
}
}
#[derive(Debug)]
@ -702,9 +713,60 @@ impl NestMembersAttributeData {
}
}
#[derive(Debug)]
pub struct BootstrapMethodEntry {
bootstrap_method_ref: u16,
bootstrap_arguments: Box<[u16]>
}
impl BootstrapMethodEntry {
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
Ok(
BootstrapMethodEntry {
bootstrap_method_ref: read_u16(reader)?,
bootstrap_arguments: {
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 struct BootstrapMethodsData {
bootstrap_methods: Box<[BootstrapMethodEntry]>
}
impl BootstrapMethodsData {
fn from_reader(reader: &mut dyn Read) -> Result<Self, Error> {
Ok(
BootstrapMethodsData {
bootstrap_methods: {
let length = read_u16(reader)?;
let mut v = Vec::with_capacity(length.into());
for _i in 0..length {
v.push(BootstrapMethodEntry::from_reader(reader)?);
}
v.into_boxed_slice()
},
}
)
}
}
#[derive(Debug)]
pub enum AttributeData {
Code(CodeAttributeData),
BootstrapMethods(BootstrapMethodsData),
Signature(SignatureAttributeData),
Synthetic(),
Exceptions(ExceptionAttributeData),
@ -755,6 +817,10 @@ impl AttributeInfo {
}
),
"BootstrapMethods" => AttributeData::BootstrapMethods(
BootstrapMethodsData::from_reader(reader)?,
),
"LineNumberTable" => AttributeData::LineNumberTable(
LineNumberTableAttributeData::from_reader(reader)?
),

View file

@ -16,7 +16,7 @@ pub struct ClassStore {
pub array_classes: HashMap<AbstractTypeDescription, ObjectReference>,
pub classes: Vec<ClassStoreEntry>,
pub class_path_fragments: Vec<PathBuf>,
pub native_class_names: Vec<String>,
pub native_class_descriptors: Vec<String>,
pub primitive_classes: PrimitiveClassStore,
}
@ -83,7 +83,7 @@ impl ClassStore {
array_classes: HashMap::new(),
classes: Vec::new(),
class_path_fragments: vec![current_dir_path],
native_class_names: Vec::new(),
native_class_descriptors: Vec::new(),
primitive_classes: PrimitiveClassStore::default(),
}
}
@ -106,12 +106,12 @@ impl ClassStore {
}
pub fn add_native_class_descriptor(&mut self, name: String) -> usize {
self.native_class_names.push(name);
return self.native_class_names.len() - 1;
self.native_class_descriptors.push(name);
return self.native_class_descriptors.len() - 1;
}
pub fn get_native_class_name(&self, index: usize) -> &String {
return &self.native_class_names[index];
return &self.native_class_descriptors[index];
}
pub fn load_class_from_file(&mut self, class_file_path: &PathBuf) -> Result<usize, Error> {

View file

@ -223,7 +223,7 @@ impl ObjectArea {
fn make_array(&mut self, class_store: &ClassStore, elements: Box<[ObjectReference]>) -> (ObjectReference, usize) {
assert!(elements.len() != 0);
let array_element_class_name = self.get_reference_native_class_name(elements[0], class_store);
let array_element_type_desc = AbstractTypeDescription::parse_first(array_element_class_name).unwrap().1;
let array_element_type_desc = AbstractTypeDescription::parse_full(array_element_class_name).unwrap();
let (array_object_ref, array_size) = self.make_empty_array(class_store, array_element_type_desc, elements.len());
@ -255,6 +255,23 @@ impl ObjectArea {
return (object_ref, object_size);
}
pub fn class_ref_get_class_index(&self, class_ref: ObjectReference, class_store: &ClassStore) -> usize {
let class_data_ref = match self.get_object_field(class_ref, "classData", self.get_object_class_index(class_ref), class_store).unwrap() {
FieldValue::Reference(r) => r,
_ => unreachable!(),
};
let native_name_index = match self.get_object_field(class_data_ref, "native_class_descriptor_index", self.get_object_class_index(class_data_ref), class_store).unwrap() {
FieldValue::Int(i) => i,
_ => unreachable!(),
};
let native_class_name = class_store.get_native_class_name(native_name_index as usize);
let native_class_index = class_store.class_index_for_type(AbstractTypeDescription::parse_full(native_class_name).unwrap()).unwrap();
return native_class_index;
}
pub fn get_class_ref_native_class_name<'a>(&self, class_ref: ObjectReference, class_store: &'a ClassStore) -> &'a String {
let class_data_ref = match self.get_object_field(class_ref, "classData", self.get_object_class_index(class_ref), class_store).unwrap() {
FieldValue::Reference(r) => r,

View file

@ -1471,6 +1471,10 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(instruction_result)))?;
}
Instruction::InvokeDynamic(invokedynamic_index, _zero) => {
let methodhandle_reference = class.pool_methodhandle_entry(invokedynamic_index)?;
}
Instruction::InvokeInterface(methodref_index) => {
let (supplied_interface_name, supplied_method_name, supplied_descriptor_string) = class.gather_interfacemethodref(methodref_index)?;
@ -2600,6 +2604,13 @@ impl JVM {
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(value_1 ^ value_2)))?;
}
Instruction::XorLong() => {
let value_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
let value_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_long(0))?;
wrap_stackframe_error(class, method, frame.operand_stack.push_long(value_1 ^ value_2))?;
}
_ => {
return Err(Error::RunTimeError(format!("Opcode not implemented yet: {:?}", instruction)))
},

View file

@ -25,9 +25,9 @@ fn main() {
jvm.class_store.class_path_fragments.push(PathBuf::from("./classpath"));
match jvm.entrypoint(
&"Main".to_string(),
&"SiedepunktNamen".to_string(),
&"main".to_string(),
&["Hello World"],
&["5"],
) {
Ok(()) => (),
Err(e) => println!("{:#?}", e),

View file

@ -1,3 +1,7 @@
use std::time::SystemTime;
use std::time::UNIX_EPOCH;
use crate::accessmasks::FieldAccessFlag;
use crate::classfile::FieldInfo;
use crate::classstore::ClassStore;
use crate::stackframe::StackFrame;
@ -58,6 +62,59 @@ impl JavaIOFileDescriptor {
struct JavaLangClass {}
impl JavaLangClass {
fn get_declared_fields_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let thread = &mut jvm.threads[jvm.active_thread];
let frame_index = thread.stack_frames.len() - 1;
&mut thread.stack_frames[frame_index]
};
let this = frame.load_local_reference(0).unwrap();
let public_only = frame.load_local_boolean_compatible(1).unwrap();
let class_index = jvm.heap_area.object_area.class_ref_get_class_index(this, &jvm.class_store);
if ! jvm.class_store.have_class(&"java/lang/reflect/Field".to_string()) {
return Ok(JVMCallbackOperation::LoadClass("java/lang/reflect/Field".to_string()));
}
if ! jvm.class_store.was_init(&"java/lang/reflect/Field".to_string()).unwrap() {
return Ok(JVMCallbackOperation::InitClass("java/lang/reflect/Field".to_string()));
}
if ! jvm.class_store.have_class(&"[Ljava/lang/reflect/Field;".to_string()) {
let description = AbstractTypeDescription {
array_level: 0,
kind: AbstractTypeKind::Classname("java/lang/reflect/Field".to_string()),
};
return Ok(JVMCallbackOperation::MakeArrayClass(this, description));
}
let field_class_index = jvm.class_store.class_idx_from_name(&"java/lang/reflect/Field".to_string()).unwrap();
let fields = ClassFieldIterator::new(class_index, &jvm.class_store)
.filter(|field_info| if public_only { field_info.access_flags & FieldAccessFlag::Public } else { true } )
.map(|field_info| {
let field = jvm.heap_area.make_object(&jvm.class_store, field_class_index);
let java_string = jvm.heap_area.make_handmade_string(&field_info.name, &jvm.class_store);
jvm.heap_area.object_area.set_object_field(
field,
"name",
java_string.into(),
field_class_index,
&jvm.class_store
).unwrap();
jvm.heap_area.object_area.set_object_field(
field,
"clazz",
this.into(),
field_class_index,
&jvm.class_store
).unwrap();
field
})
.collect();
let field_array = jvm.heap_area.make_array(&jvm.class_store, fields);
Ok(JVMCallbackOperation::ReturnFrame(field_array.into()))
}
fn is_array(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
@ -500,6 +557,12 @@ impl JavaLangStringUTF16 {
struct JavaLangSystem {}
impl JavaLangSystem {
fn nano_time(_: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let nanos = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos() as i64;
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(nanos)))
}
fn register_natives(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
// Load class because it won't be loaded otherwise
let frame = {
@ -849,7 +912,18 @@ impl JdkInternalMiscUnsafe {
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(success)))
} else {
todo!()
let object_class_descriptor = jvm.heap_area.object_area.get_reference_native_class_name(object, &jvm.class_store);
let object_class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(object_class_descriptor).unwrap()).unwrap();
let field = JdkInternalMiscUnsafe::class_field_at_offset(object_class_index, &jvm.class_store, offset)?;
let current_value = jvm.heap_area.object_area.get_object_field(object, &field.name, object_class_index, &jvm.class_store)?;
let function_result = current_value == expected.into();
if function_result {
jvm.heap_area.object_area.set_object_field(object, &field.name, replacement.into(), object_class_index, &jvm.class_store)?;
}
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(function_result)))
}
}
@ -1003,6 +1077,46 @@ impl JdkInternalMiscUnsafe {
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Boolean(function_result)))
}
pub fn object_field_offset_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
let frame = {
let thread = &mut jvm.threads[jvm.active_thread];
let frame_index = thread.stack_frames.len() - 1;
&mut thread.stack_frames[frame_index]
};
let field_object_reference = frame.load_local_reference(1).unwrap();
let field_class_index = jvm.heap_area.object_area.get_reference_class_index(field_object_reference, &jvm.class_store);
let class = jvm.heap_area.object_area.get_object_field(
field_object_reference,
"clazz",
field_class_index,
&jvm.class_store
)?.expect_reference();
let field_name = jvm.heap_area.object_area.get_object_field(
field_object_reference,
"name",
field_class_index,
&jvm.class_store
)?.expect_reference();
let byte_offset = JdkInternalMiscUnsafe::object_field_offset_2(jvm, class, field_name)?;
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(byte_offset)))
}
fn object_field_offset_2(jvm: &mut JVM, class_object_reference: ObjectReference, field_name_string_reference: ObjectReference) -> Result<i64, Error> {
let class_descriptor = jvm.heap_area.object_area.get_class_ref_native_class_name(class_object_reference, &jvm.class_store);
let class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(class_descriptor).unwrap()).unwrap();
let rust_field_name_string = jvm.heap_area.decode_java_string(field_name_string_reference, &jvm.class_store);
let byte_offset: i64 = ClassFieldIterator::new(class_index as usize, &jvm.class_store)
.take_while(|f| f.name != rust_field_name_string)
.map(|f| f.descriptor.storage_size() as i64)
.sum();
Ok(byte_offset)
}
pub fn object_field_offset_1(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
// args: Class class, String fieldName
let frame = {
@ -1012,16 +1126,9 @@ impl JdkInternalMiscUnsafe {
};
let class_object_reference = frame.load_local_reference(1).unwrap();
let class_descriptor = jvm.heap_area.object_area.get_class_ref_native_class_name(class_object_reference, &jvm.class_store);
let class_index = jvm.class_store.class_index_for_type(AbstractTypeDescription::parse_full(class_descriptor).unwrap()).unwrap();
let field_name_string_reference = frame.load_local_reference(2).unwrap();
let rust_field_name_string = jvm.heap_area.decode_java_string(field_name_string_reference, &jvm.class_store);
let byte_offset: i64 = ClassFieldIterator::new(class_index as usize, &jvm.class_store)
.take_while(|f| f.name != rust_field_name_string)
.map(|f| f.descriptor.storage_size() as i64)
.sum();
let byte_offset = JdkInternalMiscUnsafe::object_field_offset_2(jvm, class_object_reference, field_name_string_reference)?;
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Long(byte_offset)))
}
@ -1257,7 +1364,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
]),
return_type: AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/reflect/Field".to_string()) },
},
todo_call
JavaLangClass::get_declared_fields_0
),
(
@ -1784,7 +1891,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
},
todo_call
JavaLangSystem::nano_time
),
(
@ -2543,7 +2650,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
]),
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long()},
},
todo_call
JdkInternalMiscUnsafe::object_field_offset_0
),
(

View file

@ -430,6 +430,23 @@ impl StackFrame {
}
}
pub fn load_local_boolean_compatible(&self, index: u16) -> Result<bool, Error> {
let local = self.locals[index as usize];
match local {
StackValue::Boolean(b) => Ok(b),
StackValue::Int(i) => Ok(i != 0),
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function locals, expected Boolean but found '{:?}'", index, local)))
}
}
pub fn load_local_boolean(&self, index: u16) -> Result<bool, Error> {
let local = self.locals[index as usize];
match local {
StackValue::Boolean(b) => Ok(b),
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function locals, expected Boolean but found '{:?}'", index, local)))
}
}
pub fn load_local_int(&self, index: u16) -> Result<i32, Error> {
let local = self.locals[index as usize];
match local {