fixed cp entry indices
This commit is contained in:
parent
2f739cb4db
commit
6bad19c244
5 changed files with 49 additions and 35 deletions
BIN
Dummy.class
BIN
Dummy.class
Binary file not shown.
|
|
@ -1,6 +1,8 @@
|
||||||
public class Dummy {
|
public class Dummy {
|
||||||
|
|
||||||
public static int get(){
|
private final static double answer = 42.0;
|
||||||
return 42;
|
|
||||||
|
public static double get(){
|
||||||
|
return answer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
55
src/lib.rs
55
src/lib.rs
|
|
@ -11,10 +11,14 @@ pub fn get_class(bytecode: Vec<u8>) -> Option<Class> {
|
||||||
check_magic(&bytecode);
|
check_magic(&bytecode);
|
||||||
|
|
||||||
let constant_pool_count = read_u16(&bytecode, 8);
|
let constant_pool_count = read_u16(&bytecode, 8);
|
||||||
|
// println!("cp count: {}", constant_pool_count);
|
||||||
let mut index = 10;
|
let mut index = 10;
|
||||||
let mut constant_pool: Vec<CpEntry> = vec![];
|
let mut constant_pool: HashMap<usize, CpEntry> = HashMap::with_capacity(constant_pool_count as usize);
|
||||||
for cp_index in 0..constant_pool_count - 1 {
|
let mut cp_index: usize = 1;
|
||||||
constant_pool.push(read_constant_pool_entry((cp_index + 1) as usize, &mut index, &bytecode));
|
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);
|
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];
|
let tag = bytecode[*index];
|
||||||
|
// println!("#{}: {}", cp_index, tag);
|
||||||
match tag {
|
match tag {
|
||||||
1 => {
|
1 => {
|
||||||
let len = read_u16(bytecode, *index + 1) as usize;
|
let len = read_u16(bytecode, *index + 1) as usize;
|
||||||
let utf: Vec<u8> = Vec::from(&bytecode[*index + 3..*index + 3 + len]);
|
let utf: Vec<u8> = Vec::from(&bytecode[*index + 3..*index + 3 + len]);
|
||||||
*index += len + 3;
|
*index += len + 3;
|
||||||
CpEntry::Utf8(cp_index, String::from_utf8(utf).unwrap())
|
CpEntry::Utf8(*cp_index, String::from_utf8(utf).unwrap())
|
||||||
}
|
}
|
||||||
3 => {
|
3 => {
|
||||||
let value = read_i32(bytecode, *index + 1);
|
let value = read_i32(bytecode, *index + 1);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::Integer(cp_index, value)
|
CpEntry::Integer(*cp_index, value)
|
||||||
}
|
}
|
||||||
4 => {
|
4 => {
|
||||||
let value = read_f32(bytecode, *index + 1);
|
let value = read_f32(bytecode, *index + 1);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::Float(cp_index, value)
|
CpEntry::Float(*cp_index, value)
|
||||||
}
|
}
|
||||||
5 => {
|
5 => {
|
||||||
let value = read_i64(bytecode, *index + 1);
|
let value = read_i64(bytecode, *index + 1);
|
||||||
*index += 9;
|
*index += 9;
|
||||||
CpEntry::Long(cp_index, value)
|
let r = CpEntry::Long(*cp_index, value);
|
||||||
|
*cp_index += 1;
|
||||||
|
r
|
||||||
}
|
}
|
||||||
6 => {
|
6 => {
|
||||||
let value = read_f64(bytecode, *index + 1);
|
let value = read_f64(bytecode, *index + 1);
|
||||||
*index += 9;
|
*index += 9;
|
||||||
CpEntry::Double(cp_index, value)
|
let r = CpEntry::Double(*cp_index, value);
|
||||||
|
*cp_index += 1;
|
||||||
|
r
|
||||||
}
|
}
|
||||||
7 => {
|
7 => {
|
||||||
let name_index = read_u16(bytecode, *index + 1);
|
let name_index = read_u16(bytecode, *index + 1);
|
||||||
*index += 3;
|
*index += 3;
|
||||||
CpEntry::ClassRef(cp_index, name_index)
|
CpEntry::ClassRef(*cp_index, name_index)
|
||||||
}
|
}
|
||||||
8 => {
|
8 => {
|
||||||
let string_index = read_u16(bytecode, *index + 1);
|
let string_index = read_u16(bytecode, *index + 1);
|
||||||
*index += 3;
|
*index += 3;
|
||||||
CpEntry::StringRef(cp_index, string_index)
|
CpEntry::StringRef(*cp_index, string_index)
|
||||||
}
|
}
|
||||||
9 => {
|
9 => {
|
||||||
let class_index = read_u16(bytecode, *index + 1);
|
let class_index = read_u16(bytecode, *index + 1);
|
||||||
let name_and_type_index = read_u16(bytecode, *index + 3);
|
let name_and_type_index = read_u16(bytecode, *index + 3);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::Fieldref(cp_index, class_index, name_and_type_index)
|
CpEntry::Fieldref(*cp_index, class_index, name_and_type_index)
|
||||||
}
|
}
|
||||||
10 => {
|
10 => {
|
||||||
let class_index = read_u16(bytecode, *index + 1);
|
let class_index = read_u16(bytecode, *index + 1);
|
||||||
let name_and_type_index = read_u16(bytecode, *index + 3);
|
let name_and_type_index = read_u16(bytecode, *index + 3);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::MethodRef(cp_index, class_index, name_and_type_index)
|
CpEntry::MethodRef(*cp_index, class_index, name_and_type_index)
|
||||||
}
|
}
|
||||||
11 => {
|
11 => {
|
||||||
let class_index = read_u16(bytecode, *index + 1);
|
let class_index = read_u16(bytecode, *index + 1);
|
||||||
let name_and_type_index = read_u16(bytecode, *index + 3);
|
let name_and_type_index = read_u16(bytecode, *index + 3);
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::InterfaceMethodref(cp_index, class_index, name_and_type_index)
|
CpEntry::InterfaceMethodref(*cp_index, class_index, name_and_type_index)
|
||||||
}
|
}
|
||||||
12 => {
|
12 => {
|
||||||
let name_index = read_u16(bytecode, *index + 1) as usize;
|
let name_index = read_u16(bytecode, *index + 1) as usize;
|
||||||
let descriptor_index = read_u16(bytecode, *index + 3) as usize;
|
let descriptor_index = read_u16(bytecode, *index + 3) as usize;
|
||||||
*index += 5;
|
*index += 5;
|
||||||
CpEntry::NameAndType(cp_index, name_index, descriptor_index)
|
CpEntry::NameAndType(*cp_index, name_index, descriptor_index)
|
||||||
}
|
}
|
||||||
// 15 MethodHandle,
|
// 15 MethodHandle,
|
||||||
// 16 MethodType,
|
// 16 MethodType,
|
||||||
|
|
@ -147,11 +156,12 @@ fn read_constant_pool_entry(cp_index: usize, index: &mut usize, bytecode: &[u8])
|
||||||
// 18 InvokeDynamic,
|
// 18 InvokeDynamic,
|
||||||
// 19 Module,
|
// 19 Module,
|
||||||
// 20 Package,
|
// 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 access_flags = read_u16(bytecode, *index);
|
||||||
let name_index = read_u16(bytecode, *index + 2) as usize;
|
let name_index = read_u16(bytecode, *index + 2) as usize;
|
||||||
let descriptor_index = read_u16(bytecode, *index + 4) 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) {
|
if let Some(att) = read_attribute(constant_pool.clone(), bytecode, index) {
|
||||||
attributes.insert(att.0, att.1);
|
attributes.insert(att.0, att.1);
|
||||||
} else {
|
} else {
|
||||||
panic!(); // bug/not-implemented
|
panic!("attribute not recognized"); // bug/not-implemented
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Field::new(
|
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 access_flags = read_u16(bytecode, *index);
|
||||||
let name_index = read_u16(bytecode, *index + 2) as usize;
|
let name_index = read_u16(bytecode, *index + 2) as usize;
|
||||||
let descriptor_index = read_u16(bytecode, *index + 4) 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;
|
let attribute_name_index = read_u16(bytecode, *index) as usize;
|
||||||
*index += 2;
|
*index += 2;
|
||||||
let attribute_length = read_u32(bytecode, *index) as usize;
|
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;
|
*index += attribute_length;
|
||||||
|
|
||||||
|
|
||||||
if let CpEntry::Utf8(_, s) = &constant_pool[attribute_name_index - 1] {
|
if let CpEntry::Utf8(_, s) = &constant_pool.get(&attribute_name_index).unwrap() {
|
||||||
// println!("{}", s);
|
// println!("Att [{}]", s);
|
||||||
return match s.as_str() {
|
return match s.as_str() {
|
||||||
"ConstantValue" => {
|
"ConstantValue" => {
|
||||||
assert_eq!(info.len(), 2);
|
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))))
|
Some(("Code".into(), AttributeType::Code(MethodCode::new(max_stack, max_locals, code, exception_table, code_attributes))))
|
||||||
}
|
}
|
||||||
"SourceFile" => Some(("SourceFile".into(), AttributeType::SourceFile)),
|
"SourceFile" => Some(("SourceFile".into(), AttributeType::SourceFile)),
|
||||||
|
"LineNumberTable" => Some(("SourceFile".into(), AttributeType::LineNumberTable)),
|
||||||
_ => None
|
_ => None
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use std::io::Read;
|
||||||
fn main() {
|
fn main() {
|
||||||
let bytecode = read_class_file("./Dummy.class");
|
let bytecode = read_class_file("./Dummy.class");
|
||||||
if let Some(class) = classfile_reader::get_class(bytecode){
|
if let Some(class) = classfile_reader::get_class(bytecode){
|
||||||
|
println!("{:?}", class);
|
||||||
let ret = class.execute("public static get()I");
|
let ret = class.execute("public static get()I");
|
||||||
println!("{:?}", ret);
|
println!("{:?}", ret);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
src/types.rs
22
src/types.rs
|
|
@ -7,7 +7,7 @@ use crate::{CpEntry, opcodes};
|
||||||
pub struct Class {
|
pub struct Class {
|
||||||
pub minor_version: u16,
|
pub minor_version: u16,
|
||||||
pub major_version: u16,
|
pub major_version: u16,
|
||||||
pub constant_pool: Rc<Vec<CpEntry>>,
|
pub constant_pool: Rc<HashMap<usize, CpEntry>>,
|
||||||
pub access_flags: u16,
|
pub access_flags: u16,
|
||||||
pub this_class: u16,
|
pub this_class: u16,
|
||||||
pub super_class: u16,
|
pub super_class: u16,
|
||||||
|
|
@ -29,7 +29,7 @@ impl Class {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Method {
|
pub struct Method {
|
||||||
constant_pool: Rc<Vec<CpEntry>>,
|
constant_pool: Rc<HashMap<usize, CpEntry>>,
|
||||||
access_flags: u16,
|
access_flags: u16,
|
||||||
name_index: usize,
|
name_index: usize,
|
||||||
descriptor_index: usize,
|
descriptor_index: usize,
|
||||||
|
|
@ -44,7 +44,7 @@ impl fmt::Debug for Method {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Method {
|
impl Method {
|
||||||
pub fn new(constant_pool: Rc<Vec<CpEntry>>,
|
pub fn new(constant_pool: Rc<HashMap<usize, CpEntry>>,
|
||||||
access_flags: u16,
|
access_flags: u16,
|
||||||
name_index: usize,
|
name_index: usize,
|
||||||
descriptor_index: usize,
|
descriptor_index: usize,
|
||||||
|
|
@ -54,10 +54,10 @@ impl Method {
|
||||||
|
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> String {
|
||||||
let mut full_name = get_modifier(self.access_flags);
|
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);
|
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);
|
full_name.push_str(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,10 +76,10 @@ impl Method {
|
||||||
pc += 1;
|
pc += 1;
|
||||||
let c = code.opcodes[pc] as i32;
|
let c = code.opcodes[pc] as i32;
|
||||||
stack.push(Value::I32(c));
|
stack.push(Value::I32(c));
|
||||||
},
|
}
|
||||||
&opcodes::ireturn => {
|
&opcodes::ireturn => {
|
||||||
return stack.pop();
|
return stack.pop();
|
||||||
},
|
}
|
||||||
//TODO implement all opcodes
|
//TODO implement all opcodes
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +91,7 @@ impl Method {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
constant_pool: Rc<Vec<CpEntry>>,
|
constant_pool: Rc<HashMap<usize, CpEntry>>,
|
||||||
access_flags: u16,
|
access_flags: u16,
|
||||||
name_index: usize,
|
name_index: usize,
|
||||||
descriptor_index: usize,
|
descriptor_index: usize,
|
||||||
|
|
@ -110,7 +110,7 @@ impl fmt::Debug for Field {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Field {
|
impl Field {
|
||||||
pub fn new(constant_pool: Rc<Vec<CpEntry>>,
|
pub fn new(constant_pool: Rc<HashMap<usize, CpEntry>>,
|
||||||
access_flags: u16,
|
access_flags: u16,
|
||||||
name_index: usize,
|
name_index: usize,
|
||||||
descriptor_index: usize,
|
descriptor_index: usize,
|
||||||
|
|
@ -121,11 +121,11 @@ impl Field {
|
||||||
pub fn name(&self) -> String {
|
pub fn name(&self) -> String {
|
||||||
let mut full_name = get_modifier(self.access_flags);
|
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_str(s);
|
||||||
}
|
}
|
||||||
full_name.push(' ');
|
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);
|
full_name.push_str(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue