xref: /DragonOS/kernel/crates/rbpf/tests/disassembler.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
1 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
2 // Copyright 2017 Jan-Erik Rediger <badboy@archlinux.us>
3 //
4 // Adopted from tests in `tests/assembler.rs`
5 
6 extern crate rbpf;
7 mod common;
8 
9 use rbpf::{assembler::assemble, disassembler::to_insn_vec};
10 
11 // Using a macro to keep actual line numbers in failure output
12 macro_rules! disasm {
13     ($src:expr) => {{
14         let src = $src;
15         let asm = assemble(src).expect("Can't assemble from string");
16         let insn = to_insn_vec(&asm);
17         let reasm = insn
18             .into_iter()
19             .map(|ins| ins.desc)
20             .collect::<Vec<_>>()
21             .join("\n");
22 
23         assert_eq!(src, reasm);
24     }};
25 }
26 
27 #[test]
test_empty()28 fn test_empty() {
29     disasm!("");
30 }
31 
32 // Example for InstructionType::NoOperand.
33 #[test]
test_exit()34 fn test_exit() {
35     disasm!("exit");
36 }
37 
38 // Example for InstructionType::AluBinary.
39 #[test]
test_add64()40 fn test_add64() {
41     disasm!("add64 r1, r3");
42     disasm!("add64 r1, 0x5");
43 }
44 
45 // Example for InstructionType::AluUnary.
46 #[test]
test_neg64()47 fn test_neg64() {
48     disasm!("neg64 r1");
49 }
50 
51 // Example for InstructionType::LoadReg.
52 #[test]
test_ldxw()53 fn test_ldxw() {
54     disasm!("ldxw r1, [r2+0x5]");
55 }
56 
57 // Example for InstructionType::StoreImm.
58 #[test]
test_stw()59 fn test_stw() {
60     disasm!("stw [r2+0x5], 0x7");
61 }
62 
63 // Example for InstructionType::StoreReg.
64 #[test]
test_stxw()65 fn test_stxw() {
66     disasm!("stxw [r2+0x5], r8");
67 }
68 
69 // Example for InstructionType::JumpUnconditional.
70 #[test]
test_ja()71 fn test_ja() {
72     disasm!("ja +0x8");
73 }
74 
75 // Example for InstructionType::JumpConditional.
76 #[test]
test_jeq()77 fn test_jeq() {
78     disasm!("jeq r1, 0x4, +0x8");
79     disasm!("jeq r1, r3, +0x8");
80 }
81 
82 // Example for InstructionType::Call.
83 #[test]
test_call()84 fn test_call() {
85     disasm!("call 0x3");
86 }
87 
88 // Example for InstructionType::Endian.
89 #[test]
test_be32()90 fn test_be32() {
91     disasm!("be32 r1");
92 }
93 
94 // Example for InstructionType::LoadImm.
95 #[test]
test_lddw()96 fn test_lddw() {
97     disasm!("lddw r1, 0x1234abcd5678eeff");
98     disasm!("lddw r1, 0xff11ee22dd33cc44");
99 }
100 
101 // Example for InstructionType::LoadAbs.
102 #[test]
test_ldabsw()103 fn test_ldabsw() {
104     disasm!("ldabsw 0x1");
105 }
106 
107 // Example for InstructionType::LoadInd.
108 #[test]
test_ldindw()109 fn test_ldindw() {
110     disasm!("ldindw r1, 0x2");
111 }
112 
113 // Example for InstructionType::LoadReg.
114 #[test]
test_ldxdw()115 fn test_ldxdw() {
116     disasm!("ldxdw r1, [r2+0x3]");
117 }
118 
119 // Example for InstructionType::StoreImm.
120 #[test]
test_sth()121 fn test_sth() {
122     disasm!("sth [r1+0x2], 0x3");
123 }
124 
125 // Example for InstructionType::StoreReg.
126 #[test]
test_stxh()127 fn test_stxh() {
128     disasm!("stxh [r1+0x2], r3");
129 }
130 
131 // Test all supported AluBinary mnemonics.
132 #[test]
test_alu_binary()133 fn test_alu_binary() {
134     disasm!(
135         "add64 r1, r2
136 sub64 r1, r2
137 mul64 r1, r2
138 div64 r1, r2
139 or64 r1, r2
140 and64 r1, r2
141 lsh64 r1, r2
142 rsh64 r1, r2
143 mod64 r1, r2
144 xor64 r1, r2
145 mov64 r1, r2
146 arsh64 r1, r2"
147     );
148 
149     disasm!(
150         "add64 r1, 0x2
151 sub64 r1, 0x2
152 mul64 r1, 0x2
153 div64 r1, 0x2
154 or64 r1, 0x2
155 and64 r1, 0x2
156 lsh64 r1, 0x2
157 rsh64 r1, 0x2
158 mod64 r1, 0x2
159 xor64 r1, 0x2
160 mov64 r1, 0x2
161 arsh64 r1, 0x2"
162     );
163 
164     disasm!(
165         "add32 r1, r2
166 sub32 r1, r2
167 mul32 r1, r2
168 div32 r1, r2
169 or32 r1, r2
170 and32 r1, r2
171 lsh32 r1, r2
172 rsh32 r1, r2
173 mod32 r1, r2
174 xor32 r1, r2
175 mov32 r1, r2
176 arsh32 r1, r2"
177     );
178 
179     disasm!(
180         "add32 r1, 0x2
181 sub32 r1, 0x2
182 mul32 r1, 0x2
183 div32 r1, 0x2
184 or32 r1, 0x2
185 and32 r1, 0x2
186 lsh32 r1, 0x2
187 rsh32 r1, 0x2
188 mod32 r1, 0x2
189 xor32 r1, 0x2
190 mov32 r1, 0x2
191 arsh32 r1, 0x2"
192     );
193 }
194 
195 // Test all supported AluUnary mnemonics.
196 #[test]
test_alu_unary()197 fn test_alu_unary() {
198     disasm!(
199         "neg64 r1
200 neg32 r1"
201     );
202 }
203 
204 // Test all supported LoadAbs mnemonics.
205 #[test]
test_load_abs()206 fn test_load_abs() {
207     disasm!(
208         "ldabsw 0x1
209 ldabsh 0x1
210 ldabsb 0x1
211 ldabsdw 0x1"
212     );
213 }
214 
215 // Test all supported LoadInd mnemonics.
216 #[test]
test_load_ind()217 fn test_load_ind() {
218     disasm!(
219         "ldindw r1, 0x2
220 ldindh r1, 0x2
221 ldindb r1, 0x2
222 ldinddw r1, 0x2"
223     );
224 }
225 
226 // Test all supported LoadReg mnemonics.
227 #[test]
test_load_reg()228 fn test_load_reg() {
229     disasm!(
230         r"ldxw r1, [r2+0x3]
231 ldxh r1, [r2+0x3]
232 ldxb r1, [r2+0x3]
233 ldxdw r1, [r2+0x3]"
234     );
235 }
236 
237 // Test all supported StoreImm mnemonics.
238 #[test]
test_store_imm()239 fn test_store_imm() {
240     disasm!(
241         "stw [r1+0x2], 0x3
242 sth [r1+0x2], 0x3
243 stb [r1+0x2], 0x3
244 stdw [r1+0x2], 0x3"
245     );
246 }
247 
248 // Test all supported StoreReg mnemonics.
249 #[test]
test_store_reg()250 fn test_store_reg() {
251     disasm!(
252         "stxw [r1+0x2], r3
253 stxh [r1+0x2], r3
254 stxb [r1+0x2], r3
255 stxdw [r1+0x2], r3"
256     );
257 }
258 
259 // Test all supported JumpConditional mnemonics.
260 #[test]
test_jump_conditional()261 fn test_jump_conditional() {
262     disasm!(
263         "jeq r1, r2, +0x3
264 jgt r1, r2, +0x3
265 jge r1, r2, +0x3
266 jlt r1, r2, +0x3
267 jle r1, r2, +0x3
268 jset r1, r2, +0x3
269 jne r1, r2, +0x3
270 jsgt r1, r2, +0x3
271 jsge r1, r2, -0x3
272 jslt r1, r2, +0x3
273 jsle r1, r2, -0x3"
274     );
275 
276     disasm!(
277         "jeq r1, 0x2, +0x3
278 jgt r1, 0x2, +0x3
279 jge r1, 0x2, +0x3
280 jlt r1, 0x2, +0x3
281 jle r1, 0x2, +0x3
282 jset r1, 0x2, +0x3
283 jne r1, 0x2, +0x3
284 jsgt r1, 0x2, +0x3
285 jsge r1, 0x2, -0x3
286 jslt r1, 0x2, +0x3
287 jsle r1, 0x2, -0x3"
288     );
289 
290     disasm!(
291         "jeq32 r1, r2, +0x3
292 jgt32 r1, r2, +0x3
293 jge32 r1, r2, +0x3
294 jlt32 r1, r2, +0x3
295 jle32 r1, r2, +0x3
296 jset32 r1, r2, +0x3
297 jne32 r1, r2, +0x3
298 jsgt32 r1, r2, +0x3
299 jsge32 r1, r2, -0x3
300 jslt32 r1, r2, +0x3
301 jsle32 r1, r2, -0x3"
302     );
303 
304     disasm!(
305         "jeq32 r1, 0x2, +0x3
306 jgt32 r1, 0x2, +0x3
307 jge32 r1, 0x2, +0x3
308 jlt32 r1, 0x2, +0x3
309 jle32 r1, 0x2, +0x3
310 jset32 r1, 0x2, +0x3
311 jne32 r1, 0x2, +0x3
312 jsgt32 r1, 0x2, +0x3
313 jsge32 r1, 0x2, -0x3
314 jslt32 r1, 0x2, +0x3
315 jsle32 r1, 0x2, -0x3"
316     );
317 }
318 
319 // Test all supported Endian mnemonics.
320 #[test]
test_endian()321 fn test_endian() {
322     disasm!(
323         "be16 r1
324 be32 r1
325 be64 r1
326 le16 r1
327 le32 r1
328 le64 r1"
329     );
330 }
331 
332 #[test]
test_large_immediate()333 fn test_large_immediate() {
334     disasm!("add64 r1, 0x7fffffff");
335     disasm!("add64 r1, 0x7fffffff");
336 }
337 
338 // Non-regression tests for overflow when trying to negate offset 0x8000i16.
339 #[test]
test_offset_overflow()340 fn test_offset_overflow() {
341     let insns = [
342         0x62, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stw
343         0x6a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // sth
344         0x72, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stb
345         0x7a, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, // stdw
346         0x61, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxw
347         0x69, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxh
348         0x71, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxb
349         0x79, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // ldxdw
350         0x15, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq (imm)
351         0x1d, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq (reg)
352         0x16, 0x01, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, // jeq32 (imm)
353         0x1e, 0x21, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, // jeq32 (reg)
354     ];
355 
356     let expected_output = "stw [r1-0x8000], 0x1
357 sth [r1-0x8000], 0x1
358 stb [r1-0x8000], 0x1
359 stdw [r1-0x8000], 0x1
360 ldxw r1, [r0-0x8000]
361 ldxh r1, [r0-0x8000]
362 ldxb r1, [r0-0x8000]
363 ldxdw r1, [r0-0x8000]
364 jeq r1, 0x2, -0x8000
365 jeq r1, r2, -0x8000
366 jeq32 r1, 0x2, -0x8000
367 jeq32 r1, r2, -0x8000";
368 
369     let prog = to_insn_vec(&insns);
370     let asm = prog
371         .into_iter()
372         .map(|ins| ins.desc)
373         .collect::<Vec<_>>()
374         .join("\n");
375 
376     assert_eq!(asm, expected_output);
377 }
378