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]>,
access_flags: AccessFlagMask,
access_flags: ClassAccessFlagMask,
this_class: u16,
super_class: u16,
@ -93,17 +93,24 @@ impl JavaClassFile {
let mut i = 0;
while i < constant_pool_size {
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
};
constant_pool_vec.push(cpinfo);
if delta_i == 2 {
constant_pool_vec.push(ConstantPoolInfo::Nothing());
}
i += delta_i;
}
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 super_class = read_u16(reader)?;
let interfaces = {
@ -270,20 +277,21 @@ pub struct ConstantInvokeDynamicInfo {
#[derive(Debug)]
#[repr(u8)]
pub enum ConstantPoolInfo {
ConstantClass(ConstantClassInfo) = 7,
ConstantFieldRef(ConstantFieldRefInfo) = 9,
ConstantMethodRef(ConstantMethodRefInfo) = 10,
ConstantInterfaceMethodRef(ConstantInterfaceMethodRefInfo) = 11,
ConstantString(ConstantStringInfo) = 8,
ConstantInteger(ConstantIntegerInfo) = 3,
ConstantFloat(ConstantFloatInfo) = 4,
ConstantLong(ConstantLongInfo) = 5,
ConstantDouble(ConstantDoubleInfo) = 6,
ConstantNameAndType(ConstantNameAndTypeInfo) = 12,
ConstantUtf8(ConstantUtf8Info) = 1,
ConstantMethodHandle(ConstantMethodHandleInfo) = 15,
ConstantMethodType(ConstantMethodTypeInfo) = 16,
ConstantInvokeDynamic(ConstantInvokeDynamicInfo) = 18,
Class(ConstantClassInfo) = 7,
FieldRef(ConstantFieldRefInfo) = 9,
MethodRef(ConstantMethodRefInfo) = 10,
InterfaceMethodRef(ConstantInterfaceMethodRefInfo) = 11,
String(ConstantStringInfo) = 8,
Integer(ConstantIntegerInfo) = 3,
Float(ConstantFloatInfo) = 4,
Long(ConstantLongInfo) = 5,
Double(ConstantDoubleInfo) = 6,
NameAndType(ConstantNameAndTypeInfo) = 12,
Utf8(ConstantUtf8Info) = 1,
MethodHandle(ConstantMethodHandleInfo) = 15,
MethodType(ConstantMethodTypeInfo) = 16,
InvokeDynamic(ConstantInvokeDynamicInfo) = 18,
Nothing() = 255,
}
impl ConstantPoolInfo {
@ -294,7 +302,7 @@ impl ConstantPoolInfo {
match tag {
1 => {
ConstantPoolInfo::ConstantUtf8(
ConstantPoolInfo::Utf8(
ConstantUtf8Info {
utf8: {
let length = read_u16(reader)?;
@ -309,7 +317,7 @@ impl ConstantPoolInfo {
}
3 => {
ConstantPoolInfo::ConstantInteger(
ConstantPoolInfo::Integer(
ConstantIntegerInfo {
value: read_i32(reader)?
}
@ -317,7 +325,7 @@ impl ConstantPoolInfo {
}
4 => {
ConstantPoolInfo::ConstantFloat(
ConstantPoolInfo::Float(
ConstantFloatInfo {
value: read_f32(reader)?
}
@ -325,7 +333,7 @@ impl ConstantPoolInfo {
}
5 => {
ConstantPoolInfo::ConstantLong(
ConstantPoolInfo::Long(
ConstantLongInfo {
value: read_u64(reader)?
}
@ -333,7 +341,7 @@ impl ConstantPoolInfo {
}
6 => {
ConstantPoolInfo::ConstantDouble(
ConstantPoolInfo::Double(
ConstantDoubleInfo {
value: read_f64(reader)?
}
@ -341,7 +349,7 @@ impl ConstantPoolInfo {
}
7 => {
ConstantPoolInfo::ConstantClass(
ConstantPoolInfo::Class(
ConstantClassInfo {
name_index: read_u16(reader)?
}
@ -349,7 +357,7 @@ impl ConstantPoolInfo {
}
8 => {
ConstantPoolInfo::ConstantString(
ConstantPoolInfo::String(
ConstantStringInfo {
string_index: read_u16(reader)?
}
@ -357,7 +365,7 @@ impl ConstantPoolInfo {
}
9 => {
ConstantPoolInfo::ConstantFieldRef(
ConstantPoolInfo::FieldRef(
ConstantFieldRefInfo {
class_index: read_u16(reader)?,
name_and_type_index: read_u16(reader)?
@ -366,7 +374,7 @@ impl ConstantPoolInfo {
}
10 => {
ConstantPoolInfo::ConstantMethodRef(
ConstantPoolInfo::MethodRef(
ConstantMethodRefInfo {
class_index: read_u16(reader)?,
name_and_type_index: read_u16(reader)?
@ -375,7 +383,7 @@ impl ConstantPoolInfo {
}
11 => {
ConstantPoolInfo::ConstantInterfaceMethodRef(
ConstantPoolInfo::InterfaceMethodRef(
ConstantInterfaceMethodRefInfo {
class_index: read_u16(reader)?,
name_and_type_index: read_u16(reader)?
@ -384,7 +392,7 @@ impl ConstantPoolInfo {
}
12 => {
ConstantPoolInfo::ConstantNameAndType(
ConstantPoolInfo::NameAndType(
ConstantNameAndTypeInfo {
name_index: read_u16(reader)?,
descriptor_index: read_u16(reader)?
@ -393,7 +401,7 @@ impl ConstantPoolInfo {
}
15 => {
ConstantPoolInfo::ConstantMethodHandle(
ConstantPoolInfo::MethodHandle(
ConstantMethodHandleInfo {
reference_kind: ConstantMethodHandleType::try_from(read_u8(reader)?)?,
reference_index: read_u16(reader)?,
@ -402,7 +410,7 @@ impl ConstantPoolInfo {
}
16 => {
ConstantPoolInfo::ConstantMethodType(
ConstantPoolInfo::MethodType(
ConstantMethodTypeInfo {
descriptor_index: read_u16(reader)?,
}
@ -410,7 +418,7 @@ impl ConstantPoolInfo {
}
18 => {
ConstantPoolInfo::ConstantInvokeDynamic(
ConstantPoolInfo::InvokeDynamic(
ConstantInvokeDynamicInfo {
bootstrap_method_attr_index: read_u16(reader)?,
name_and_type_index: read_u16(reader)?,
@ -426,26 +434,27 @@ impl ConstantPoolInfo {
#[derive(Debug, Clone, Copy)]
#[repr(u16)]
pub enum AccessFlag {
AccessPublic = 0x0001, // Declared public; may be accessed from outside its package.
AccessFinal = 0x0010, // Declared final; no subclasses allowed.
AccessSuper = 0x0020, // Treat superclass methods specially when invoked by the invokespecial instruction.
AccessInterface = 0x0200, // Is an interface, not a class.
AccessAbstract = 0x0400, // Declared abstract; must not be instantiated.
AccessSynthetic = 0x1000, // Declared synthetic; not present in the source code.
AccessAnnotation = 0x2000, // Declared as an annotation type.
AccessEnum = 0x4000, // Declared as an enum type.
}
pub enum FieldAccessFlag {
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; never directly assigned to after object construction (JLS §17.5).
Volatile = 0x0040, // Declared volatile; cannot be cached.
Transient = 0x0080, // Declared transient; not written or read by a persistent object manager.
Synthetic = 0x1000, // Declared synthetic; not present in the source code.
Enum = 0x4000, // Declared as an element of an enum class.
}
pub struct AccessFlagMask {
mask: u16
}
pub struct FieldAccessFlagMask {
mask: u16
}
impl Debug for AccessFlagMask {
impl Debug for FieldAccessFlagMask {
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 {
if (flag as u16 & self.mask) != 0 {
@ -460,7 +469,7 @@ impl Debug for AccessFlagMask {
#[derive(Debug)]
pub struct FieldInfo {
access_flags: AccessFlagMask,
access_flags: FieldAccessFlagMask,
name_index: u16,
descriptor_index: u16,
attributes: Box<[AttributeInfo]>,
@ -470,7 +479,7 @@ impl FieldInfo {
fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>) -> Result<Self, Error> {
Ok(
FieldInfo {
access_flags: AccessFlagMask { mask: read_u16(reader)? },
access_flags: FieldAccessFlagMask { mask: read_u16(reader)? },
name_index: read_u16(reader)?,
descriptor_index: read_u16(reader)?,
attributes: AttributeInfo::array_from_reader(reader, pool, true)?,
@ -731,7 +740,7 @@ impl AttributeInfo {
let data = {
let name_entry = &pool[attribute_name_index as usize];
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))),
};
@ -781,7 +790,7 @@ impl AttributeInfo {
#[derive(Debug)]
pub struct MethodInfo {
access_flags: AccessFlagMask,
access_flags: MethodAccessFlagMask,
name_index: u16,
descriptor_index: u16,
attributes: Box<[AttributeInfo]>,
@ -791,7 +800,7 @@ impl MethodInfo {
fn from_reader(reader: &mut dyn Read, pool: &Box<[ConstantPoolInfo]>) -> Result<Self, Error> {
Ok(
MethodInfo {
access_flags: AccessFlagMask { mask: read_u16(reader)? },
access_flags: MethodAccessFlagMask { mask: read_u16(reader)? },
name_index: read_u16(reader)?,
descriptor_index: read_u16(reader)?,
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> {
let mut buffer: Box<[u8]> = vec![0; size].into_boxed_slice();

View file

@ -4,7 +4,7 @@ mod classfile;
mod bytecode;
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);
}