Constant pool fix

This commit is contained in:
VegOwOtenks 2024-08-29 19:32:05 +02:00
parent b751fc3588
commit c1eca63f5a
2 changed files with 134 additions and 54 deletions

View file

@ -53,7 +53,7 @@ pub struct JavaClassFile {
constant_pool: Box<[ConstantPoolInfo]>, constant_pool: Box<[ConstantPoolInfo]>,
access_flags: AccessFlagMask, access_flags: ClassAccessFlagMask,
this_class: u16, this_class: u16,
super_class: u16, super_class: u16,
@ -93,17 +93,24 @@ impl JavaClassFile {
let mut i = 0; let mut i = 0;
while i < constant_pool_size { while i < constant_pool_size {
let cpinfo = ConstantPoolInfo::from_reader(reader)?; let cpinfo = ConstantPoolInfo::from_reader(reader)?;
i += match cpinfo {
ConstantPoolInfo::ConstantDouble(_) | ConstantPoolInfo::ConstantLong(_) => 2, let delta_i = match cpinfo {
ConstantPoolInfo::Double(_) | ConstantPoolInfo::Long(_) => 2,
_ => 1 _ => 1
}; };
constant_pool_vec.push(cpinfo); constant_pool_vec.push(cpinfo);
if delta_i == 2 {
constant_pool_vec.push(ConstantPoolInfo::Nothing());
}
i += delta_i;
} }
constant_pool_vec.into_boxed_slice() constant_pool_vec.into_boxed_slice()
}; };
let access_flags = AccessFlagMask { mask: read_u16(reader)? }; let access_flags = ClassAccessFlagMask { mask: read_u16(reader)? };
let this_class = read_u16(reader)?; let this_class = read_u16(reader)?;
let super_class = read_u16(reader)?; let super_class = read_u16(reader)?;
let interfaces = { let interfaces = {
@ -270,20 +277,21 @@ pub struct ConstantInvokeDynamicInfo {
#[derive(Debug)] #[derive(Debug)]
#[repr(u8)] #[repr(u8)]
pub enum ConstantPoolInfo { pub enum ConstantPoolInfo {
ConstantClass(ConstantClassInfo) = 7, Class(ConstantClassInfo) = 7,
ConstantFieldRef(ConstantFieldRefInfo) = 9, FieldRef(ConstantFieldRefInfo) = 9,
ConstantMethodRef(ConstantMethodRefInfo) = 10, MethodRef(ConstantMethodRefInfo) = 10,
ConstantInterfaceMethodRef(ConstantInterfaceMethodRefInfo) = 11, InterfaceMethodRef(ConstantInterfaceMethodRefInfo) = 11,
ConstantString(ConstantStringInfo) = 8, String(ConstantStringInfo) = 8,
ConstantInteger(ConstantIntegerInfo) = 3, Integer(ConstantIntegerInfo) = 3,
ConstantFloat(ConstantFloatInfo) = 4, Float(ConstantFloatInfo) = 4,
ConstantLong(ConstantLongInfo) = 5, Long(ConstantLongInfo) = 5,
ConstantDouble(ConstantDoubleInfo) = 6, Double(ConstantDoubleInfo) = 6,
ConstantNameAndType(ConstantNameAndTypeInfo) = 12, NameAndType(ConstantNameAndTypeInfo) = 12,
ConstantUtf8(ConstantUtf8Info) = 1, Utf8(ConstantUtf8Info) = 1,
ConstantMethodHandle(ConstantMethodHandleInfo) = 15, MethodHandle(ConstantMethodHandleInfo) = 15,
ConstantMethodType(ConstantMethodTypeInfo) = 16, MethodType(ConstantMethodTypeInfo) = 16,
ConstantInvokeDynamic(ConstantInvokeDynamicInfo) = 18, InvokeDynamic(ConstantInvokeDynamicInfo) = 18,
Nothing() = 255,
} }
impl ConstantPoolInfo { impl ConstantPoolInfo {
@ -294,7 +302,7 @@ impl ConstantPoolInfo {
match tag { match tag {
1 => { 1 => {
ConstantPoolInfo::ConstantUtf8( ConstantPoolInfo::Utf8(
ConstantUtf8Info { ConstantUtf8Info {
utf8: { utf8: {
let length = read_u16(reader)?; let length = read_u16(reader)?;
@ -309,7 +317,7 @@ impl ConstantPoolInfo {
} }
3 => { 3 => {
ConstantPoolInfo::ConstantInteger( ConstantPoolInfo::Integer(
ConstantIntegerInfo { ConstantIntegerInfo {
value: read_i32(reader)? value: read_i32(reader)?
} }
@ -317,7 +325,7 @@ impl ConstantPoolInfo {
} }
4 => { 4 => {
ConstantPoolInfo::ConstantFloat( ConstantPoolInfo::Float(
ConstantFloatInfo { ConstantFloatInfo {
value: read_f32(reader)? value: read_f32(reader)?
} }
@ -325,7 +333,7 @@ impl ConstantPoolInfo {
} }
5 => { 5 => {
ConstantPoolInfo::ConstantLong( ConstantPoolInfo::Long(
ConstantLongInfo { ConstantLongInfo {
value: read_u64(reader)? value: read_u64(reader)?
} }
@ -333,7 +341,7 @@ impl ConstantPoolInfo {
} }
6 => { 6 => {
ConstantPoolInfo::ConstantDouble( ConstantPoolInfo::Double(
ConstantDoubleInfo { ConstantDoubleInfo {
value: read_f64(reader)? value: read_f64(reader)?
} }
@ -341,7 +349,7 @@ impl ConstantPoolInfo {
} }
7 => { 7 => {
ConstantPoolInfo::ConstantClass( ConstantPoolInfo::Class(
ConstantClassInfo { ConstantClassInfo {
name_index: read_u16(reader)? name_index: read_u16(reader)?
} }
@ -349,7 +357,7 @@ impl ConstantPoolInfo {
} }
8 => { 8 => {
ConstantPoolInfo::ConstantString( ConstantPoolInfo::String(
ConstantStringInfo { ConstantStringInfo {
string_index: read_u16(reader)? string_index: read_u16(reader)?
} }
@ -357,7 +365,7 @@ impl ConstantPoolInfo {
} }
9 => { 9 => {
ConstantPoolInfo::ConstantFieldRef( ConstantPoolInfo::FieldRef(
ConstantFieldRefInfo { ConstantFieldRefInfo {
class_index: read_u16(reader)?, class_index: read_u16(reader)?,
name_and_type_index: read_u16(reader)? name_and_type_index: read_u16(reader)?
@ -366,7 +374,7 @@ impl ConstantPoolInfo {
} }
10 => { 10 => {
ConstantPoolInfo::ConstantMethodRef( ConstantPoolInfo::MethodRef(
ConstantMethodRefInfo { ConstantMethodRefInfo {
class_index: read_u16(reader)?, class_index: read_u16(reader)?,
name_and_type_index: read_u16(reader)? name_and_type_index: read_u16(reader)?
@ -375,7 +383,7 @@ impl ConstantPoolInfo {
} }
11 => { 11 => {
ConstantPoolInfo::ConstantInterfaceMethodRef( ConstantPoolInfo::InterfaceMethodRef(
ConstantInterfaceMethodRefInfo { ConstantInterfaceMethodRefInfo {
class_index: read_u16(reader)?, class_index: read_u16(reader)?,
name_and_type_index: read_u16(reader)? name_and_type_index: read_u16(reader)?
@ -384,7 +392,7 @@ impl ConstantPoolInfo {
} }
12 => { 12 => {
ConstantPoolInfo::ConstantNameAndType( ConstantPoolInfo::NameAndType(
ConstantNameAndTypeInfo { ConstantNameAndTypeInfo {
name_index: read_u16(reader)?, name_index: read_u16(reader)?,
descriptor_index: read_u16(reader)? descriptor_index: read_u16(reader)?
@ -393,7 +401,7 @@ impl ConstantPoolInfo {
} }
15 => { 15 => {
ConstantPoolInfo::ConstantMethodHandle( ConstantPoolInfo::MethodHandle(
ConstantMethodHandleInfo { ConstantMethodHandleInfo {
reference_kind: ConstantMethodHandleType::try_from(read_u8(reader)?)?, reference_kind: ConstantMethodHandleType::try_from(read_u8(reader)?)?,
reference_index: read_u16(reader)?, reference_index: read_u16(reader)?,
@ -402,7 +410,7 @@ impl ConstantPoolInfo {
} }
16 => { 16 => {
ConstantPoolInfo::ConstantMethodType( ConstantPoolInfo::MethodType(
ConstantMethodTypeInfo { ConstantMethodTypeInfo {
descriptor_index: read_u16(reader)?, descriptor_index: read_u16(reader)?,
} }
@ -410,7 +418,7 @@ impl ConstantPoolInfo {
} }
18 => { 18 => {
ConstantPoolInfo::ConstantInvokeDynamic( ConstantPoolInfo::InvokeDynamic(
ConstantInvokeDynamicInfo { ConstantInvokeDynamicInfo {
bootstrap_method_attr_index: read_u16(reader)?, bootstrap_method_attr_index: read_u16(reader)?,
name_and_type_index: read_u16(reader)?, name_and_type_index: read_u16(reader)?,
@ -426,26 +434,27 @@ impl ConstantPoolInfo {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
#[repr(u16)] #[repr(u16)]
pub enum AccessFlag { pub enum FieldAccessFlag {
AccessPublic = 0x0001, // Declared public; may be accessed from outside its package. Public = 0x0001, // Declared public; may be accessed from outside its package.
AccessFinal = 0x0010, // Declared final; no subclasses allowed. Private = 0x0002, // Declared private; accessible only within the defining class and other classes belonging to the same nest (§5.4.4).
AccessSuper = 0x0020, // Treat superclass methods specially when invoked by the invokespecial instruction. Protected = 0x0004, // Declared protected; may be accessed within subclasses.
AccessInterface = 0x0200, // Is an interface, not a class. Static = 0x0008, // Declared static.
AccessAbstract = 0x0400, // Declared abstract; must not be instantiated. Final = 0x0010, // Declared final; never directly assigned to after object construction (JLS §17.5).
AccessSynthetic = 0x1000, // Declared synthetic; not present in the source code. Volatile = 0x0040, // Declared volatile; cannot be cached.
AccessAnnotation = 0x2000, // Declared as an annotation type. Transient = 0x0080, // Declared transient; not written or read by a persistent object manager.
AccessEnum = 0x4000, // Declared as an enum type. Synthetic = 0x1000, // Declared synthetic; not present in the source code.
} Enum = 0x4000, // Declared as an element of an enum class.
}
pub struct AccessFlagMask { pub struct FieldAccessFlagMask {
mask: u16 mask: u16
} }
impl Debug for AccessFlagMask { impl Debug for FieldAccessFlagMask {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
let mut flag_vec = Vec::<AccessFlag>::new(); let mut flag_vec = Vec::new();
let flags = [AccessFlag::AccessPublic,AccessFlag::AccessFinal,AccessFlag::AccessSuper,AccessFlag::AccessInterface,AccessFlag::AccessAbstract,AccessFlag::AccessSynthetic,AccessFlag::AccessAnnotation,AccessFlag::AccessEnum]; let flags = [FieldAccessFlag::Public,FieldAccessFlag::Private,FieldAccessFlag::Protected,FieldAccessFlag::Static,FieldAccessFlag::Final,FieldAccessFlag::Volatile,FieldAccessFlag::Transient,FieldAccessFlag::Synthetic,FieldAccessFlag::Enum,];
for flag in flags { for flag in flags {
if (flag as u16 & self.mask) != 0 { if (flag as u16 & self.mask) != 0 {
@ -460,7 +469,7 @@ impl Debug for AccessFlagMask {
#[derive(Debug)] #[derive(Debug)]
pub struct FieldInfo { pub struct FieldInfo {
access_flags: AccessFlagMask, access_flags: FieldAccessFlagMask,
name_index: u16, name_index: u16,
descriptor_index: u16, descriptor_index: u16,
attributes: Box<[AttributeInfo]>, attributes: Box<[AttributeInfo]>,
@ -470,7 +479,7 @@ impl FieldInfo {
fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>) -> Result<Self, Error> { fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>) -> Result<Self, Error> {
Ok( Ok(
FieldInfo { FieldInfo {
access_flags: AccessFlagMask { mask: read_u16(reader)? }, access_flags: FieldAccessFlagMask { mask: read_u16(reader)? },
name_index: read_u16(reader)?, name_index: read_u16(reader)?,
descriptor_index: read_u16(reader)?, descriptor_index: read_u16(reader)?,
attributes: AttributeInfo::array_from_reader(reader, pool, true)?, attributes: AttributeInfo::array_from_reader(reader, pool, true)?,
@ -731,7 +740,7 @@ impl AttributeInfo {
let data = { let data = {
let name_entry = &pool[attribute_name_index as usize]; let name_entry = &pool[attribute_name_index as usize];
let utf8 = match name_entry { let utf8 = match name_entry {
ConstantPoolInfo::ConstantUtf8( ConstantUtf8Info { utf8 } ) => utf8, ConstantPoolInfo::Utf8( ConstantUtf8Info { utf8 } ) => utf8,
_ => return Err(Error::BadFileError(format!("Bad name index for attribute info: {}", attribute_name_index))), _ => return Err(Error::BadFileError(format!("Bad name index for attribute info: {}", attribute_name_index))),
}; };
@ -781,7 +790,7 @@ impl AttributeInfo {
#[derive(Debug)] #[derive(Debug)]
pub struct MethodInfo { pub struct MethodInfo {
access_flags: AccessFlagMask, access_flags: MethodAccessFlagMask,
name_index: u16, name_index: u16,
descriptor_index: u16, descriptor_index: u16,
attributes: Box<[AttributeInfo]>, attributes: Box<[AttributeInfo]>,
@ -791,7 +800,7 @@ impl MethodInfo {
fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>) -> Result<Self, Error> { fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>) -> Result<Self, Error> {
Ok( Ok(
MethodInfo { MethodInfo {
access_flags: AccessFlagMask { mask: read_u16(reader)? }, access_flags: MethodAccessFlagMask { mask: read_u16(reader)? },
name_index: read_u16(reader)?, name_index: read_u16(reader)?,
descriptor_index: read_u16(reader)?, descriptor_index: read_u16(reader)?,
attributes: AttributeInfo::array_from_reader(reader, pool, true)? attributes: AttributeInfo::array_from_reader(reader, pool, true)?
@ -800,6 +809,77 @@ impl MethodInfo {
} }
} }
#[derive(Debug, Copy, Clone)]
pub enum MethodAccessFlag {
Public = 0x0001, // Declared public; may be accessed from outside its package.
Private = 0x0002, // Declared private; accessible only within the defining class and other classes belonging to the same nest (§5.4.4).
Protected = 0x0004, // Declared protected; may be accessed within subclasses.
Static = 0x0008, // Declared static.
Final = 0x0010, // Declared final; must not be overridden (§5.4.5).
Synchronized = 0x0020, // Declared synchronized; invocation is wrapped by a monitor use.
Bridge = 0x0040, // A bridge method, generated by the compiler.
Varargs = 0x0080, // Declared with variable number of arguments.
Native = 0x0100, // Declared native; implemented in a language other than the Java programming language.
Abstract = 0x0400, // Declared abstract; no implementation is provided.
Strict = 0x0800, // In a class file whose major version number is at least 46 and at most 60: Declared strictfp.
Synthetic = 0x1000, // Declared synthetic; not present in the source code.
}
pub struct MethodAccessFlagMask {
mask: u16,
}
impl Debug for MethodAccessFlagMask {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
let mut flag_vec = Vec::new();
let flags = [MethodAccessFlag::Public,MethodAccessFlag::Private,MethodAccessFlag::Protected,MethodAccessFlag::Static,MethodAccessFlag::Final,MethodAccessFlag::Synchronized,MethodAccessFlag::Bridge,MethodAccessFlag::Varargs,MethodAccessFlag::Native,MethodAccessFlag::Abstract,MethodAccessFlag::Strict,MethodAccessFlag::Synthetic];
for flag in flags {
if (flag as u16 & self.mask) != 0 {
flag_vec.push(flag)
}
}
f.debug_list().entries(flag_vec)
.finish()
}
}
#[derive(Debug, Copy, Clone)]
pub enum ClassAccessFlag {
Public = 0x0001, // Declared public; may be accessed from outside its package.
Final = 0x0010, // Declared final; no subclasses allowed.
Super = 0x0020, // Treat superclass methods specially when invoked by the invokespecial instruction.
Interface = 0x0200, // Is an interface, not a class.
Abstract = 0x0400, // Declared abstract; must not be instantiated.
Synthetic = 0x1000, // Declared synthetic; not present in the source code.
Annotation = 0x2000, // Declared as an annotation interface.
Enum = 0x4000, // Declared as an enum class.
Module = 0x8000, // Is a module, not a class or interface.
}
pub struct ClassAccessFlagMask {
mask: u16,
}
impl Debug for ClassAccessFlagMask {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
let mut flag_vec = Vec::new();
let flags = [ClassAccessFlag::Public,ClassAccessFlag::Final,ClassAccessFlag::Super,ClassAccessFlag::Interface,ClassAccessFlag::Abstract,ClassAccessFlag::Synthetic,ClassAccessFlag::Annotation,ClassAccessFlag::Enum,ClassAccessFlag::Module];
for flag in flags {
if (flag as u16 & self.mask) != 0 {
flag_vec.push(flag)
}
}
f.debug_list().entries(flag_vec)
.finish()
}
}
fn read_buffer(reader: &mut dyn Read, size: usize) -> Result<Box<[u8]>, Error> { fn read_buffer(reader: &mut dyn Read, size: usize) -> Result<Box<[u8]>, Error> {
let mut buffer: Box<[u8]> = vec![0; size].into_boxed_slice(); let mut buffer: Box<[u8]> = vec![0; size].into_boxed_slice();

View file

@ -4,7 +4,7 @@ mod classfile;
mod bytecode; mod bytecode;
fn main() { fn main() {
let class_file = classfile::JavaClassFile::new(&mut File::open("class/HashMap.class").unwrap()).unwrap(); let class_file = classfile::JavaClassFile::new(&mut File::open("class/Enumerator$EnumeratorIterator.class").unwrap()).unwrap();
println!("{:#?}", class_file); println!("{:#?}", class_file);
} }