Constant pool fix
This commit is contained in:
parent
b751fc3588
commit
c1eca63f5a
2 changed files with 134 additions and 54 deletions
186
src/classfile.rs
186
src/classfile.rs
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue