lvm_class/attribute/method/
code.rs1use crate::ClassFormatErr;
2use crate::attribute::AttributeKind;
3use crate::constant_pool::ConstantPool;
4use common::utils::cursor::ByteCursor;
5use num_enum::TryFromPrimitive;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum CodeAttributeInfo {
10 LineNumberTable(Vec<LineNumberEntry>),
11 LocalVariableTable(Vec<LocalVariableEntry>),
12 StackMapTable(Vec<StackMapFrame>),
13 LocalVariableTypeTable(Vec<LocalVariableTypeEntry>),
14 RuntimeVisibleTypeAnnotations,
15 RuntimeInvisibleTypeAnnotations,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct LineNumberEntry {
21 pub start_pc: u16,
22 pub line_number: u16,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq)]
27pub struct LocalVariableEntry {
28 pub start_pc: u16,
29 pub length: u16,
30 pub name_index: u16,
31 pub descriptor_index: u16,
32 pub index: u16,
33}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct LocalVariableTypeEntry {
38 pub start_pc: u16,
39 pub length: u16,
40 pub name_index: u16,
41 pub signature_index: u16,
42 pub index: u16,
43}
44
45#[derive(Debug, Clone, PartialEq, Eq)]
47pub enum StackMapFrame {
48 Same {
49 offset_delta: u16,
50 },
51 SameLocals1StackItem {
52 offset_delta: u16,
53 stack: VerificationTypeInfo,
54 },
55 SameLocals1StackItemExtended {
56 offset_delta: u16,
57 stack: VerificationTypeInfo,
58 },
59 Chop {
60 k: u8,
61 offset_delta: u16,
62 },
63 SameExtended {
64 offset_delta: u16,
65 },
66 Append {
67 k: u8,
68 offset_delta: u16,
69 locals: Vec<VerificationTypeInfo>,
70 },
71 Full {
72 offset_delta: u16,
73 locals: Vec<VerificationTypeInfo>,
74 stack: Vec<VerificationTypeInfo>,
75 },
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, TryFromPrimitive)]
79#[repr(u8)]
80pub enum VerificationTypeTag {
81 Top,
82 Integer,
83 Float,
84 Double,
85 Long,
86 Null,
87 UninitializedThis,
88 Object,
89 Uninitialized,
90}
91
92#[derive(Debug, Clone, PartialEq, Eq)]
93pub enum VerificationTypeInfo {
94 Top,
95 Integer,
96 Float,
97 Double,
98 Long,
99 Null,
100 UninitializedThis,
101 Object(u16),
102 Uninitialized(u16),
103}
104
105impl<'a> StackMapFrame {
106 pub(crate) fn read(cursor: &mut ByteCursor<'a>) -> Result<Self, ClassFormatErr> {
107 let frame_type = cursor.u8()?;
108 match frame_type {
109 0..=63 => Ok(StackMapFrame::Same {
110 offset_delta: u16::from(frame_type),
111 }),
112 64..=127 => Ok(StackMapFrame::SameLocals1StackItem {
113 offset_delta: u16::from(frame_type - 64),
114 stack: VerificationTypeInfo::read(cursor)?,
115 }),
116 247 => Ok(StackMapFrame::SameLocals1StackItemExtended {
117 offset_delta: cursor.u16()?,
118 stack: VerificationTypeInfo::read(cursor)?,
119 }),
120 248..=250 => Ok(StackMapFrame::Chop {
121 k: 251 - frame_type,
122 offset_delta: cursor.u16()?,
123 }),
124 251 => Ok(StackMapFrame::SameExtended {
125 offset_delta: cursor.u16()?,
126 }),
127 252..=254 => Ok(StackMapFrame::Append {
128 k: frame_type - 251,
129 offset_delta: cursor.u16()?,
130 locals: (0..usize::from(frame_type - 251))
131 .map(|_| VerificationTypeInfo::read(cursor)) .collect::<Result<Vec<_>, _>>()?,
133 }),
134 255 => {
135 let offset_delta = cursor.u16()?;
136 let number_of_locals = cursor.u16()?;
137 let mut locals = Vec::with_capacity(number_of_locals as usize);
138 for _ in 0..number_of_locals {
139 locals.push(VerificationTypeInfo::read(cursor)?)
140 }
141 let number_of_stack_items = cursor.u16()?;
142 let mut stack = Vec::with_capacity(number_of_stack_items as usize);
143 for _ in 0..number_of_stack_items {
144 stack.push(VerificationTypeInfo::read(cursor)?)
145 }
146 Ok(StackMapFrame::Full {
147 offset_delta,
148 locals,
149 stack,
150 })
151 }
152 other => Err(ClassFormatErr::UnknownStackFrameType(other)),
153 }
154 }
155}
156
157impl<'a> VerificationTypeInfo {
158 pub(crate) fn read(cursor: &mut ByteCursor<'a>) -> Result<Self, ClassFormatErr> {
159 let raw_tag = cursor.u8()?;
160 let frame_type: VerificationTypeTag = VerificationTypeTag::try_from_primitive(raw_tag)
161 .map_err(|_| ClassFormatErr::UnknownTag(raw_tag))?;
162 Ok(match frame_type {
163 VerificationTypeTag::Top => Self::Top,
164 VerificationTypeTag::Integer => Self::Integer,
165 VerificationTypeTag::Float => Self::Float,
166 VerificationTypeTag::Double => Self::Double,
167 VerificationTypeTag::Long => Self::Long,
168 VerificationTypeTag::Null => Self::Null,
169 VerificationTypeTag::UninitializedThis => Self::UninitializedThis,
170 VerificationTypeTag::Object => Self::Object(cursor.u16()?),
171 VerificationTypeTag::Uninitialized => Self::Uninitialized(cursor.u16()?),
172 })
173 }
174}
175
176impl<'a> CodeAttributeInfo {
177 pub(crate) fn read(
178 pool: &ConstantPool,
179 cursor: &mut ByteCursor<'a>,
180 ) -> Result<Self, ClassFormatErr> {
181 let attribute_name_index = cursor.u16()?;
182 let _attribute_length = cursor.u32()? as usize;
183
184 let attribute_kind = AttributeKind::try_from(pool.get_utf8(&attribute_name_index)?)?;
185 match attribute_kind {
186 AttributeKind::LineNumberTable => {
187 let line_number_table_length = cursor.u16()? as usize;
188 let mut line_number_table = Vec::with_capacity(line_number_table_length);
189 for _ in 0..line_number_table_length {
190 line_number_table.push(LineNumberEntry {
191 start_pc: cursor.u16()?,
192 line_number: cursor.u16()?,
193 });
194 }
195 Ok(CodeAttributeInfo::LineNumberTable(line_number_table))
196 }
197 AttributeKind::LocalVariableTable => {
198 let local_variable_table_length = cursor.u16()?;
199 let mut local_variable_table =
200 Vec::with_capacity(local_variable_table_length as usize);
201 for _ in 0..local_variable_table_length {
202 local_variable_table.push(LocalVariableEntry {
203 start_pc: cursor.u16()?,
204 length: cursor.u16()?,
205 name_index: cursor.u16()?,
206 descriptor_index: cursor.u16()?,
207 index: cursor.u16()?,
208 });
209 }
210 Ok(CodeAttributeInfo::LocalVariableTable(local_variable_table))
211 }
212 AttributeKind::LocalVariableTypeTable => {
213 let local_variable_table_type_length = cursor.u16()?;
214 let mut local_variable_type_table =
215 Vec::with_capacity(local_variable_table_type_length as usize);
216 for _ in 0..local_variable_table_type_length {
217 local_variable_type_table.push(LocalVariableTypeEntry {
218 start_pc: cursor.u16()?,
219 length: cursor.u16()?,
220 name_index: cursor.u16()?,
221 signature_index: cursor.u16()?,
222 index: cursor.u16()?,
223 });
224 }
225 Ok(CodeAttributeInfo::LocalVariableTypeTable(
226 local_variable_type_table,
227 ))
228 }
229 AttributeKind::StackMapTable => {
230 let frames_count = cursor.u16()?;
231 let mut frames = Vec::with_capacity(frames_count as usize);
232 for _ in 0..frames_count {
233 frames.push(StackMapFrame::read(cursor)?)
234 }
235 Ok(CodeAttributeInfo::StackMapTable(frames))
236 }
237 other => unimplemented!("{other:?}"),
238 }
239 }
240}