123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- // Copyright 2017 Rich Lane <lanerl@gmail.com>
- //
- // Licensed under the Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
- // the MIT license <http://opensource.org/licenses/MIT>, at your option. This file may not be
- // copied, modified, or distributed except according to those terms.
- extern crate rbpf;
- extern crate combine;
- use rbpf::asm_parser::{Instruction, Operand, parse};
- #[test]
- fn test_empty() {
- assert_eq!(parse(""), Ok(vec![]));
- }
- #[test]
- fn test_exit() {
- // No operands.
- assert_eq!(parse("exit"),
- Ok(vec![Instruction {
- name: "exit".to_string(),
- operands: vec![],
- }]));
- }
- #[test]
- fn test_lsh() {
- // Register and immediate operands.
- assert_eq!(parse("lsh r3, 0x20"),
- Ok(vec![Instruction {
- name: "lsh".to_string(),
- operands: vec![Operand::Register(3), Operand::Integer(0x20)],
- }]));
- }
- #[test]
- fn test_ja() {
- // Jump offset operand.
- assert_eq!(parse("ja +1"),
- Ok(vec![Instruction {
- name: "ja".to_string(),
- operands: vec![Operand::Integer(1)],
- }]));
- }
- #[test]
- fn test_ldxh() {
- // Register and memory operands.
- assert_eq!(parse("ldxh r4, [r1+12]"),
- Ok(vec![Instruction {
- name: "ldxh".to_string(),
- operands: vec![Operand::Register(4), Operand::Memory(1, 12)],
- }]));
- }
- #[test]
- fn test_tcp_sack() {
- // Sample program from ubpf.
- let src = "\
- ldxb r2, [r1+12]
- ldxb r3, [r1+13]
- lsh r3, 0x8
- or r3, r2
- mov r0, 0x0
- jne r3, 0x8, +37
- ldxb r2, [r1+23]
- jne r2, 0x6, +35
- ldxb r2, [r1+14]
- add r1, 0xe
- and r2, 0xf
- lsh r2, 0x2
- add r1, r2
- mov r0, 0x0
- ldxh r4, [r1+12]
- add r1, 0x14
- rsh r4, 0x2
- and r4, 0x3c
- mov r2, r4
- add r2, 0xffffffec
- mov r5, 0x15
- mov r3, 0x0
- jgt r5, r4, +20
- mov r5, r3
- lsh r5, 0x20
- arsh r5, 0x20
- mov r4, r1
- add r4, r5
- ldxb r5, [r4]
- jeq r5, 0x1, +4
- jeq r5, 0x0, +12
- mov r6, r3
- jeq r5, 0x5, +9
- ja +2
- add r3, 0x1
- mov r6, r3
- ldxb r3, [r4+1]
- add r3, r6
- lsh r3, 0x20
- arsh r3, 0x20
- jsgt r2, r3, -18
- ja +1
- mov r0, 0x1
- exit
- ";
- assert_eq!(parse(src),
- Ok(vec![Instruction {
- name: "ldxb".to_string(),
- operands: vec![Operand::Register(2), Operand::Memory(1, 12)],
- },
- Instruction {
- name: "ldxb".to_string(),
- operands: vec![Operand::Register(3), Operand::Memory(1, 13)],
- },
- Instruction {
- name: "lsh".to_string(),
- operands: vec![Operand::Register(3), Operand::Integer(8)],
- },
- Instruction {
- name: "or".to_string(),
- operands: vec![Operand::Register(3), Operand::Register(2)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(0), Operand::Integer(0)],
- },
- Instruction {
- name: "jne".to_string(),
- operands: vec![Operand::Register(3),
- Operand::Integer(8),
- Operand::Integer(37)],
- },
- Instruction {
- name: "ldxb".to_string(),
- operands: vec![Operand::Register(2), Operand::Memory(1, 23)],
- },
- Instruction {
- name: "jne".to_string(),
- operands: vec![Operand::Register(2),
- Operand::Integer(6),
- Operand::Integer(35)],
- },
- Instruction {
- name: "ldxb".to_string(),
- operands: vec![Operand::Register(2), Operand::Memory(1, 14)],
- },
- Instruction {
- name: "add".to_string(),
- operands: vec![Operand::Register(1), Operand::Integer(14)],
- },
- Instruction {
- name: "and".to_string(),
- operands: vec![Operand::Register(2), Operand::Integer(15)],
- },
- Instruction {
- name: "lsh".to_string(),
- operands: vec![Operand::Register(2), Operand::Integer(2)],
- },
- Instruction {
- name: "add".to_string(),
- operands: vec![Operand::Register(1), Operand::Register(2)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(0), Operand::Integer(0)],
- },
- Instruction {
- name: "ldxh".to_string(),
- operands: vec![Operand::Register(4), Operand::Memory(1, 12)],
- },
- Instruction {
- name: "add".to_string(),
- operands: vec![Operand::Register(1), Operand::Integer(20)],
- },
- Instruction {
- name: "rsh".to_string(),
- operands: vec![Operand::Register(4), Operand::Integer(2)],
- },
- Instruction {
- name: "and".to_string(),
- operands: vec![Operand::Register(4), Operand::Integer(60)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(2), Operand::Register(4)],
- },
- Instruction {
- name: "add".to_string(),
- operands: vec![Operand::Register(2), Operand::Integer(4294967276)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(5), Operand::Integer(21)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(3), Operand::Integer(0)],
- },
- Instruction {
- name: "jgt".to_string(),
- operands: vec![Operand::Register(5),
- Operand::Register(4),
- Operand::Integer(20)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(5), Operand::Register(3)],
- },
- Instruction {
- name: "lsh".to_string(),
- operands: vec![Operand::Register(5), Operand::Integer(32)],
- },
- Instruction {
- name: "arsh".to_string(),
- operands: vec![Operand::Register(5), Operand::Integer(32)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(4), Operand::Register(1)],
- },
- Instruction {
- name: "add".to_string(),
- operands: vec![Operand::Register(4), Operand::Register(5)],
- },
- Instruction {
- name: "ldxb".to_string(),
- operands: vec![Operand::Register(5), Operand::Memory(4, 0)],
- },
- Instruction {
- name: "jeq".to_string(),
- operands: vec![Operand::Register(5),
- Operand::Integer(1),
- Operand::Integer(4)],
- },
- Instruction {
- name: "jeq".to_string(),
- operands: vec![Operand::Register(5),
- Operand::Integer(0),
- Operand::Integer(12)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(6), Operand::Register(3)],
- },
- Instruction {
- name: "jeq".to_string(),
- operands: vec![Operand::Register(5),
- Operand::Integer(5),
- Operand::Integer(9)],
- },
- Instruction {
- name: "ja".to_string(),
- operands: vec![Operand::Integer(2)],
- },
- Instruction {
- name: "add".to_string(),
- operands: vec![Operand::Register(3), Operand::Integer(1)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(6), Operand::Register(3)],
- },
- Instruction {
- name: "ldxb".to_string(),
- operands: vec![Operand::Register(3), Operand::Memory(4, 1)],
- },
- Instruction {
- name: "add".to_string(),
- operands: vec![Operand::Register(3), Operand::Register(6)],
- },
- Instruction {
- name: "lsh".to_string(),
- operands: vec![Operand::Register(3), Operand::Integer(32)],
- },
- Instruction {
- name: "arsh".to_string(),
- operands: vec![Operand::Register(3), Operand::Integer(32)],
- },
- Instruction {
- name: "jsgt".to_string(),
- operands: vec![Operand::Register(2),
- Operand::Register(3),
- Operand::Integer(-18)],
- },
- Instruction {
- name: "ja".to_string(),
- operands: vec![Operand::Integer(1)],
- },
- Instruction {
- name: "mov".to_string(),
- operands: vec![Operand::Register(0), Operand::Integer(1)],
- },
- Instruction {
- name: "exit".to_string(),
- operands: vec![],
- }]));
- }
- #[test]
- fn test_error_eof() {
- // Unexpected end of input in a register name.
- assert_eq!(parse("lsh r"),
- Err("Parse error at line 1 column 6: unexpected end of input, expected digit"
- .to_string()));
- }
- #[test]
- fn test_error_unexpected_character() {
- // Unexpected character at end of input.
- assert_eq!(parse("exit\n^"),
- Err("Parse error at line 2 column 1: unexpected '^', expected end of input"
- .to_string()));
- }
- #[test]
- fn test_initial_whitespace() {
- assert_eq!(parse("
- exit"),
- Ok(vec![Instruction {
- name: "exit".to_string(),
- operands: vec![],
- }]));
- }
|