Skip to content

Commit 46e08df

Browse files
committed
Added writing verification types and stack map
1 parent 565504b commit 46e08df

File tree

3 files changed

+87
-20
lines changed

3 files changed

+87
-20
lines changed

src/bytecode/classfile.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -352,19 +352,28 @@ pub enum Attribute {
352352

353353
#[derive(Debug)]
354354
pub enum StackMapFrame {
355-
SameFrame,
356-
SameLocals1StackItemFrame { stack: VerificationType },
355+
SameFrame { tag: u8 },
356+
SameLocals1StackItemFrame { tag: u8, stack: VerificationType },
357357
SameLocals1StackItemFrameExtended { offset_delta: u16, stack: VerificationType },
358-
ChopFrame { offset_delta: u16 },
358+
ChopFrame { tag: u8, offset_delta: u16 },
359359
SameFrameExtended { offset_delta: u16 },
360-
AppendFrame { offset_delta: u16, locals: Vec<VerificationType> },
360+
AppendFrame { tag: u8, offset_delta: u16, locals: Vec<VerificationType> },
361361
FullFrame { offset_delta: u16, locals: Vec<VerificationType>, stack: Vec<VerificationType> },
362-
FutureUse
362+
FutureUse { tag: u8 }
363363
}
364364

365365
impl StackMapFrame {
366366
pub fn len(&self) -> usize {
367-
0
367+
match self {
368+
&StackMapFrame::SameFrame { tag: _ } => 1,
369+
&StackMapFrame::SameLocals1StackItemFrame{ tag: _, ref stack } => 1 + stack.len(),
370+
&StackMapFrame::SameLocals1StackItemFrameExtended { offset_delta: _, ref stack } => 3 + stack.len(),
371+
&StackMapFrame::ChopFrame { tag: _, offset_delta: _ } => 3,
372+
&StackMapFrame::SameFrameExtended { offset_delta: _ } => 3,
373+
&StackMapFrame::AppendFrame { tag: _, offset_delta: _, ref locals } => 3 + locals.iter().fold(0, |acc, x| acc + x.len()),
374+
&StackMapFrame::FullFrame { offset_delta: _, ref locals, ref stack } => 7 + locals.iter().fold(0, |acc, x| acc + x.len()) + stack.iter().fold(0, |acc, x| acc + x.len()),
375+
&StackMapFrame::FutureUse { tag: _ } => 0
376+
}
368377
}
369378
}
370379

@@ -376,11 +385,21 @@ pub enum VerificationType {
376385
Long,
377386
Double,
378387
Null,
379-
Uninitializedthis,
388+
UninitializedThis,
380389
Object { cpool_index: ConstantPoolIndex },
381390
Uninitialized { offset: u16 }
382391
}
383392

393+
impl VerificationType {
394+
pub fn len(&self) -> usize {
395+
match self {
396+
&VerificationType::Object { cpool_index: _ } => 3,
397+
&VerificationType::Uninitialized { offset: _ } => 3,
398+
_ => 1
399+
}
400+
}
401+
}
402+
384403
#[derive(Debug)]
385404
pub struct ExceptionHandler {
386405
pub start_pc: u16,

src/bytecode/io/reader.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -601,27 +601,27 @@ impl ClassReader {
601601
3 => VerificationType::Double,
602602
4 => VerificationType::Long,
603603
5 => VerificationType::Null,
604-
6 => VerificationType::Uninitializedthis,
604+
6 => VerificationType::UninitializedThis,
605605
7 => VerificationType::Object { cpool_index: ConstantPoolIndex::new(r.get_u16() as usize ) },
606606
8 => VerificationType::Uninitialized { offset: r.get_u16() },
607607
_ => VerificationType::Top
608608
};
609609

610610
match frame_type {
611-
0...63 => StackMapFrame::SameFrame,
612-
64...127 => StackMapFrame::SameLocals1StackItemFrame { stack: read_verification_type(&mut reader) },
611+
tag@0...63 => StackMapFrame::SameFrame { tag: tag },
612+
tag@64...127 => StackMapFrame::SameLocals1StackItemFrame { tag: tag, stack: read_verification_type(&mut reader) },
613613
247 => StackMapFrame::SameLocals1StackItemFrameExtended { offset_delta: reader.get_u16(), stack: read_verification_type(&mut reader) },
614-
248...250 => StackMapFrame::ChopFrame { offset_delta: reader.get_u16() },
614+
tag@248...250 => StackMapFrame::ChopFrame { tag: tag, offset_delta: reader.get_u16() },
615615
251 => StackMapFrame::SameFrameExtended { offset_delta: reader.get_u16() },
616-
i@252...254 => StackMapFrame::AppendFrame { offset_delta: reader.get_u16(), locals: (0..i - 251).map(|_| read_verification_type(&mut reader)).collect() },
616+
tag@252...254 => StackMapFrame::AppendFrame { tag: tag, offset_delta: reader.get_u16(), locals: (0..tag - 251).map(|_| read_verification_type(&mut reader)).collect() },
617617
255 => StackMapFrame::FullFrame { offset_delta: reader.get_u16(), locals: {
618618
let n = reader.get_u16();
619619
(0..n).map(|_| read_verification_type(&mut reader)).collect()
620620
}, stack: {
621621
let n = reader.get_u16();
622622
(0..n).map(|_| read_verification_type(&mut reader)).collect()
623623
}},
624-
_ => StackMapFrame::FutureUse,
624+
tag@_ => StackMapFrame::FutureUse { tag: tag },
625625
}
626626
}).collect()
627627
})),

src/bytecode/io/writer.rs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,13 +131,58 @@ impl<'a> ClassWriter<'a> {
131131
.and(self.write_exception_handlers(exception_table))
132132
.and(self.write_attributes(attributes, cp))
133133
},
134-
&Attribute::StackMapTable(ref table) => self.write_u16(cp.get_utf8_index("StackMapTable") as u16).and(self.write_stack_map_table(table, cp)),
134+
&Attribute::StackMapTable(ref table) => self.write_stack_map_table(table, cp),
135135
_ => Ok(0)
136136
}
137137
}
138138

139139
fn write_stack_map_table(&mut self, table: &Vec<StackMapFrame>, cp: &ConstantPool) -> Result<usize, Error> {
140-
self.write_u16(cp.get_utf8_index("StackMapTable") as u16).and(self.write_u32(2 + table.iter().map(|st| st.len()).fold(0, |acc, x| acc + x) as u32))
140+
// attribute_name_index
141+
self.write_u16(cp.get_utf8_index("StackMapTable") as u16)
142+
// attribute_length = number_of_entries length (2) + sum of entries' length
143+
.and(self.write_u32(2 + table.iter().map(|st| st.len()).fold(0, |acc, x| acc + x) as u32))
144+
// number_of_entries
145+
.and(self.write_u16(table.len() as u16))
146+
// entries
147+
.and(table.iter().fold(Ok(0), |acc, x| {
148+
match x {
149+
&StackMapFrame::SameFrame { tag } => self.write_u8(tag),
150+
&StackMapFrame::SameLocals1StackItemFrame{ tag, ref stack } => self.write_u8(tag).and(self.write_verification_type(stack)),
151+
&StackMapFrame::SameLocals1StackItemFrameExtended { offset_delta, ref stack } => self.write_u8(247).and(self.write_u16(offset_delta)).and(self.write_verification_type(stack)),
152+
&StackMapFrame::ChopFrame { tag, offset_delta } => self.write_u8(tag).and(self.write_u16(offset_delta)),
153+
&StackMapFrame::SameFrameExtended { offset_delta } => self.write_u8(251).and(self.write_u16(offset_delta)),
154+
&StackMapFrame::AppendFrame { tag, offset_delta, ref locals } => self.write_u8(tag).and(self.write_u16(offset_delta)).and(locals.iter().fold(Ok(0), |acc, x| self.write_verification_type(x))),
155+
&StackMapFrame::FullFrame { offset_delta, ref locals, ref stack } => {
156+
// full frame tag
157+
self.write_u8(255)
158+
// offset_delta
159+
.and(self.write_u16(offset_delta))
160+
// number_of_locals
161+
.and(self.write_u16(locals.len() as u16))
162+
// locals
163+
.and(locals.iter().fold(Ok(0), |acc, x| self.write_verification_type(x)))
164+
// number_of_stack_items
165+
.and(self.write_u16(stack.len() as u16))
166+
// stack
167+
.and(stack.iter().fold(Ok(0), |acc, x| self.write_verification_type(x)))
168+
},
169+
&StackMapFrame::FutureUse { tag } => self.write_u8(tag)
170+
}
171+
}))
172+
}
173+
174+
fn write_verification_type(&mut self, info: &VerificationType) -> Result<usize, Error> {
175+
match info {
176+
&VerificationType::Top => self.write_u8(0),
177+
&VerificationType::Integer => self.write_u8(1),
178+
&VerificationType::Float => self.write_u8(2),
179+
&VerificationType::Long => self.write_u8(4),
180+
&VerificationType::Double => self.write_u8(3),
181+
&VerificationType::Null => self.write_u8(5),
182+
&VerificationType::UninitializedThis => self.write_u8(6),
183+
&VerificationType::Object { ref cpool_index } => self.write_u8(7).and(self.write_u16(cpool_index.idx as u16)),
184+
&VerificationType::Uninitialized { offset } => self.write_u8(8).and(self.write_u16(offset))
185+
}
141186
}
142187

143188
fn write_instructions(&mut self, instructions: &Vec<Instruction>) -> Result<usize, Error> {
@@ -231,7 +276,7 @@ impl<'a> ClassWriter<'a> {
231276
&Instruction::FNEG => self.write_u8(0x76),
232277
&Instruction::FREM => self.write_u8(0x72),
233278
&Instruction::FRETURN => self.write_u8(0xae),
234-
&Instruction::FSTORE(value) => self.write_u8(0x38),
279+
&Instruction::FSTORE(value) => self.write_u8(0x38).and(self.write_u8(value)),
235280
&Instruction::FSTORE_0 => self.write_u8(0x43),
236281
&Instruction::FSTORE_1 => self.write_u8(0x44),
237282
&Instruction::FSTORE_2 => self.write_u8(0x45),
@@ -327,17 +372,17 @@ impl<'a> ClassWriter<'a> {
327372
&Instruction::LNEG => self.write_u8(0x75),
328373
//LOOKUPSWITCH(i32, Vec<(i32, i32)>),
329374
&Instruction::LOOKUPSWITCH(a, ref l) => {
330-
self.write_u8(0xab);
375+
let _ = self.write_u8(0xab);
331376
let padding = (4 - ((offset + 1) % 4)) % 4;
332377

333378
for _ in 0..padding {
334-
self.write_u8(0);
379+
let _ = self.write_u8(0);
335380
}
336381

337382
let padding = (4 - ((offset + 1) % 4)) % 4;
338383

339384
for _ in 0..padding {
340-
self.write_u8(0);
385+
let _ = self.write_u8(0);
341386
}
342387

343388
self.write_u32(a as u32);
@@ -418,7 +463,10 @@ impl<'a> ClassWriter<'a> {
418463
fn write_exception_handlers(&mut self, exception_table: &Vec<ExceptionHandler>) -> Result<usize, Error> {
419464
self.write_u16(exception_table.len() as u16)
420465
.and(exception_table.iter().fold(Ok(0), |acc, x| {
421-
self.write_u16(x.start_pc).and(self.write_u16(x.end_pc)).and(self.write_u16(x.handler_pc)).and(self.write_u16(x.catch_type.idx as u16))
466+
self.write_u16(x.start_pc)
467+
.and(self.write_u16(x.end_pc))
468+
.and(self.write_u16(x.handler_pc))
469+
.and(self.write_u16(x.catch_type.idx as u16))
422470
}))
423471
}
424472

0 commit comments

Comments
 (0)