1#![deny(missing_docs)]
2
3use crate::{
4 graal_io::{GraalIoError, GraalReader},
5 instruction::Instruction,
6 opcode::{Opcode, OpcodeError},
7 operand::{Operand, OperandError},
8 utils::Gs2BytecodeAddress,
9};
10
11use std::{
12 collections::{BTreeSet, HashMap},
13 io::Read,
14};
15
16use log::warn;
17use petgraph::graph::{DiGraph, NodeIndex};
18use serde::{Deserialize, Serialize};
19use thiserror::Error;
20
21#[derive(Error, Debug, Clone, Serialize)]
23pub enum BytecodeLoaderError {
24 #[error("Invalid section type: {0}")]
26 InvalidSectionType(u32),
27
28 #[error("Invalid section length for {0}: {1}")]
30 InvalidSectionLength(SectionType, u32),
31
32 #[error("String index {0} is out of bounds. Length: {1}")]
34 StringIndexOutOfBounds(usize, usize),
35
36 #[error("No previous instruction to set operand")]
38 NoPreviousInstruction,
39
40 #[error("Block at address {0} is unreachable")]
42 UnreachableBlock(Gs2BytecodeAddress),
43
44 #[error("GraalIo error: {0}")]
46 GraalIo(#[from] GraalIoError),
47
48 #[error("Invalid opcode: {0}")]
50 OpcodeError(#[from] OpcodeError),
51
52 #[error("Invalid operand: {0}")]
54 InvalidOperand(#[from] OperandError),
55}
56
57impl std::fmt::Display for SectionType {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 match self {
60 SectionType::Gs1Flags => write!(f, "Gs1Flags"),
61 SectionType::Functions => write!(f, "Functions"),
62 SectionType::Strings => write!(f, "Strings"),
63 SectionType::Instructions => write!(f, "Instructions"),
64 }
65 }
66}
67
68#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy)]
70#[repr(u32)]
71pub enum SectionType {
72 Gs1Flags = 1,
74
75 Functions = 2,
77
78 Strings = 3,
80
81 Instructions = 4,
83}
84
85pub struct BytecodeLoaderBuilder<R> {
87 reader: R,
88}
89
90impl<R: std::io::Read> BytecodeLoaderBuilder<R> {
91 pub fn new(reader: R) -> Self {
107 Self { reader }
108 }
109
110 pub fn build(self) -> Result<BytecodeLoader<R>, BytecodeLoaderError> {
123 let mut loader = BytecodeLoader {
124 block_breaks: BTreeSet::new(),
125 reader: GraalReader::new(self.reader),
126 function_map: HashMap::new(),
127 strings: Vec::new(),
128 instructions: Vec::new(),
129 raw_block_graph: DiGraph::new(),
130 raw_block_address_to_node: HashMap::new(),
131 block_address_to_function: HashMap::new(),
132 };
133 loader.load()?; Ok(loader)
135 }
136}
137
138pub struct BytecodeLoader<R: Read> {
140 reader: GraalReader<R>,
141 strings: Vec<String>,
142
143 pub function_map: HashMap<Option<String>, Gs2BytecodeAddress>,
145
146 pub instructions: Vec<Instruction>,
148
149 block_breaks: BTreeSet<Gs2BytecodeAddress>,
151
152 raw_block_graph: DiGraph<Gs2BytecodeAddress, ()>,
154
155 raw_block_address_to_node: HashMap<Gs2BytecodeAddress, NodeIndex>,
157
158 pub block_address_to_function: HashMap<Gs2BytecodeAddress, Option<String>>,
160}
161
162impl<R: Read> BytecodeLoader<R> {
163 fn expect_section_length(
176 section_type: SectionType,
177 expected_length: u32,
178 got_length: u32,
179 ) -> Result<(), BytecodeLoaderError> {
180 if expected_length != got_length {
181 return Err(BytecodeLoaderError::InvalidSectionLength(
182 section_type,
183 got_length,
184 ));
185 }
186 Ok(())
187 }
188
189 fn read_gs1_flags(&mut self) -> Result<(), BytecodeLoaderError> {
193 let section_length = self.reader.read_u32().map_err(BytecodeLoaderError::from)?;
194 let _flags = self.reader.read_u32().map_err(BytecodeLoaderError::from)?;
195
196 Self::expect_section_length(SectionType::Gs1Flags, 4, section_length)?;
198
199 Ok(())
200 }
201
202 fn insert_block_start(&mut self, address: Gs2BytecodeAddress) {
207 self.block_breaks.insert(address);
208 }
209
210 fn read_functions(&mut self) -> Result<(), BytecodeLoaderError> {
220 let section_length = self.reader.read_u32().map_err(BytecodeLoaderError::from)?;
221
222 self.function_map.insert(None, 0);
224
225 let mut bytes_read = 0;
229 while bytes_read < section_length {
230 let function_location =
231 self.reader.read_u32().map_err(BytecodeLoaderError::from)? as Gs2BytecodeAddress;
232 let function_name = self
233 .reader
234 .read_string()
235 .map_err(BytecodeLoaderError::from)?
236 .0;
237 self.function_map
238 .insert(Some(function_name.clone()), function_location);
239 bytes_read += 4 + function_name.len() as u32;
240 bytes_read += 1; self.insert_block_start(function_location);
243 }
244
245 Self::expect_section_length(SectionType::Functions, section_length, bytes_read)?;
247
248 Ok(())
249 }
250
251 fn read_strings(&mut self) -> Result<(), BytecodeLoaderError> {
260 let section_length = self.reader.read_u32().map_err(BytecodeLoaderError::from)?;
261
262 let mut bytes_read = 0;
264 while bytes_read < section_length {
265 let (string, raw_len) = self
266 .reader
267 .read_string()
268 .map_err(BytecodeLoaderError::from)?;
269 self.strings.push(string.clone());
270 bytes_read += raw_len;
271 bytes_read += 1; }
273
274 Self::expect_section_length(SectionType::Strings, section_length, bytes_read)?;
276
277 Ok(())
278 }
279
280 fn read_opcode(&mut self) -> Result<Opcode, BytecodeLoaderError> {
282 let opcode_byte = self.reader.read_u8().map_err(BytecodeLoaderError::from)?;
283 let opcode = Opcode::from_byte(opcode_byte)?;
284 Ok(opcode)
285 }
286
287 fn read_operand(
289 &mut self,
290 opcode: Opcode,
291 ) -> Result<Option<(Operand, usize)>, BytecodeLoaderError> {
292 match opcode {
293 Opcode::ImmStringByte => {
294 let string_index = self.reader.read_u8().map_err(BytecodeLoaderError::from)?;
295 let string = self.strings.get(string_index as usize).ok_or(
296 BytecodeLoaderError::StringIndexOutOfBounds(
297 string_index as usize,
298 self.strings.len(),
299 ),
300 )?;
301 Ok(Some((Operand::new_string(string), 1)))
302 }
303 Opcode::ImmStringShort => {
304 let string_index = self.reader.read_u16().map_err(BytecodeLoaderError::from)?;
305 let string = self.strings.get(string_index as usize).ok_or(
306 BytecodeLoaderError::StringIndexOutOfBounds(
307 string_index as usize,
308 self.strings.len(),
309 ),
310 )?;
311 Ok(Some((Operand::new_string(string), 2)))
312 }
313 Opcode::ImmStringInt => {
314 let string_index = self.reader.read_u32().map_err(BytecodeLoaderError::from)?;
315 let string = self.strings.get(string_index as usize).ok_or(
316 BytecodeLoaderError::StringIndexOutOfBounds(
317 string_index as usize,
318 self.strings.len(),
319 ),
320 )?;
321 Ok(Some((Operand::new_string(string), 4)))
322 }
323 Opcode::ImmByte => {
324 let value = self.reader.read_u8().map_err(BytecodeLoaderError::from)?;
325 Ok(Some((Operand::new_number(value as i8 as i32), 1)))
326 }
327 Opcode::ImmShort => {
328 let value = self.reader.read_u16().map_err(BytecodeLoaderError::from)?;
329 Ok(Some((Operand::new_number(value as i16 as i32), 2)))
330 }
331 Opcode::ImmInt => {
332 let value = self.reader.read_u32().map_err(BytecodeLoaderError::from)?;
333 Ok(Some((Operand::new_number(value as i32), 4)))
334 }
335 Opcode::ImmFloat => {
336 let value = self
337 .reader
338 .read_string()
339 .map_err(BytecodeLoaderError::from)?
340 .0;
341 Ok(Some((Operand::new_float(value.clone()), value.len() + 1)))
342 }
343 _ => Ok(None),
344 }
345 }
346
347 fn read_instructions(&mut self) -> Result<(), BytecodeLoaderError> {
349 self.insert_block_start(0);
351
352 let section_length = self.reader.read_u32().map_err(BytecodeLoaderError::from)?;
353
354 let mut bytes_read = 0;
355 while bytes_read < section_length {
356 let opcode = self.read_opcode()?;
357 bytes_read += 1;
358
359 let operand = self.read_operand(opcode)?;
360
361 if let Some(operand) = operand {
362 {
364 let last_instruction = self
365 .instructions
366 .last_mut()
367 .ok_or(BytecodeLoaderError::NoPreviousInstruction)?;
368
369 last_instruction.set_operand(operand.0.clone());
370 }
371
372 bytes_read += operand.1 as u32;
373
374 assert!(self.instructions.last().is_some());
375
376 if self.instructions.last().unwrap().opcode.has_jump_target() {
378 self.insert_block_start(operand.0.get_number_value()? as Gs2BytecodeAddress);
379 }
380 } else {
381 let address = self.instructions.len();
383 self.instructions.push(Instruction::new(opcode, address));
384
385 if opcode.is_block_end() {
386 let current_address = address as Gs2BytecodeAddress;
387 self.insert_block_start(current_address + 1);
388 }
389 }
390 }
391
392 Self::expect_section_length(SectionType::Instructions, section_length, bytes_read)?;
394
395 if self.instructions.is_empty() {
397 warn!("No instructions were loaded.");
398 self.block_breaks.clear();
399 }
400
401 let instruction_count = self.instructions.len() as Gs2BytecodeAddress;
403 for address in self.block_breaks.iter() {
404 if *address > instruction_count {
406 return Err(BytecodeLoaderError::InvalidOperand(
407 OperandError::InvalidJumpTarget(*address),
408 ));
409 }
410 }
411
412 Ok(())
413 }
414
415 fn load(&mut self) -> Result<(), BytecodeLoaderError> {
429 for _ in 0..4 {
431 let section_type = self.read_section_type()?;
432 match section_type {
433 SectionType::Gs1Flags => {
434 self.read_gs1_flags()?;
435 }
436 SectionType::Functions => {
437 self.read_functions()?;
438 }
439 SectionType::Strings => {
440 self.read_strings()?;
441 }
442 SectionType::Instructions => {
443 self.read_instructions()?;
444 }
445 }
446 }
447
448 for block_break in self.block_breaks.iter() {
450 let node = self.raw_block_graph.add_node(*block_break);
451 self.raw_block_address_to_node.insert(*block_break, node);
452 }
453
454 for instruction in self.instructions.iter() {
456 let current_instruction_address = instruction.address as Gs2BytecodeAddress;
457 let current_block_address = self.find_block_start_address(current_instruction_address);
458 let is_block_end = self
460 .block_breaks
461 .contains(&(current_instruction_address + 1));
462
463 if instruction.opcode.has_jump_target() {
465 let source_node = self
466 .raw_block_address_to_node
467 .get(¤t_block_address)
468 .unwrap();
472
473 let target_address =
476 instruction.operand.as_ref().unwrap().get_number_value()? as Gs2BytecodeAddress;
477
478 let target_node = self.raw_block_address_to_node.get(&target_address).unwrap();
480
481 self.raw_block_graph
482 .add_edge(*source_node, *target_node, ());
483 }
484
485 if is_block_end && instruction.opcode.connects_to_next_block() {
487 let source_node = self
488 .raw_block_address_to_node
489 .get(¤t_block_address)
490 .unwrap();
494
495 let next_block_address = current_instruction_address + 1;
497
498 let target_node = self
500 .raw_block_address_to_node
501 .get(&next_block_address)
502 .unwrap();
503
504 self.raw_block_graph
505 .add_edge(*source_node, *target_node, ());
506 }
507 }
508
509 for (function_name, function_address) in self.function_map.iter() {
511 assert_eq!(
512 self.raw_block_graph.node_count(),
513 self.raw_block_address_to_node.len(),
514 "Graph node count and block address map size do not match!"
515 );
516 for (&block_address, &node) in &self.raw_block_address_to_node {
517 assert!(
518 self.raw_block_graph.node_indices().any(|n| n == node),
519 "Node {:?} for block address {} is missing in the graph.",
520 node,
521 block_address
522 );
523 }
524
525 if let Some(function_node) = self.raw_block_address_to_node.get(function_address) {
526 let mut dfs = petgraph::visit::Dfs::new(&self.raw_block_graph, *function_node);
527
528 while let Some(node) = dfs.next(&self.raw_block_graph) {
529 if let Some(block_address) = self
531 .raw_block_address_to_node
532 .iter()
533 .find_map(|(k, v)| if *v == node { Some(*k) } else { None })
534 {
535 self.block_address_to_function
536 .insert(block_address, function_name.clone());
537 } else {
538 warn!("Node {:?} has no matching block address.", node);
539 }
540 }
541 } else {
542 warn!(
543 "Function '{:?}' at address {} has no corresponding node in raw_block_address_to_node.",
544 function_name, function_address
545 );
546 }
547 }
548
549 Ok(())
550 }
551
552 pub fn get_function_name_for_address(
564 &self,
565 address: Gs2BytecodeAddress,
566 ) -> Result<Option<String>, BytecodeLoaderError> {
567 let block_start = self.find_block_start_address(address);
568 Ok(self
569 .block_address_to_function
570 .get(&block_start)
571 .ok_or(BytecodeLoaderError::UnreachableBlock(block_start))?
573 .clone())
574 }
575
576 pub fn is_instruction_reachable(&self, address: Gs2BytecodeAddress) -> bool {
584 let blk = self.find_block_start_address(address);
585 self.block_address_to_function.contains_key(&blk)
586 }
587
588 pub fn find_block_start_address(&self, address: Gs2BytecodeAddress) -> Gs2BytecodeAddress {
597 let mut block_start = 0;
598 for block_break in self.block_breaks.iter() {
599 if *block_break > address {
600 break;
601 }
602 block_start = *block_break;
603 }
604 block_start
605 }
606
607 fn read_section_type(&mut self) -> Result<SectionType, BytecodeLoaderError> {
609 let section_type = self.reader.read_u32().map_err(BytecodeLoaderError::from)?;
610 match section_type {
611 1 => Ok(SectionType::Gs1Flags),
612 2 => Ok(SectionType::Functions),
613 3 => Ok(SectionType::Strings),
614 4 => Ok(SectionType::Instructions),
615 _ => Err(BytecodeLoaderError::InvalidSectionType(section_type)),
616 }
617 }
618}
619
620#[cfg(test)]
621mod tests {
622 use crate::{bytecode_loader::BytecodeLoaderBuilder, utils::Gs2BytecodeAddress};
623
624 #[test]
625 fn test_load() {
626 let reader = std::io::Cursor::new(vec![
627 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x61, 0x62, 0x63, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x01, 0xF3, 0x01, 0x14, 0xF4, 0x00, 0x01, 0x15, 0xF0, 0x00, 0x1b, 0x07, ]);
652 let loader = BytecodeLoaderBuilder::new(reader).build().unwrap();
653
654 assert_eq!(loader.function_map.len(), 2);
655 assert_eq!(loader.function_map.get(&Some("main".to_string())), Some(&0));
656 assert_eq!(loader.strings.len(), 1);
657 assert_eq!(loader.strings.first(), Some(&"abc".to_string()));
658 assert_eq!(loader.instructions.len(), 5);
659 assert_eq!(loader.instructions[0].opcode, crate::opcode::Opcode::Jmp);
660 assert_eq!(
661 loader.instructions[1].opcode,
662 crate::opcode::Opcode::PushNumber
663 );
664 assert_eq!(
665 loader.instructions[1].operand,
666 Some(crate::operand::Operand::new_number(1))
667 );
668 assert_eq!(
669 loader.instructions[2].opcode,
670 crate::opcode::Opcode::PushString
671 );
672 assert_eq!(
673 loader.instructions[2].operand,
674 Some(crate::operand::Operand::new_string("abc"))
675 );
676 assert_eq!(loader.instructions[3].opcode, crate::opcode::Opcode::Pi);
677 assert_eq!(loader.instructions[4].opcode, crate::opcode::Opcode::Ret);
678 }
679
680 #[test]
681 fn test_complex_load() {
682 let reader = std::io::Cursor::new(vec![
683 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x61, 0x62, 0x63, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x01, 0xF3, 0x19, 0x14, 0xF3, 0x00, 0x01, 0xF3, 0x0c, 0x14, 0xF3, 0x00, 0x01, 0xF3, 0x17, 0x14, 0xF3, 0x00, 0x01, 0xF3, 0x17, 0x14, 0xF3, 0x00, 0x01, 0xF3, 0x17, 0x14, 0xF3, 0x00, 0x01, 0xF3, 0x17, 0x01, 0xF3, 0x17, 0x14, 0xF3, 0x00, 0x02, 0xF3, 0x03, 0x14, 0xF3, 0x00, 0x02, 0xF3, 0x03, 0x14, 0xF3, 0x00, 0x02, 0xF3, 0x03, 0x14, 0xF3, 0x00, 0x02, 0xF3, 0x05, 0x14, 0xF3, 0x00, 0x02, 0xF3, 0x07, 0x01, 0xF3, 0x0b, 0x20, 0x07, ]);
723 let loader = BytecodeLoaderBuilder::new(reader).build().unwrap();
724
725 assert_eq!(loader.function_map.len(), 2);
726
727 let block_starts: Vec<Gs2BytecodeAddress> = loader.block_breaks.iter().copied().collect();
730
731 let block_0 = loader.find_block_start_address(0);
733 let block_0x19 = loader.find_block_start_address(0x19);
734 assert!(loader.raw_block_graph.contains_edge(
735 loader.raw_block_address_to_node[&block_0],
736 loader.raw_block_address_to_node[&block_0x19]
737 ));
738
739 let block_1 = loader.find_block_start_address(1);
741 let block_0x0c = loader.find_block_start_address(0x0c);
742 assert!(loader.raw_block_graph.contains_edge(
743 loader.raw_block_address_to_node[&block_1],
744 loader.raw_block_address_to_node[&block_0x0c]
745 ));
746
747 let block_0x03 = loader.find_block_start_address(0x03);
749 let block_0x17 = loader.find_block_start_address(0x17);
750 assert!(loader.raw_block_graph.contains_edge(
751 loader.raw_block_address_to_node[&block_0x03],
752 loader.raw_block_address_to_node[&block_0x17]
753 ));
754
755 let block_0x05 = loader.find_block_start_address(0x05);
757 assert!(loader.raw_block_graph.contains_edge(
758 loader.raw_block_address_to_node[&block_0x05],
759 loader.raw_block_address_to_node[&block_0x17]
760 ));
761 let block_0x07 = loader.find_block_start_address(0x07);
763 assert!(loader.raw_block_graph.contains_edge(
764 loader.raw_block_address_to_node[&block_0x07],
765 loader.raw_block_address_to_node[&block_0x17]
766 ));
767
768 let block_0x0b = loader.find_block_start_address(0x0b);
770 assert!(loader.raw_block_graph.contains_edge(
771 loader.raw_block_address_to_node[&block_0x0b],
772 loader.raw_block_address_to_node[&block_0x17]
773 ));
774
775 let block_0x0c = loader.find_block_start_address(0x0c);
777 let block_0x03 = loader.find_block_start_address(0x03);
778 assert!(loader.raw_block_graph.contains_edge(
779 loader.raw_block_address_to_node[&block_0x0c],
780 loader.raw_block_address_to_node[&block_0x03]
781 ));
782
783 let block_0x0e = loader.find_block_start_address(0x0e);
785 assert!(loader.raw_block_graph.contains_edge(
786 loader.raw_block_address_to_node[&block_0x0c],
787 loader.raw_block_address_to_node[&block_0x0e]
788 ));
789
790 let block_0x0e = loader.find_block_start_address(0x0e);
792 assert!(loader.raw_block_graph.contains_edge(
793 loader.raw_block_address_to_node[&block_0x0e],
794 loader.raw_block_address_to_node[&block_0x03]
795 ));
796
797 let block_0x10 = loader.find_block_start_address(0x10);
799 assert!(loader.raw_block_graph.contains_edge(
800 loader.raw_block_address_to_node[&block_0x0e],
801 loader.raw_block_address_to_node[&block_0x10]
802 ));
803
804 let block_0x10 = loader.find_block_start_address(0x10);
806 assert!(loader.raw_block_graph.contains_edge(
807 loader.raw_block_address_to_node[&block_0x10],
808 loader.raw_block_address_to_node[&block_0x03]
809 ));
810
811 let block_0x12 = loader.find_block_start_address(0x12);
813 assert!(loader.raw_block_graph.contains_edge(
814 loader.raw_block_address_to_node[&block_0x10],
815 loader.raw_block_address_to_node[&block_0x12]
816 ));
817
818 let block_0x12 = loader.find_block_start_address(0x12);
820 let block_0x05 = loader.find_block_start_address(0x05);
821 assert!(loader.raw_block_graph.contains_edge(
822 loader.raw_block_address_to_node[&block_0x12],
823 loader.raw_block_address_to_node[&block_0x05]
824 ));
825
826 let block_0x14 = loader.find_block_start_address(0x14);
828 assert!(loader.raw_block_graph.contains_edge(
829 loader.raw_block_address_to_node[&block_0x12],
830 loader.raw_block_address_to_node[&block_0x14]
831 ));
832
833 let block_0x14 = loader.find_block_start_address(0x14);
835 let block_0x07 = loader.find_block_start_address(0x07);
836 assert!(loader.raw_block_graph.contains_edge(
837 loader.raw_block_address_to_node[&block_0x14],
838 loader.raw_block_address_to_node[&block_0x07]
839 ));
840
841 let block_0x16 = loader.find_block_start_address(0x16);
843 assert!(loader.raw_block_graph.contains_edge(
844 loader.raw_block_address_to_node[&block_0x14],
845 loader.raw_block_address_to_node[&block_0x16]
846 ));
847
848 let block_0x16 = loader.find_block_start_address(0x16);
850 let block_0x0b = loader.find_block_start_address(0x0b);
851 assert!(loader.raw_block_graph.contains_edge(
852 loader.raw_block_address_to_node[&block_0x16],
853 loader.raw_block_address_to_node[&block_0x0b]
854 ));
855
856 let expected_block_starts = vec![
858 0x0, 0x1, 0x3, 0x5, 0x7, 0x9, 0xb, 0xc, 0xe, 0x10, 0x12, 0x14, 0x16, 0x17, 0x19,
859 ];
860 assert_eq!(block_starts, expected_block_starts);
861
862 let block_0x09 = loader.find_block_start_address(0x09);
864 assert_eq!(
865 loader
866 .raw_block_graph
867 .neighbors_directed(
868 loader.raw_block_address_to_node[&block_0x09],
869 petgraph::Direction::Incoming
870 )
871 .count(),
872 0
873 );
874
875 assert_eq!(block_starts.len(), 15);
876
877 assert_eq!(loader.function_map.len(), 2);
879
880 for address in expected_block_starts.iter() {
882 match address {
883 0 => assert_eq!(loader.get_function_name_for_address(0).unwrap(), None),
885 0x09 => assert!(loader.get_function_name_for_address(9).is_err()),
887 0x19 => assert_eq!(loader.get_function_name_for_address(0x19).unwrap(), None),
889 _ => assert_eq!(
890 loader.get_function_name_for_address(*address).unwrap(),
891 Some("main".to_string())
892 ),
893 }
894 }
895 }
896
897 #[test]
898 fn test_load_invalid_section_type() {
899 let reader = std::io::Cursor::new(vec![0x00, 0x00, 0x00, 0x05]);
900 let result = BytecodeLoaderBuilder::new(reader).build();
901 assert!(result.is_err());
902 }
903
904 #[test]
905 fn test_load_invalid_section_length() {
906 let reader = std::io::Cursor::new(vec![
907 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, ]);
911 let result = BytecodeLoaderBuilder::new(reader).build();
912 assert!(result.is_err());
913 }
914
915 #[test]
916 fn test_fmt_section_type() {
917 assert_eq!(
918 format!("{}", super::SectionType::Gs1Flags),
919 "Gs1Flags".to_string()
920 );
921 assert_eq!(
922 format!("{}", super::SectionType::Functions),
923 "Functions".to_string()
924 );
925 assert_eq!(
926 format!("{}", super::SectionType::Strings),
927 "Strings".to_string()
928 );
929 assert_eq!(
930 format!("{}", super::SectionType::Instructions),
931 "Instructions".to_string()
932 );
933 }
934
935 #[test]
936 fn test_load_string_index_out_of_bounds() {
937 let reader = std::io::Cursor::new(vec![
938 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x61, 0x62, 0x63, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x01, 0xF3, 0x01, 0x14, 0xF4, 0x00, 0x01, 0x15, 0xF0, 0x01, 0x1b, 0x07, ]);
963
964 let result = BytecodeLoaderBuilder::new(reader).build();
965
966 assert!(result.is_err());
967 }
968
969 #[test]
970 fn test_invalid_instruction() {
971 let reader = std::io::Cursor::new(vec![
972 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x61, 0x62, 0x63, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0xF3, 0x01, ]);
988
989 let result = BytecodeLoaderBuilder::new(reader).build();
990
991 assert!(result.is_err());
992 }
993
994 #[test]
995 fn test_load_invalid_function_section_length() {
996 let reader = std::io::Cursor::new(vec![
997 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x61, 0x62, 0x63, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x01, 0xF3, 0x01, 0x14, 0xF4, 0x00, 0x01, 0x15, 0xF0, 0x00, 0x1b, 0x07, ]);
1022
1023 let result = BytecodeLoaderBuilder::new(reader).build();
1024
1025 assert!(result.is_err());
1026 }
1027
1028 #[test]
1029 fn test_operands() {
1030 let reader = std::io::Cursor::new(vec![
1031 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x61, 0x62, 0x63, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x23, 0x01, 0xF3, 0x01, 0x14, 0xF4, 0x00, 0x01, 0x14, 0xF5, 0x00, 0x00, 0x00, 0x01, 0x14, 0xF6, 0x33, 0x2e, 0x31, 0x34, 0x00, 0x15, 0xF0, 0x00, 0x15, 0xF1, 0x00, 0x00, 0x15, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x07, ]);
1068 let loader = BytecodeLoaderBuilder::new(reader).build().unwrap();
1069
1070 assert_eq!(loader.function_map.len(), 2);
1071 assert_eq!(loader.function_map.get(&Some("main".to_string())), Some(&0));
1072 assert_eq!(loader.strings.len(), 1);
1073 assert_eq!(loader.strings.first(), Some(&"abc".to_string()));
1074 assert_eq!(loader.instructions.len(), 9);
1075
1076 assert_eq!(loader.instructions[0].opcode, crate::opcode::Opcode::Jmp);
1077 assert_eq!(
1078 loader.instructions[0].operand,
1079 Some(crate::operand::Operand::new_number(1))
1080 );
1081 assert_eq!(
1082 loader.instructions[1].opcode,
1083 crate::opcode::Opcode::PushNumber
1084 );
1085 assert_eq!(
1086 loader.instructions[1].operand,
1087 Some(crate::operand::Operand::new_number(1))
1088 );
1089 assert_eq!(
1090 loader.instructions[2].opcode,
1091 crate::opcode::Opcode::PushNumber
1092 );
1093 assert_eq!(
1094 loader.instructions[2].operand,
1095 Some(crate::operand::Operand::new_number(1))
1096 );
1097 assert_eq!(
1098 loader.instructions[3].opcode,
1099 crate::opcode::Opcode::PushNumber
1100 );
1101 assert_eq!(
1102 loader.instructions[3].operand,
1103 Some(crate::operand::Operand::new_float("3.14".to_string()))
1104 );
1105 assert_eq!(
1106 loader.instructions[4].opcode,
1107 crate::opcode::Opcode::PushString
1108 );
1109 assert_eq!(
1110 loader.instructions[4].operand,
1111 Some(crate::operand::Operand::new_string("abc"))
1112 );
1113 assert_eq!(
1114 loader.instructions[5].opcode,
1115 crate::opcode::Opcode::PushString
1116 );
1117 assert_eq!(
1118 loader.instructions[5].operand,
1119 Some(crate::operand::Operand::new_string("abc"))
1120 );
1121 assert_eq!(
1122 loader.instructions[6].opcode,
1123 crate::opcode::Opcode::PushString
1124 );
1125 assert_eq!(
1126 loader.instructions[6].operand,
1127 Some(crate::operand::Operand::new_string("abc"))
1128 );
1129 assert_eq!(loader.instructions[7].opcode, crate::opcode::Opcode::Pi);
1130 assert_eq!(loader.instructions[7].operand, None);
1131 assert_eq!(loader.instructions[8].opcode, crate::opcode::Opcode::Ret);
1132 assert_eq!(loader.instructions[8].operand, None);
1133 }
1134
1135 #[test]
1136 fn test_start_block_addresses() {
1137 let reader = std::io::Cursor::new(vec![
1138 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x41, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x26, 0x01, 0xF3, 0x05, 0x14, 0xF4, 0x00, 0x01, 0x14, 0xF5, 0x00, 0x00, 0x00, 0x01, 0x14, 0xF6, 0x33, 0x2e, 0x31, 0x34, 0x00, 0x15, 0xF0, 0x00, 0x15, 0xF1, 0x00, 0x00, 0x02, 0xF3, 0x02, 0x15, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x07, ]);
1178 let loader = BytecodeLoaderBuilder::new(reader).build().unwrap();
1179
1180 assert_eq!(loader.block_breaks.len(), 7);
1181 assert!(loader.block_breaks.contains(&0));
1182 assert!(loader.block_breaks.contains(&1));
1183 assert!(loader.block_breaks.contains(&2));
1184 assert!(loader.block_breaks.contains(&3));
1185 assert!(loader.block_breaks.contains(&5));
1186 assert!(loader.block_breaks.contains(&7));
1187 assert!(loader.block_breaks.contains(&10));
1188 }
1189
1190 #[test]
1191 fn test_invalid_blocks() {
1192 let reader = std::io::Cursor::new(vec![
1193 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x41, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x26, 0x01, 0xF3, 0x05, 0x14, 0xF4, 0x00, 0x01, 0x14, 0xF5, 0x00, 0x00, 0x00, 0x01, 0x14, 0xF6, 0x33, 0x2e, 0x31, 0x34, 0x00, 0x15, 0xF0, 0x00, 0x15, 0xF1, 0x00, 0x00, 0x02, 0xF3, 0xFF, 0x15, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x07, ]);
1233
1234 let loader = BytecodeLoaderBuilder::new(reader).build();
1236 assert!(loader.is_err());
1237 }
1238}