fixed cp entry indices

This commit is contained in:
Sander Hautvast 2023-09-26 14:54:42 +02:00
parent 2f739cb4db
commit 6bad19c244
5 changed files with 49 additions and 35 deletions

Binary file not shown.

View file

@ -1,6 +1,8 @@
public class Dummy {
public static int get(){
return 42;
private final static double answer = 42.0;
public static double get(){
return answer;
}
}

View file

@ -11,10 +11,14 @@ pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
check_magic(&bytecode);
let constant_pool_count = read_u16(&bytecode, 8);
// println!("cp count: {}", constant_pool_count);
let mut index = 10;
let mut constant_pool: Vec<CpEntry> = vec![];
for cp_index in 0..constant_pool_count - 1 {
constant_pool.push(read_constant_pool_entry((cp_index + 1) as usize, &mut index, &bytecode));
let mut constant_pool: HashMap<usize, CpEntry> = HashMap::with_capacity(constant_pool_count as usize);
let mut cp_index: usize = 1;
for _ in 1..constant_pool_count - 1
{
constant_pool.insert(cp_index, read_constant_pool_entry(&mut cp_index, &mut index, &bytecode));
cp_index += 1;
}
let constant_pool = Rc::new(constant_pool);
@ -78,68 +82,73 @@ fn check_magic(bytecode: &[u8]) {
}
}
fn read_constant_pool_entry(cp_index: usize, index: &mut usize, bytecode: &[u8]) -> CpEntry {
fn read_constant_pool_entry(cp_index: &mut usize, index: &mut usize, bytecode: &[u8]) -> CpEntry {
let tag = bytecode[*index];
// println!("#{}: {}", cp_index, tag);
match tag {
1 => {
let len = read_u16(bytecode, *index + 1) as usize;
let utf: Vec<u8> = Vec::from(&bytecode[*index + 3..*index + 3 + len]);
*index += len + 3;
CpEntry::Utf8(cp_index, String::from_utf8(utf).unwrap())
CpEntry::Utf8(*cp_index, String::from_utf8(utf).unwrap())
}
3 => {
let value = read_i32(bytecode, *index + 1);
*index += 5;
CpEntry::Integer(cp_index, value)
CpEntry::Integer(*cp_index, value)
}
4 => {
let value = read_f32(bytecode, *index + 1);
*index += 5;
CpEntry::Float(cp_index, value)
CpEntry::Float(*cp_index, value)
}
5 => {
let value = read_i64(bytecode, *index + 1);
*index += 9;
CpEntry::Long(cp_index, value)
let r = CpEntry::Long(*cp_index, value);
*cp_index += 1;
r
}
6 => {
let value = read_f64(bytecode, *index + 1);
*index += 9;
CpEntry::Double(cp_index, value)
let r = CpEntry::Double(*cp_index, value);
*cp_index += 1;
r
}
7 => {
let name_index = read_u16(bytecode, *index + 1);
*index += 3;
CpEntry::ClassRef(cp_index, name_index)
CpEntry::ClassRef(*cp_index, name_index)
}
8 => {
let string_index = read_u16(bytecode, *index + 1);
*index += 3;
CpEntry::StringRef(cp_index, string_index)
CpEntry::StringRef(*cp_index, string_index)
}
9 => {
let class_index = read_u16(bytecode, *index + 1);
let name_and_type_index = read_u16(bytecode, *index + 3);
*index += 5;
CpEntry::Fieldref(cp_index, class_index, name_and_type_index)
CpEntry::Fieldref(*cp_index, class_index, name_and_type_index)
}
10 => {
let class_index = read_u16(bytecode, *index + 1);
let name_and_type_index = read_u16(bytecode, *index + 3);
*index += 5;
CpEntry::MethodRef(cp_index, class_index, name_and_type_index)
CpEntry::MethodRef(*cp_index, class_index, name_and_type_index)
}
11 => {
let class_index = read_u16(bytecode, *index + 1);
let name_and_type_index = read_u16(bytecode, *index + 3);
*index += 5;
CpEntry::InterfaceMethodref(cp_index, class_index, name_and_type_index)
CpEntry::InterfaceMethodref(*cp_index, class_index, name_and_type_index)
}
12 => {
let name_index = read_u16(bytecode, *index + 1) as usize;
let descriptor_index = read_u16(bytecode, *index + 3) as usize;
*index += 5;
CpEntry::NameAndType(cp_index, name_index, descriptor_index)
CpEntry::NameAndType(*cp_index, name_index, descriptor_index)
}
// 15 MethodHandle,
// 16 MethodType,
@ -147,11 +156,12 @@ fn read_constant_pool_entry(cp_index: usize, index: &mut usize, bytecode: &[u8])
// 18 InvokeDynamic,
// 19 Module,
// 20 Package,
_ => panic!()
_ => panic!("cp entry type not recognized")
}
}
fn read_field(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Field {
fn read_field(constant_pool: Rc<HashMap<usize, CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Field {
let access_flags = read_u16(bytecode, *index);
let name_index = read_u16(bytecode, *index + 2) as usize;
let descriptor_index = read_u16(bytecode, *index + 4) as usize;
@ -162,7 +172,7 @@ fn read_field(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8
if let Some(att) = read_attribute(constant_pool.clone(), bytecode, index) {
attributes.insert(att.0, att.1);
} else {
panic!(); // bug/not-implemented
panic!("attribute not recognized"); // bug/not-implemented
}
}
Field::new(
@ -174,7 +184,7 @@ fn read_field(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8
)
}
fn read_method(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Method {
fn read_method(constant_pool: Rc<HashMap<usize, CpEntry>>, index: &mut usize, bytecode: &[u8]) -> Method {
let access_flags = read_u16(bytecode, *index);
let name_index = read_u16(bytecode, *index + 2) as usize;
let descriptor_index = read_u16(bytecode, *index + 4) as usize;
@ -197,7 +207,7 @@ fn read_method(constant_pool: Rc<Vec<CpEntry>>, index: &mut usize, bytecode: &[u
)
}
fn read_attribute(constant_pool: Rc<Vec<CpEntry>>, bytecode: &[u8], index: &mut usize) -> Option<(String, AttributeType)> {
fn read_attribute(constant_pool: Rc<HashMap<usize, CpEntry>>, bytecode: &[u8], index: &mut usize) -> Option<(String, AttributeType)> {
let attribute_name_index = read_u16(bytecode, *index) as usize;
*index += 2;
let attribute_length = read_u32(bytecode, *index) as usize;
@ -206,8 +216,8 @@ fn read_attribute(constant_pool: Rc<Vec<CpEntry>>, bytecode: &[u8], index: &mut
*index += attribute_length;
if let CpEntry::Utf8(_, s) = &constant_pool[attribute_name_index - 1] {
// println!("{}", s);
if let CpEntry::Utf8(_, s) = &constant_pool.get(&attribute_name_index).unwrap() {
// println!("Att [{}]", s);
return match s.as_str() {
"ConstantValue" => {
assert_eq!(info.len(), 2);
@ -237,6 +247,7 @@ fn read_attribute(constant_pool: Rc<Vec<CpEntry>>, bytecode: &[u8], index: &mut
Some(("Code".into(), AttributeType::Code(MethodCode::new(max_stack, max_locals, code, exception_table, code_attributes))))
}
"SourceFile" => Some(("SourceFile".into(), AttributeType::SourceFile)),
"LineNumberTable" => Some(("SourceFile".into(), AttributeType::LineNumberTable)),
_ => None
};
}

View file

@ -4,6 +4,7 @@ use std::io::Read;
fn main() {
let bytecode = read_class_file("./Dummy.class");
if let Some(class) = classfile_reader::get_class(bytecode){
println!("{:?}", class);
let ret = class.execute("public static get()I");
println!("{:?}", ret);
}

View file

@ -7,7 +7,7 @@ use crate::{CpEntry, opcodes};
pub struct Class {
pub minor_version: u16,
pub major_version: u16,
pub constant_pool: Rc<Vec<CpEntry>>,
pub constant_pool: Rc<HashMap<usize, CpEntry>>,
pub access_flags: u16,
pub this_class: u16,
pub super_class: u16,
@ -29,7 +29,7 @@ impl Class {
}
pub struct Method {
constant_pool: Rc<Vec<CpEntry>>,
constant_pool: Rc<HashMap<usize, CpEntry>>,
access_flags: u16,
name_index: usize,
descriptor_index: usize,
@ -44,7 +44,7 @@ impl fmt::Debug for Method {
}
impl Method {
pub fn new(constant_pool: Rc<Vec<CpEntry>>,
pub fn new(constant_pool: Rc<HashMap<usize, CpEntry>>,
access_flags: u16,
name_index: usize,
descriptor_index: usize,
@ -54,10 +54,10 @@ impl Method {
pub fn name(&self) -> String {
let mut full_name = get_modifier(self.access_flags);
if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.name_index - 1] {
if let CpEntry::Utf8(_, s) = &self.constant_pool.get(&self.name_index).unwrap() {
full_name.push_str(s);
}
if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.descriptor_index - 1] {
if let CpEntry::Utf8(_, s) = &self.constant_pool.get(&self.descriptor_index).unwrap() {
full_name.push_str(s);
}
@ -76,10 +76,10 @@ impl Method {
pc += 1;
let c = code.opcodes[pc] as i32;
stack.push(Value::I32(c));
},
}
&opcodes::ireturn => {
return stack.pop();
},
}
//TODO implement all opcodes
_ => {}
}
@ -91,7 +91,7 @@ impl Method {
}
pub struct Field {
constant_pool: Rc<Vec<CpEntry>>,
constant_pool: Rc<HashMap<usize, CpEntry>>,
access_flags: u16,
name_index: usize,
descriptor_index: usize,
@ -110,7 +110,7 @@ impl fmt::Debug for Field {
}
impl Field {
pub fn new(constant_pool: Rc<Vec<CpEntry>>,
pub fn new(constant_pool: Rc<HashMap<usize, CpEntry>>,
access_flags: u16,
name_index: usize,
descriptor_index: usize,
@ -121,11 +121,11 @@ impl Field {
pub fn name(&self) -> String {
let mut full_name = get_modifier(self.access_flags);
if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.descriptor_index - 1] {
if let CpEntry::Utf8(_, s) = &self.constant_pool.get(&self.descriptor_index).unwrap() {
full_name.push_str(s);
}
full_name.push(' ');
if let CpEntry::Utf8(_, s) = &self.constant_pool[&self.name_index - 1] {
if let CpEntry::Utf8(_, s) = &self.constant_pool.get(&self.name_index).unwrap() {
full_name.push_str(s);
}