Compare commits
2 commits
6b03cab14d
...
8e5b6bb2b8
Author | SHA1 | Date | |
---|---|---|---|
8e5b6bb2b8 | |||
f5428c79b2 |
5 changed files with 333 additions and 17 deletions
|
@ -102,6 +102,7 @@ impl Bytecode {
|
||||||
0x6D => (Instruction::DivideLong(), 1),
|
0x6D => (Instruction::DivideLong(), 1),
|
||||||
0x6E => (Instruction::DivideFloat(), 1),
|
0x6E => (Instruction::DivideFloat(), 1),
|
||||||
|
|
||||||
|
0x70 => (Instruction::ModuloInt(), 1),
|
||||||
0x74 => (Instruction::NegateInt(), 1),
|
0x74 => (Instruction::NegateInt(), 1),
|
||||||
0x75 => (Instruction::NegateLong(), 1),
|
0x75 => (Instruction::NegateLong(), 1),
|
||||||
0x78 => (Instruction::ArithmeticShiftIntLeft(), 1),
|
0x78 => (Instruction::ArithmeticShiftIntLeft(), 1),
|
||||||
|
@ -386,6 +387,7 @@ pub enum Instruction {
|
||||||
DivideLong() = 0x6D, // long division
|
DivideLong() = 0x6D, // long division
|
||||||
DivideFloat() = 0x6E, // float division
|
DivideFloat() = 0x6E, // float division
|
||||||
|
|
||||||
|
ModuloInt() = 0x70, // modulo
|
||||||
NegateInt() = 0x74, // arithmetic negation
|
NegateInt() = 0x74, // arithmetic negation
|
||||||
NegateLong() = 0x75, // arithmetic negation
|
NegateLong() = 0x75, // arithmetic negation
|
||||||
ArithmeticShiftIntLeft() = 0x78, // shift int left, preserve sign
|
ArithmeticShiftIntLeft() = 0x78, // shift int left, preserve sign
|
||||||
|
|
|
@ -375,6 +375,15 @@ impl JavaClassFile {
|
||||||
|
|
||||||
return Ok((class_name, method_name, method_descriptor));
|
return Ok((class_name, method_name, method_descriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn gather_methodref_compatible(&self, methodref_index: u16) -> Result<(&String, &String, &String), Error> {
|
||||||
|
return match self.pool_entry(methodref_index) {
|
||||||
|
Ok(ConstantPoolInfo::MethodRef(_)) => self.gather_methodref(methodref_index),
|
||||||
|
Ok(ConstantPoolInfo::InterfaceMethodRef(_)) => self.gather_interfacemethodref(methodref_index),
|
||||||
|
Err(i) => Err(i),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn sourcefile(&self) -> Result<Option<&String>, Error> {
|
pub fn sourcefile(&self) -> Result<Option<&String>, Error> {
|
||||||
match (&self.attributes).into_iter()
|
match (&self.attributes).into_iter()
|
||||||
|
@ -391,6 +400,23 @@ impl JavaClassFile {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_method_bytecode_protected(&self, method: &MethodInfo, instruction_pointer: u16, exception: crate::heap_area::ObjectReference) -> bool {
|
||||||
|
let code_attribute = method.get_code_attribute().unwrap();
|
||||||
|
|
||||||
|
for exception_entry in &code_attribute.exception_table {
|
||||||
|
if exception_entry.start_pc <= instruction_pointer && exception_entry.end_pc > instruction_pointer {
|
||||||
|
if exception_entry.catch_type == 0 {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// Check catch-type
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -500,10 +526,10 @@ impl LineNumberTableAttributeData {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ExceptionTableEntry {
|
pub struct ExceptionTableEntry {
|
||||||
start_pc: u16,
|
pub start_pc: u16,
|
||||||
end_pc: u16,
|
pub end_pc: u16,
|
||||||
handler_pc: u16,
|
pub handler_pc: u16,
|
||||||
catch_type: u16,
|
pub catch_type: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExceptionTableEntry {
|
impl ExceptionTableEntry {
|
||||||
|
@ -517,6 +543,10 @@ impl ExceptionTableEntry {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn catches_in(&self, instruction_pointer: u16) -> bool {
|
||||||
|
return self.start_pc <= instruction_pointer && self.end_pc > instruction_pointer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -1128,6 +1158,20 @@ impl MethodInfo {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_native(&self) -> bool {
|
||||||
|
return self.access_flags & MethodAccessFlag::Native;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_protected_handler_pc(&self, instruction_pointer: u16) -> Option<u16> {
|
||||||
|
for exception_entry in &self.get_code_attribute()?.exception_table {
|
||||||
|
if exception_entry.catches_in(instruction_pointer) {
|
||||||
|
return Some(exception_entry.handler_pc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
88
src/jvm.rs
88
src/jvm.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::classfile::ExceptionTableEntry;
|
||||||
use core::fmt::{Display, Formatter};
|
use core::fmt::{Display, Formatter};
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
@ -9,7 +10,7 @@ use crate::classfile;
|
||||||
use crate::classfile::{ JavaClassFile, FieldInfo, MethodInfo, MethodDescriptor, AbstractTypeDescription, AbstractTypeKind, AttributeInfo, AttributeData, CodeAttributeData, ConstantValueAttributeData };
|
use crate::classfile::{ JavaClassFile, FieldInfo, MethodInfo, MethodDescriptor, AbstractTypeDescription, AbstractTypeKind, AttributeInfo, AttributeData, CodeAttributeData, ConstantValueAttributeData };
|
||||||
use crate::classstore;
|
use crate::classstore;
|
||||||
use crate::classstore::ClassStore;
|
use crate::classstore::ClassStore;
|
||||||
use crate::constantpool::{ ConstantPoolInfo, ConstantClassInfo, ConstantUtf8Info, ConstantMethodRefInfo, ConstantNameAndTypeInfo};
|
use crate::constantpool::{ ConstantClassInfo, ConstantInterfaceMethodRefInfo, ConstantMethodRefInfo, ConstantNameAndTypeInfo, ConstantPoolInfo, ConstantUtf8Info};
|
||||||
use crate::heap_area::{ HeapArea, FieldValue, ObjectReference, CompartmentEntry };
|
use crate::heap_area::{ HeapArea, FieldValue, ObjectReference, CompartmentEntry };
|
||||||
use crate::iterators::{ ClassMethodIterator, ClassFieldIterator };
|
use crate::iterators::{ ClassMethodIterator, ClassFieldIterator };
|
||||||
use crate::native_methods;
|
use crate::native_methods;
|
||||||
|
@ -259,7 +260,12 @@ impl JVM {
|
||||||
ConstantPoolInfo::Class(ConstantClassInfo { name_index: 18 }),
|
ConstantPoolInfo::Class(ConstantClassInfo { name_index: 18 }),
|
||||||
ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "java/lang/System".to_string() }),
|
ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "java/lang/System".to_string() }),
|
||||||
ConstantPoolInfo::NameAndType(ConstantNameAndTypeInfo { name_index: 20, descriptor_index: 13 }),
|
ConstantPoolInfo::NameAndType(ConstantNameAndTypeInfo { name_index: 20, descriptor_index: 13 }),
|
||||||
ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "initPhase1".to_string() }),
|
ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "initPhase1".to_string() }), // 20
|
||||||
|
ConstantPoolInfo::InterfaceMethodRef(ConstantInterfaceMethodRefInfo { class_index: 22, name_and_type_index: 24}),
|
||||||
|
ConstantPoolInfo::Class(ConstantClassInfo { name_index: 23 }),
|
||||||
|
ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "java/lang/Throwable".to_string() }),
|
||||||
|
ConstantPoolInfo::NameAndType(ConstantNameAndTypeInfo { name_index: 25, descriptor_index: 13 }),
|
||||||
|
ConstantPoolInfo::Utf8(ConstantUtf8Info { utf8: "printStackTrace".to_string() }), // 25
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
access_flags: ClassAccessFlagMask { mask: ClassAccessFlag::Super.discriminant() },
|
access_flags: ClassAccessFlagMask { mask: ClassAccessFlag::Super.discriminant() },
|
||||||
|
@ -309,9 +315,24 @@ impl JVM {
|
||||||
0xB8_u8.to_be(), // invokestatic
|
0xB8_u8.to_be(), // invokestatic
|
||||||
0x04_u16.to_be_bytes()[0], // index 4 into the constant
|
0x04_u16.to_be_bytes()[0], // index 4 into the constant
|
||||||
0x04_u16.to_be_bytes()[1], // pool
|
0x04_u16.to_be_bytes()[1], // pool
|
||||||
|
|
||||||
|
0xB1_u8.to_be(), // returnvoid
|
||||||
|
// index 14
|
||||||
|
|
||||||
|
0xB9_u8.to_be(), // invokeinterface
|
||||||
|
21_u16.to_be_bytes()[0], // index 21 constant
|
||||||
|
21_u16.to_be_bytes()[1], // index 21 constant
|
||||||
|
0x00_u8.to_be(), // constant 0
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
exception_table: Box::new([]),
|
exception_table: Box::new([
|
||||||
|
ExceptionTableEntry {
|
||||||
|
start_pc: 0,
|
||||||
|
end_pc: u16::MAX,
|
||||||
|
handler_pc: 14,
|
||||||
|
catch_type: 0, // Catchall
|
||||||
|
}
|
||||||
|
]),
|
||||||
attributes: Box::new([]),
|
attributes: Box::new([]),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -460,6 +481,43 @@ impl JVM {
|
||||||
JVMCallbackOperation::MakeArrayClass(component_class_ref, component_descriptor) => {
|
JVMCallbackOperation::MakeArrayClass(component_class_ref, component_descriptor) => {
|
||||||
self.make_array_class(component_class_ref, component_descriptor);
|
self.make_array_class(component_class_ref, component_descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JVMCallbackOperation::ThrowException(exception) => {
|
||||||
|
let mut is_handler_found = false;
|
||||||
|
while ! is_handler_found {
|
||||||
|
is_handler_found = {
|
||||||
|
let frame = {
|
||||||
|
let frame_index = self.stack_frames.len() - 1;
|
||||||
|
&mut self.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
|
let method = &class.methods[frame.method_index as usize];
|
||||||
|
if method.is_native() {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
class.is_method_bytecode_protected(method, frame.instruction_pointer as u16, exception)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ! is_handler_found {
|
||||||
|
self.stack_frames.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_handler_found {
|
||||||
|
let frame = {
|
||||||
|
let frame_index = self.stack_frames.len() - 1;
|
||||||
|
&mut self.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
let class = self.class_store.class_file_from_idx(frame.class_index).unwrap();
|
||||||
|
let method = &class.methods[frame.method_index as usize];
|
||||||
|
frame.operand_stack.clear();
|
||||||
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Reference(exception)))?;
|
||||||
|
frame.instruction_pointer = method.get_protected_handler_pc(frame.instruction_pointer as u16).unwrap() as u32;
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1345,7 +1403,7 @@ impl JVM {
|
||||||
},
|
},
|
||||||
|
|
||||||
Instruction::InvokeStatic(methodref_index) => {
|
Instruction::InvokeStatic(methodref_index) => {
|
||||||
let (supplied_class_name, supplied_method_name, supplied_descriptor_string) = class.gather_methodref(methodref_index)?;
|
let (supplied_class_name, supplied_method_name, supplied_descriptor_string) = class.gather_methodref_compatible(methodref_index)?;
|
||||||
|
|
||||||
if ! self.class_store.have_class(supplied_class_name) {
|
if ! self.class_store.have_class(supplied_class_name) {
|
||||||
// rewind the bytecode offset, I'll need to execute this instruction again
|
// rewind the bytecode offset, I'll need to execute this instruction again
|
||||||
|
@ -1784,6 +1842,15 @@ impl JVM {
|
||||||
wrap_stackframe_error(class, method, frame.operand_stack.push_long(result))?;
|
wrap_stackframe_error(class, method, frame.operand_stack.push_long(result))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction::ModuloInt() => {
|
||||||
|
let int_1 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||||
|
let int_2 = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||||
|
|
||||||
|
let modulo = int_2.wrapping_rem(int_1);
|
||||||
|
|
||||||
|
wrap_stackframe_error(class, method, frame.operand_stack.push(StackValue::Int(modulo)))?;
|
||||||
|
}
|
||||||
|
|
||||||
Instruction::NegateInt() => {
|
Instruction::NegateInt() => {
|
||||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
||||||
let negated = -int;
|
let negated = -int;
|
||||||
|
@ -1962,6 +2029,7 @@ impl JVM {
|
||||||
match expected_field_descriptor.as_str() {
|
match expected_field_descriptor.as_str() {
|
||||||
"Z" => FieldValue::Boolean(i != 0),
|
"Z" => FieldValue::Boolean(i != 0),
|
||||||
"B" => FieldValue::Byte(i as i8),
|
"B" => FieldValue::Byte(i as i8),
|
||||||
|
"C" => FieldValue::Char(i as u16),
|
||||||
_ => FieldValue::Int(i)
|
_ => FieldValue::Int(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2068,7 +2136,7 @@ impl JVM {
|
||||||
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
|
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
|
||||||
}
|
}
|
||||||
|
|
||||||
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int(0))?;
|
let int = wrap_stackframe_error(class, method, frame.operand_stack.pop_int_compatible(0))?;
|
||||||
|
|
||||||
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(int)));
|
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(int)));
|
||||||
}
|
}
|
||||||
|
@ -2281,7 +2349,10 @@ impl JVM {
|
||||||
Instruction::ThrowException() => {
|
Instruction::ThrowException() => {
|
||||||
let exception = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
let exception = wrap_stackframe_error(class, method, frame.operand_stack.pop_reference(0))?;
|
||||||
if exception == ObjectReference::NULL {
|
if exception == ObjectReference::NULL {
|
||||||
|
// TODO: Throw NullPointerException
|
||||||
|
} else {
|
||||||
|
// TODO: Check throwable instance
|
||||||
|
return Ok(JVMCallbackOperation::ThrowException(exception));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2312,6 +2383,7 @@ pub enum JVMCallbackOperation {
|
||||||
LoadClass(String),
|
LoadClass(String),
|
||||||
InitClass(String),
|
InitClass(String),
|
||||||
MakeArrayClass(ObjectReference, AbstractTypeDescription),
|
MakeArrayClass(ObjectReference, AbstractTypeDescription),
|
||||||
|
ThrowException(ObjectReference),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_local_reference(class: &JavaClassFile, method: &MethodInfo, frame: &mut StackFrame, index: usize) -> Result<(), Error> {
|
fn load_local_reference(class: &JavaClassFile, method: &MethodInfo, frame: &mut StackFrame, index: usize) -> Result<(), Error> {
|
||||||
|
@ -2367,8 +2439,8 @@ fn fill_arguments(class: &JavaClassFile, method: &MethodInfo, arguments: &mut Ve
|
||||||
wrap_stackframe_error(
|
wrap_stackframe_error(
|
||||||
class,
|
class,
|
||||||
method,
|
method,
|
||||||
stack.pop_char(0)
|
stack.pop_int_compatible(0)
|
||||||
)? as i32
|
)?
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -461,6 +461,14 @@ impl JavaLangThrowable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct JdkInternalMiscCDS {}
|
||||||
|
|
||||||
|
impl JdkInternalMiscCDS {
|
||||||
|
fn get_cds_config_status(_jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct JdkInternalMiscUnsafe {}
|
struct JdkInternalMiscUnsafe {}
|
||||||
|
|
||||||
impl JdkInternalMiscUnsafe {
|
impl JdkInternalMiscUnsafe {
|
||||||
|
@ -2949,6 +2957,185 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
},
|
},
|
||||||
JavaLangThrowable::fill_in_stacktrace
|
JavaLangThrowable::fill_in_stacktrace
|
||||||
),
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/invoke/MethodHandle",
|
||||||
|
"invokeExact",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/invoke/MethodHandle",
|
||||||
|
"invoke",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/invoke/MethodHandle",
|
||||||
|
"invokeBasic",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/invoke/MethodHandle",
|
||||||
|
"linkToVirtual",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/invoke/MethodHandle",
|
||||||
|
"linkToStatic",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/invoke/MethodHandle",
|
||||||
|
"linkToSpecial",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/invoke/MethodHandle",
|
||||||
|
"linkToInterface",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/invoke/MethodHandle",
|
||||||
|
"linkToNative",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 1, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Object".to_string())},
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/CDS",
|
||||||
|
"getCDSConfigStatus",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() },
|
||||||
|
},
|
||||||
|
JdkInternalMiscCDS::get_cds_config_status
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/CDS",
|
||||||
|
"logLambdaFormInvoker",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/CDS",
|
||||||
|
"initializeFromArchive",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/Class".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||||
|
},
|
||||||
|
ignore_call // TODO: idk
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/CDS",
|
||||||
|
"defineArchivedModules",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/ClassLoader".to_string())},
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/ClassLoader".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/CDS",
|
||||||
|
"getRandomSeedForDumping",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() },
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/CDS",
|
||||||
|
"dumpClassList",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/CDS",
|
||||||
|
"dumpDynamicArchive",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (classname, methodname, methoddescriptor, binding) in native_mappings {
|
for (classname, methodname, methoddescriptor, binding) in native_mappings {
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub enum StackValue {
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Byte(i8),
|
Byte(i8),
|
||||||
Char(u16),
|
Char(u16),
|
||||||
Short(u16),
|
Short(i16),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Float(f32),
|
Float(f32),
|
||||||
Reference(ObjectReference),
|
Reference(ObjectReference),
|
||||||
|
@ -47,6 +47,10 @@ impl OperandStack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) -> () {
|
||||||
|
self.depth = 0
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, value: StackValue) -> Result<(), Error> {
|
pub fn push(&mut self, value: StackValue) -> Result<(), Error> {
|
||||||
if self.depth as usize == self.stack.len() {
|
if self.depth as usize == self.stack.len() {
|
||||||
return Err(Error::PushError(format!("Trying to push onto full operand stack, capacity: {}, value: {:?}", self.depth, value)))
|
return Err(Error::PushError(format!("Trying to push onto full operand stack, capacity: {}, value: {:?}", self.depth, value)))
|
||||||
|
@ -98,9 +102,15 @@ impl OperandStack {
|
||||||
self.push_long(l)
|
self.push_long(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
FieldValue::Char(c) => {
|
||||||
println!("{value:?}");
|
self.push(StackValue::Char(c))
|
||||||
todo!();
|
}
|
||||||
|
|
||||||
|
FieldValue::Short(s) => {
|
||||||
|
self.push(StackValue::Short(s))
|
||||||
|
}
|
||||||
|
FieldValue::Double(d) => {
|
||||||
|
self.push_double(d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +197,7 @@ impl OperandStack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pop_short(&mut self, index: usize) -> Result<u16, Error> {
|
pub fn pop_short(&mut self, index: usize) -> Result<i16, Error> {
|
||||||
let absolute_index = self.depth as usize - 1 - index;
|
let absolute_index = self.depth as usize - 1 - index;
|
||||||
let value = self.stack[absolute_index];
|
let value = self.stack[absolute_index];
|
||||||
self.depth -= 1;
|
self.depth -= 1;
|
||||||
|
@ -214,6 +224,7 @@ impl OperandStack {
|
||||||
match value {
|
match value {
|
||||||
StackValue::Int(i) => Ok(i),
|
StackValue::Int(i) => Ok(i),
|
||||||
StackValue::Byte(b) => Ok(b as i32),
|
StackValue::Byte(b) => Ok(b as i32),
|
||||||
|
StackValue::Char(c) => Ok(c as i32),
|
||||||
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Int-compatible but found '{:?}'", index, value)))
|
_ => Err(Error::LocalError(format!("Mismatched type at index {} of the function operand stack, expected Int-compatible but found '{:?}'", index, value)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue