Preload java/lang/ref/Reference
This commit is contained in:
parent
5cf17d5ca3
commit
c4da80f23c
4 changed files with 173 additions and 9 deletions
|
@ -246,6 +246,7 @@ impl Bytecode {
|
||||||
}
|
}
|
||||||
0xAC => (Instruction::ReturnInt(), 1),
|
0xAC => (Instruction::ReturnInt(), 1),
|
||||||
0xAD => (Instruction::ReturnLong(), 1),
|
0xAD => (Instruction::ReturnLong(), 1),
|
||||||
|
0xAE => (Instruction::ReturnFloat(), 1),
|
||||||
0xAF => (Instruction::ReturnDouble(), 1),
|
0xAF => (Instruction::ReturnDouble(), 1),
|
||||||
|
|
||||||
0xB0 => (Instruction::ReturnReference(), 1),
|
0xB0 => (Instruction::ReturnReference(), 1),
|
||||||
|
@ -454,6 +455,7 @@ pub enum Instruction {
|
||||||
LookupSwitch(i32, Box<[(i32, i32)]>) = 0xAB, // jump based on switch value
|
LookupSwitch(i32, Box<[(i32, i32)]>) = 0xAB, // jump based on switch value
|
||||||
ReturnInt() = 0xAC, // return integer from function
|
ReturnInt() = 0xAC, // return integer from function
|
||||||
ReturnLong() = 0xAD, // return long from function
|
ReturnLong() = 0xAD, // return long from function
|
||||||
|
ReturnFloat() = 0xAE, // return float from function
|
||||||
ReturnDouble() = 0xAF, // return double from function
|
ReturnDouble() = 0xAF, // return double from function
|
||||||
|
|
||||||
ReturnReference() = 0xB0, // return top-ref from current function
|
ReturnReference() = 0xB0, // return top-ref from current function
|
||||||
|
|
|
@ -141,11 +141,15 @@ impl ClassStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn are_types_compatible_0(&self, my_index: usize, other_name: &str) -> bool {
|
pub fn are_types_compatible_0(&self, my_index: usize, other_name: &str) -> bool {
|
||||||
|
if my_index == self.class_idx_from_name(&other_name.to_string()).unwrap() {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
CompatibleTypesIterator::new(my_index, self)
|
CompatibleTypesIterator::new(my_index, self)
|
||||||
.filter(|type_name| *type_name == other_name)
|
.filter(|type_name| *type_name == other_name)
|
||||||
.next()
|
.next()
|
||||||
.is_some()
|
.is_some()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn are_types_compatible(&self, my_type: &AbstractTypeDescription, other_type: &AbstractTypeDescription) -> bool {
|
pub fn are_types_compatible(&self, my_type: &AbstractTypeDescription, other_type: &AbstractTypeDescription) -> bool {
|
||||||
if my_type == other_type { return true; }
|
if my_type == other_type { return true; }
|
||||||
|
|
16
src/jvm.rs
16
src/jvm.rs
|
@ -211,7 +211,8 @@ impl JVM {
|
||||||
attributes: Box::new([]),
|
attributes: Box::new([]),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.class_store.add_class(array_class_file, true).unwrap();
|
let class_index = self.class_store.add_class(array_class_file, true).unwrap();
|
||||||
|
self.class_store.set_class_objectref_by_index(class_index, array_class_object);
|
||||||
|
|
||||||
self.class_store.put_array_class_ref(
|
self.class_store.put_array_class_ref(
|
||||||
array_type_description,
|
array_type_description,
|
||||||
|
@ -509,6 +510,7 @@ impl JVM {
|
||||||
|
|
||||||
JVMCallbackOperation::ThrowException(exception) => {
|
JVMCallbackOperation::ThrowException(exception) => {
|
||||||
let mut is_handler_found = false;
|
let mut is_handler_found = false;
|
||||||
|
let exception_type_index = self.heap_area.object_area.get_object_class_index(exception);
|
||||||
while ! is_handler_found {
|
while ! is_handler_found {
|
||||||
is_handler_found = {
|
is_handler_found = {
|
||||||
let frame = {
|
let frame = {
|
||||||
|
@ -520,7 +522,6 @@ impl JVM {
|
||||||
if method.is_native() {
|
if method.is_native() {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
let exception_type_index = self.heap_area.object_area.get_object_class_index(exception);
|
|
||||||
class.is_method_bytecode_protected(method, frame.instruction_pointer as u16, exception_type_index, &self.class_store)?
|
class.is_method_bytecode_protected(method, frame.instruction_pointer as u16, exception_type_index, &self.class_store)?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2279,6 +2280,17 @@ impl JVM {
|
||||||
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Double(double)));
|
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Double(double)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction::ReturnFloat() => {
|
||||||
|
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
|
||||||
|
(0, AbstractTypeKind::Float()) => (),
|
||||||
|
_ => return Err(Error::OpcodeError(format!("Found opcode '{:?}' on method returning '{:?}'", instruction, method.descriptor.return_type)))
|
||||||
|
}
|
||||||
|
|
||||||
|
let float = wrap_stackframe_error(class, method, frame.operand_stack.pop_float(0))?;
|
||||||
|
|
||||||
|
return Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Float(float)));
|
||||||
|
}
|
||||||
|
|
||||||
Instruction::ReturnInt() => {
|
Instruction::ReturnInt() => {
|
||||||
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
|
match (method.descriptor.return_type.array_level, &method.descriptor.return_type.kind) {
|
||||||
(_, AbstractTypeKind::Byte() | AbstractTypeKind::Boolean()| AbstractTypeKind::Int() | AbstractTypeKind::Char() | AbstractTypeKind::Short()) => (),
|
(_, AbstractTypeKind::Byte() | AbstractTypeKind::Boolean()| AbstractTypeKind::Int() | AbstractTypeKind::Char() | AbstractTypeKind::Short()) => (),
|
||||||
|
|
|
@ -455,6 +455,22 @@ impl JavaLangRuntime {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct JavaLangSignal {}
|
||||||
|
|
||||||
|
impl JavaLangSignal {
|
||||||
|
fn find_signal_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
let frame = {
|
||||||
|
let frame_index = jvm.stack_frames.len() - 1;
|
||||||
|
&mut jvm.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
let string_ref = frame.load_local_reference(0).unwrap();
|
||||||
|
let rust_string = jvm.heap_area.decode_java_string(string_ref, &jvm.class_store);
|
||||||
|
|
||||||
|
// TODO: Actually 'find' signals, HUP, INT and TERM
|
||||||
|
Ok(JVMCallbackOperation::ReturnFrame(FieldValue::Int(-1)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct JavaLangStringUTF16 {}
|
struct JavaLangStringUTF16 {}
|
||||||
|
|
||||||
impl JavaLangStringUTF16 {
|
impl JavaLangStringUTF16 {
|
||||||
|
@ -466,6 +482,64 @@ impl JavaLangStringUTF16 {
|
||||||
struct JavaLangSystem {}
|
struct JavaLangSystem {}
|
||||||
|
|
||||||
impl JavaLangSystem {
|
impl JavaLangSystem {
|
||||||
|
fn register_natives(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
// Load class because it won't be loaded otherwise
|
||||||
|
let frame = {
|
||||||
|
let frame_index = jvm.stack_frames.len() - 1;
|
||||||
|
&mut jvm.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
|
||||||
|
let r#return = match frame.instruction_pointer {
|
||||||
|
0 => {
|
||||||
|
Ok(JVMCallbackOperation::LoadClass("java/lang/ref/Reference".to_string()))
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
Ok(JVMCallbackOperation::InitClass("java/lang/ref/Reference".to_string()))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
Ok(JVMCallbackOperation::PopFrame())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
frame.instruction_pointer += 1;
|
||||||
|
|
||||||
|
return r#return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_err_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
let frame = {
|
||||||
|
let frame_index = jvm.stack_frames.len() - 1;
|
||||||
|
&mut jvm.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
let input_stream = frame.load_local_reference(0).unwrap();
|
||||||
|
|
||||||
|
// TODO: Bypass final
|
||||||
|
jvm.heap_area.static_area.set(
|
||||||
|
&String::from("java/lang/System"),
|
||||||
|
&String::from("err"),
|
||||||
|
FieldValue::Reference(input_stream)
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(JVMCallbackOperation::PopFrame())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_out_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
|
let frame = {
|
||||||
|
let frame_index = jvm.stack_frames.len() - 1;
|
||||||
|
&mut jvm.stack_frames[frame_index]
|
||||||
|
};
|
||||||
|
let input_stream = frame.load_local_reference(0).unwrap();
|
||||||
|
|
||||||
|
// TODO: Bypass final
|
||||||
|
jvm.heap_area.static_area.set(
|
||||||
|
&String::from("java/lang/System"),
|
||||||
|
&String::from("out"),
|
||||||
|
FieldValue::Reference(input_stream)
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(JVMCallbackOperation::PopFrame())
|
||||||
|
}
|
||||||
|
|
||||||
fn set_in_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
fn set_in_0(jvm: &mut JVM) -> Result<JVMCallbackOperation, Error> {
|
||||||
let frame = {
|
let frame = {
|
||||||
let frame_index = jvm.stack_frames.len() - 1;
|
let frame_index = jvm.stack_frames.len() - 1;
|
||||||
|
@ -1604,7 +1678,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
||||||
},
|
},
|
||||||
ignore_call
|
JavaLangSystem::register_natives
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -1628,7 +1702,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
||||||
},
|
},
|
||||||
todo_call
|
JavaLangSystem::set_out_0
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -1640,7 +1714,7 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
]),
|
]),
|
||||||
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void()},
|
||||||
},
|
},
|
||||||
todo_call
|
JavaLangSystem::set_err_0
|
||||||
),
|
),
|
||||||
|
|
||||||
(
|
(
|
||||||
|
@ -3846,6 +3920,78 @@ pub fn function_for(class_name: &str, m: &crate::classfile::MethodInfo) -> Resul
|
||||||
},
|
},
|
||||||
ignore_call
|
ignore_call
|
||||||
),
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/ScopedMemoryAccess",
|
||||||
|
"registerNatives",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||||
|
},
|
||||||
|
ignore_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/ScopedMemoryAccess",
|
||||||
|
"closeScope0",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("jdk/internal/foreign/MemorySessionImpl".to_string())},
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("jdk/internal/misc/ScopedMemoryAccess$ScopedAccessError".to_string())},
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Void() },
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"java/lang/NullPointerException",
|
||||||
|
"getExtendedNPEMessage",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Classname("java/lang/String".to_string()) },
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/Signal",
|
||||||
|
"findSignal0",
|
||||||
|
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::Int() },
|
||||||
|
},
|
||||||
|
JavaLangSignal::find_signal_0
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/Signal",
|
||||||
|
"handle0",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() },
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() },
|
||||||
|
]),
|
||||||
|
return_type: AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Long() },
|
||||||
|
},
|
||||||
|
todo_call
|
||||||
|
),
|
||||||
|
|
||||||
|
(
|
||||||
|
"jdk/internal/misc/Signal",
|
||||||
|
"raise0",
|
||||||
|
MethodDescriptor {
|
||||||
|
argument_types: Box::new([
|
||||||
|
AbstractTypeDescription { array_level: 0, kind: AbstractTypeKind::Int() },
|
||||||
|
]),
|
||||||
|
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 {
|
||||||
|
|
Loading…
Reference in a new issue