jit.rs 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
  2. // Derived from uBPF <https://github.com/iovisor/ubpf>
  3. // Copyright 2015 Big Switch Networks, Inc
  4. // (uBPF: JIT algorithm, originally in C)
  5. // Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
  6. // (Translation to Rust, MetaBuff addition)
  7. use std::{
  8. fmt::{Error as FormatterError, Formatter},
  9. io::{Error, ErrorKind},
  10. mem,
  11. ops::{Index, IndexMut},
  12. };
  13. use crate::{ebpf, HashMap};
  14. extern crate libc;
  15. type MachineCode = unsafe fn(*mut u8, usize, *mut u8, usize, usize, usize) -> u64;
  16. const PAGE_SIZE: usize = 4096;
  17. // TODO: check how long the page must be to be sure to support an eBPF program of maximum possible
  18. // length
  19. const NUM_PAGES: usize = 1;
  20. // Special values for target_pc in struct Jump
  21. const TARGET_OFFSET: isize = ebpf::PROG_MAX_INSNS as isize;
  22. const TARGET_PC_EXIT: isize = TARGET_OFFSET + 1;
  23. #[derive(Copy, Clone)]
  24. enum OperandSize {
  25. S8 = 8,
  26. S16 = 16,
  27. S32 = 32,
  28. S64 = 64,
  29. }
  30. // Registers
  31. const RAX: u8 = 0;
  32. const RCX: u8 = 1;
  33. const RDX: u8 = 2;
  34. const RBX: u8 = 3;
  35. const RSP: u8 = 4;
  36. const RBP: u8 = 5;
  37. const RSI: u8 = 6;
  38. const RDI: u8 = 7;
  39. const R8: u8 = 8;
  40. const R9: u8 = 9;
  41. const R10: u8 = 10;
  42. const R11: u8 = 11;
  43. //const R12: u8 = 12;
  44. const R13: u8 = 13;
  45. const R14: u8 = 14;
  46. const R15: u8 = 15;
  47. const REGISTER_MAP_SIZE: usize = 11;
  48. const REGISTER_MAP: [u8; REGISTER_MAP_SIZE] = [
  49. RAX, // 0 return value
  50. RDI, // 1 arg 1
  51. RSI, // 2 arg 2
  52. RDX, // 3 arg 3
  53. R9, // 4 arg 4
  54. R8, // 5 arg 5
  55. RBX, // 6 callee-saved
  56. R13, // 7 callee-saved
  57. R14, // 8 callee-saved
  58. R15, // 9 callee-saved
  59. RBP, // 10 stack pointer
  60. // R10 and R11 are used to compute store a constant pointer to mem and to compute offset for
  61. // LD_ABS_* and LD_IND_* operations, so they are not mapped to any eBPF register.
  62. ];
  63. // Return the x86 register for the given eBPF register
  64. fn map_register(r: u8) -> u8 {
  65. assert!(r < REGISTER_MAP_SIZE as u8);
  66. REGISTER_MAP[(r % REGISTER_MAP_SIZE as u8) as usize]
  67. }
  68. macro_rules! emit_bytes {
  69. ( $mem:ident, $data:tt, $t:ty ) => {{
  70. let size = mem::size_of::<$t>() as usize;
  71. assert!($mem.offset + size <= $mem.contents.len());
  72. unsafe {
  73. let mut ptr = $mem.contents.as_ptr().add($mem.offset) as *mut $t;
  74. ptr.write_unaligned($data);
  75. }
  76. $mem.offset += size;
  77. }};
  78. }
  79. #[derive(Debug)]
  80. struct Jump {
  81. offset_loc: usize,
  82. target_pc: isize,
  83. }
  84. #[derive(Debug)]
  85. struct JitCompiler {
  86. pc_locs: Vec<usize>,
  87. special_targets: HashMap<isize, usize>,
  88. jumps: Vec<Jump>,
  89. }
  90. impl JitCompiler {
  91. fn new() -> JitCompiler {
  92. JitCompiler {
  93. pc_locs: vec![],
  94. jumps: vec![],
  95. special_targets: HashMap::new(),
  96. }
  97. }
  98. fn emit1(&self, mem: &mut JitMemory, data: u8) {
  99. emit_bytes!(mem, data, u8);
  100. }
  101. fn emit2(&self, mem: &mut JitMemory, data: u16) {
  102. emit_bytes!(mem, data, u16);
  103. }
  104. fn emit4(&self, mem: &mut JitMemory, data: u32) {
  105. emit_bytes!(mem, data, u32);
  106. }
  107. fn emit8(&self, mem: &mut JitMemory, data: u64) {
  108. emit_bytes!(mem, data, u64);
  109. }
  110. fn emit_modrm(&self, mem: &mut JitMemory, modrm: u8, r: u8, m: u8) {
  111. assert_eq!((modrm | 0xc0), 0xc0);
  112. self.emit1(mem, (modrm & 0xc0) | ((r & 0b111) << 3) | (m & 0b111));
  113. }
  114. fn emit_modrm_reg2reg(&self, mem: &mut JitMemory, r: u8, m: u8) {
  115. self.emit_modrm(mem, 0xc0, r, m);
  116. }
  117. fn emit_modrm_and_displacement(&self, mem: &mut JitMemory, r: u8, m: u8, d: i32) {
  118. if d == 0 && (m & 0b111) != RBP {
  119. self.emit_modrm(mem, 0x00, r, m);
  120. } else if (-128..=127).contains(&d) {
  121. self.emit_modrm(mem, 0x40, r, m);
  122. self.emit1(mem, d as u8);
  123. } else {
  124. self.emit_modrm(mem, 0x80, r, m);
  125. self.emit4(mem, d as u32);
  126. }
  127. }
  128. fn basix_rex_would_set_bits(&self, w: u8, src: u8, dst: u8) -> bool {
  129. w != 0 || (src & 0b1000) != 0 || (dst & 0b1000) != 0
  130. }
  131. fn emit_rex(&self, mem: &mut JitMemory, w: u8, r: u8, x: u8, b: u8) {
  132. assert_eq!((w | 1), 1);
  133. assert_eq!((r | 1), 1);
  134. assert_eq!((x | 1), 1);
  135. assert_eq!((b | 1), 1);
  136. self.emit1(mem, 0x40 | (w << 3) | (r << 2) | (x << 1) | b);
  137. }
  138. // Emits a REX prefix with the top bit of src and dst.
  139. // Skipped if no bits would be set.
  140. fn emit_basic_rex(&self, mem: &mut JitMemory, w: u8, src: u8, dst: u8) {
  141. if self.basix_rex_would_set_bits(w, src, dst) {
  142. let is_masked = |val, mask| match val & mask {
  143. 0 => 0,
  144. _ => 1,
  145. };
  146. self.emit_rex(mem, w, is_masked(src, 8), 0, is_masked(dst, 8));
  147. }
  148. }
  149. fn emit_push(&self, mem: &mut JitMemory, r: u8) {
  150. self.emit_basic_rex(mem, 0, 0, r);
  151. self.emit1(mem, 0x50 | (r & 0b111));
  152. }
  153. fn emit_pop(&self, mem: &mut JitMemory, r: u8) {
  154. self.emit_basic_rex(mem, 0, 0, r);
  155. self.emit1(mem, 0x58 | (r & 0b111));
  156. }
  157. // REX prefix and ModRM byte
  158. // We use the MR encoding when there is a choice
  159. // 'src' is often used as an opcode extension
  160. fn emit_alu32(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8) {
  161. self.emit_basic_rex(mem, 0, src, dst);
  162. self.emit1(mem, op);
  163. self.emit_modrm_reg2reg(mem, src, dst);
  164. }
  165. // REX prefix, ModRM byte, and 32-bit immediate
  166. fn emit_alu32_imm32(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i32) {
  167. self.emit_alu32(mem, op, src, dst);
  168. self.emit4(mem, imm as u32);
  169. }
  170. // REX prefix, ModRM byte, and 8-bit immediate
  171. fn emit_alu32_imm8(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i8) {
  172. self.emit_alu32(mem, op, src, dst);
  173. self.emit1(mem, imm as u8);
  174. }
  175. // REX.W prefix and ModRM byte
  176. // We use the MR encoding when there is a choice
  177. // 'src' is often used as an opcode extension
  178. fn emit_alu64(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8) {
  179. self.emit_basic_rex(mem, 1, src, dst);
  180. self.emit1(mem, op);
  181. self.emit_modrm_reg2reg(mem, src, dst);
  182. }
  183. // REX.W prefix, ModRM byte, and 32-bit immediate
  184. fn emit_alu64_imm32(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i32) {
  185. self.emit_alu64(mem, op, src, dst);
  186. self.emit4(mem, imm as u32);
  187. }
  188. // REX.W prefix, ModRM byte, and 8-bit immediate
  189. fn emit_alu64_imm8(&self, mem: &mut JitMemory, op: u8, src: u8, dst: u8, imm: i8) {
  190. self.emit_alu64(mem, op, src, dst);
  191. self.emit1(mem, imm as u8);
  192. }
  193. // Register to register mov
  194. fn emit_mov(&self, mem: &mut JitMemory, src: u8, dst: u8) {
  195. self.emit_alu64(mem, 0x89, src, dst);
  196. }
  197. fn emit_cmp_imm32(&self, mem: &mut JitMemory, dst: u8, imm: i32) {
  198. self.emit_alu64_imm32(mem, 0x81, 7, dst, imm);
  199. }
  200. fn emit_cmp(&self, mem: &mut JitMemory, src: u8, dst: u8) {
  201. self.emit_alu64(mem, 0x39, src, dst);
  202. }
  203. fn emit_cmp32_imm32(&self, mem: &mut JitMemory, dst: u8, imm: i32) {
  204. self.emit_alu32_imm32(mem, 0x81, 7, dst, imm);
  205. }
  206. fn emit_cmp32(&self, mem: &mut JitMemory, src: u8, dst: u8) {
  207. self.emit_alu32(mem, 0x39, src, dst);
  208. }
  209. // Load [src + offset] into dst
  210. fn emit_load(&self, mem: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
  211. let data = match size {
  212. OperandSize::S64 => 1,
  213. _ => 0,
  214. };
  215. self.emit_basic_rex(mem, data, dst, src);
  216. match size {
  217. OperandSize::S8 => {
  218. // movzx
  219. self.emit1(mem, 0x0f);
  220. self.emit1(mem, 0xb6);
  221. }
  222. OperandSize::S16 => {
  223. // movzx
  224. self.emit1(mem, 0x0f);
  225. self.emit1(mem, 0xb7);
  226. }
  227. OperandSize::S32 | OperandSize::S64 => {
  228. // mov
  229. self.emit1(mem, 0x8b);
  230. }
  231. }
  232. self.emit_modrm_and_displacement(mem, dst, src, offset);
  233. }
  234. // Load sign-extended immediate into register
  235. fn emit_load_imm(&self, mem: &mut JitMemory, dst: u8, imm: i64) {
  236. if imm >= i32::MIN as i64 && imm <= i32::MAX as i64 {
  237. self.emit_alu64_imm32(mem, 0xc7, 0, dst, imm as i32);
  238. } else {
  239. // movabs $imm,dst
  240. self.emit_basic_rex(mem, 1, 0, dst);
  241. self.emit1(mem, 0xb8 | (dst & 0b111));
  242. self.emit8(mem, imm as u64);
  243. }
  244. }
  245. // Store register src to [dst + offset]
  246. fn emit_store(&self, mem: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
  247. match size {
  248. OperandSize::S16 => self.emit1(mem, 0x66), // 16-bit override
  249. _ => {}
  250. };
  251. let (is_s8, is_u64, rexw) = match size {
  252. OperandSize::S8 => (true, false, 0),
  253. OperandSize::S64 => (false, true, 1),
  254. _ => (false, false, 0),
  255. };
  256. if is_u64 || (src & 0b1000) != 0 || (dst & 0b1000) != 0 || is_s8 {
  257. let is_masked = |val, mask| match val & mask {
  258. 0 => 0,
  259. _ => 1,
  260. };
  261. self.emit_rex(mem, rexw, is_masked(src, 8), 0, is_masked(dst, 8));
  262. }
  263. match size {
  264. OperandSize::S8 => self.emit1(mem, 0x88),
  265. _ => self.emit1(mem, 0x89),
  266. };
  267. self.emit_modrm_and_displacement(mem, src, dst, offset);
  268. }
  269. // Store immediate to [dst + offset]
  270. fn emit_store_imm32(
  271. &self,
  272. mem: &mut JitMemory,
  273. size: OperandSize,
  274. dst: u8,
  275. offset: i32,
  276. imm: i32,
  277. ) {
  278. match size {
  279. OperandSize::S16 => self.emit1(mem, 0x66), // 16-bit override
  280. _ => {}
  281. };
  282. match size {
  283. OperandSize::S64 => self.emit_basic_rex(mem, 1, 0, dst),
  284. _ => self.emit_basic_rex(mem, 0, 0, dst),
  285. };
  286. match size {
  287. OperandSize::S8 => self.emit1(mem, 0xc6),
  288. _ => self.emit1(mem, 0xc7),
  289. };
  290. self.emit_modrm_and_displacement(mem, 0, dst, offset);
  291. match size {
  292. OperandSize::S8 => self.emit1(mem, imm as u8),
  293. OperandSize::S16 => self.emit2(mem, imm as u16),
  294. _ => self.emit4(mem, imm as u32),
  295. };
  296. }
  297. fn emit_direct_jcc(&self, mem: &mut JitMemory, code: u8, offset: u32) {
  298. self.emit1(mem, 0x0f);
  299. self.emit1(mem, code);
  300. emit_bytes!(mem, offset, u32);
  301. }
  302. fn emit_call(&self, mem: &mut JitMemory, target: usize) {
  303. // TODO use direct call when possible
  304. self.emit_load_imm(mem, RAX, target as i64);
  305. // callq *%rax
  306. self.emit1(mem, 0xff);
  307. self.emit1(mem, 0xd0);
  308. }
  309. fn emit_jump_offset(&mut self, mem: &mut JitMemory, target_pc: isize) {
  310. let jump = Jump {
  311. offset_loc: mem.offset,
  312. target_pc,
  313. };
  314. self.jumps.push(jump);
  315. self.emit4(mem, 0);
  316. }
  317. fn emit_jcc(&mut self, mem: &mut JitMemory, code: u8, target_pc: isize) {
  318. self.emit1(mem, 0x0f);
  319. self.emit1(mem, code);
  320. self.emit_jump_offset(mem, target_pc);
  321. }
  322. fn emit_jmp(&mut self, mem: &mut JitMemory, target_pc: isize) {
  323. self.emit1(mem, 0xe9);
  324. self.emit_jump_offset(mem, target_pc);
  325. }
  326. fn set_anchor(&mut self, mem: &mut JitMemory, target: isize) {
  327. self.special_targets.insert(target, mem.offset);
  328. }
  329. fn emit_muldivmod(
  330. &mut self,
  331. mem: &mut JitMemory,
  332. pc: u16,
  333. opc: u8,
  334. src: u8,
  335. dst: u8,
  336. imm: i32,
  337. ) {
  338. let mul = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::MUL32_IMM & ebpf::BPF_ALU_OP_MASK);
  339. let div = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::DIV32_IMM & ebpf::BPF_ALU_OP_MASK);
  340. let modrm = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::MOD32_IMM & ebpf::BPF_ALU_OP_MASK);
  341. let is64 = (opc & ebpf::BPF_CLS_MASK) == ebpf::BPF_ALU64;
  342. let is_reg = (opc & ebpf::BPF_X) == ebpf::BPF_X;
  343. if (div || mul) && !is_reg && imm == 0 {
  344. // Division by zero returns 0
  345. // Set register to 0: xor with itself
  346. self.emit_alu32(mem, 0x31, dst, dst);
  347. return;
  348. }
  349. if modrm && !is_reg && imm == 0 {
  350. // Modulo remainder of division by zero keeps destination register unchanged
  351. return;
  352. }
  353. if (div || modrm) && is_reg {
  354. self.emit_load_imm(mem, RCX, pc as i64);
  355. // test src,src
  356. if is64 {
  357. self.emit_alu64(mem, 0x85, src, src);
  358. } else {
  359. self.emit_alu32(mem, 0x85, src, src);
  360. }
  361. if div {
  362. // No division by 0: skip next instructions
  363. // Jump offset: emit_alu32 adds 2 to 3 bytes, emit_jmp adds 5
  364. let offset = match self.basix_rex_would_set_bits(0, dst, dst) {
  365. true => 3 + 5,
  366. false => 2 + 5,
  367. };
  368. self.emit_direct_jcc(mem, 0x85, offset);
  369. // Division by 0: set dst to 0 then go to next instruction
  370. // Set register to 0: xor with itself
  371. self.emit_alu32(mem, 0x31, dst, dst);
  372. self.emit_jmp(mem, (pc + 1) as isize);
  373. }
  374. if modrm {
  375. // Modulo by zero: keep destination register unchanged
  376. self.emit_jcc(mem, 0x84, (pc + 1) as isize);
  377. }
  378. }
  379. if dst != RAX {
  380. self.emit_push(mem, RAX);
  381. }
  382. if dst != RDX {
  383. self.emit_push(mem, RDX);
  384. }
  385. if imm != 0 {
  386. self.emit_load_imm(mem, RCX, imm as i64);
  387. } else {
  388. self.emit_mov(mem, src, RCX);
  389. }
  390. self.emit_mov(mem, dst, RAX);
  391. if div || modrm {
  392. // Set register to 0: xor %edx,%edx
  393. self.emit_alu32(mem, 0x31, RDX, RDX);
  394. }
  395. if is64 {
  396. self.emit_rex(mem, 1, 0, 0, 0);
  397. }
  398. // mul %ecx or div %ecx
  399. self.emit_alu32(mem, 0xf7, if mul { 4 } else { 6 }, RCX);
  400. if dst != RDX {
  401. if modrm {
  402. self.emit_mov(mem, RDX, dst);
  403. }
  404. self.emit_pop(mem, RDX);
  405. }
  406. if dst != RAX {
  407. if div || mul {
  408. self.emit_mov(mem, RAX, dst);
  409. }
  410. self.emit_pop(mem, RAX);
  411. }
  412. }
  413. fn jit_compile(
  414. &mut self,
  415. mem: &mut JitMemory,
  416. prog: &[u8],
  417. use_mbuff: bool,
  418. update_data_ptr: bool,
  419. helpers: &HashMap<u32, ebpf::Helper>,
  420. ) -> Result<(), Error> {
  421. self.emit_push(mem, RBP);
  422. self.emit_push(mem, RBX);
  423. self.emit_push(mem, R13);
  424. self.emit_push(mem, R14);
  425. self.emit_push(mem, R15);
  426. // RDI: mbuff
  427. // RSI: mbuff_len
  428. // RDX: mem
  429. // RCX: mem_len
  430. // R8: mem_offset
  431. // R9: mem_end_offset
  432. // Save mem pointer for use with LD_ABS_* and LD_IND_* instructions
  433. self.emit_mov(mem, RDX, R10);
  434. match (use_mbuff, update_data_ptr) {
  435. (false, _) => {
  436. // We do not use any mbuff. Move mem pointer into register 1.
  437. if map_register(1) != RDX {
  438. self.emit_mov(mem, RDX, map_register(1));
  439. }
  440. }
  441. (true, false) => {
  442. // We use a mbuff already pointing to mem and mem_end: move it to register 1.
  443. if map_register(1) != RDI {
  444. self.emit_mov(mem, RDI, map_register(1));
  445. }
  446. }
  447. (true, true) => {
  448. // We have a fixed (simulated) mbuff: update mem and mem_end offset values in it.
  449. // Store mem at mbuff + mem_offset. Trash R8.
  450. self.emit_alu64(mem, 0x01, RDI, R8); // add mbuff to mem_offset in R8
  451. self.emit_store(mem, OperandSize::S64, RDX, R8, 0); // set mem at mbuff + mem_offset
  452. // Store mem_end at mbuff + mem_end_offset. Trash R9.
  453. self.emit_load(mem, OperandSize::S64, RDX, R8, 0); // load mem into R8
  454. self.emit_alu64(mem, 0x01, RCX, R8); // add mem_len to mem (= mem_end)
  455. self.emit_alu64(mem, 0x01, RDI, R9); // add mbuff to mem_end_offset
  456. self.emit_store(mem, OperandSize::S64, R8, R9, 0); // store mem_end
  457. // Move rdi into register 1
  458. if map_register(1) != RDI {
  459. self.emit_mov(mem, RDI, map_register(1));
  460. }
  461. }
  462. }
  463. // Copy stack pointer to R10
  464. self.emit_mov(mem, RSP, map_register(10));
  465. // Allocate stack space
  466. self.emit_alu64_imm32(mem, 0x81, 5, RSP, ebpf::STACK_SIZE as i32);
  467. self.pc_locs = vec![0; prog.len() / ebpf::INSN_SIZE + 1];
  468. let mut insn_ptr: usize = 0;
  469. while insn_ptr * ebpf::INSN_SIZE < prog.len() {
  470. let insn = ebpf::get_insn(prog, insn_ptr);
  471. self.pc_locs[insn_ptr] = mem.offset;
  472. let dst = map_register(insn.dst);
  473. let src = map_register(insn.src);
  474. let target_pc = insn_ptr as isize + insn.off as isize + 1;
  475. match insn.opc {
  476. // BPF_LD class
  477. // R10 is a constant pointer to mem.
  478. ebpf::LD_ABS_B => self.emit_load(mem, OperandSize::S8, R10, RAX, insn.imm),
  479. ebpf::LD_ABS_H => self.emit_load(mem, OperandSize::S16, R10, RAX, insn.imm),
  480. ebpf::LD_ABS_W => self.emit_load(mem, OperandSize::S32, R10, RAX, insn.imm),
  481. ebpf::LD_ABS_DW => self.emit_load(mem, OperandSize::S64, R10, RAX, insn.imm),
  482. ebpf::LD_IND_B => {
  483. self.emit_mov(mem, R10, R11); // load mem into R11
  484. self.emit_alu64(mem, 0x01, src, R11); // add src to R11
  485. self.emit_load(mem, OperandSize::S8, R11, RAX, insn.imm); // ld R0, mem[src+imm]
  486. }
  487. ebpf::LD_IND_H => {
  488. self.emit_mov(mem, R10, R11); // load mem into R11
  489. self.emit_alu64(mem, 0x01, src, R11); // add src to R11
  490. self.emit_load(mem, OperandSize::S16, R11, RAX, insn.imm); // ld R0, mem[src+imm]
  491. }
  492. ebpf::LD_IND_W => {
  493. self.emit_mov(mem, R10, R11); // load mem into R11
  494. self.emit_alu64(mem, 0x01, src, R11); // add src to R11
  495. self.emit_load(mem, OperandSize::S32, R11, RAX, insn.imm); // ld R0, mem[src+imm]
  496. }
  497. ebpf::LD_IND_DW => {
  498. self.emit_mov(mem, R10, R11); // load mem into R11
  499. self.emit_alu64(mem, 0x01, src, R11); // add src to R11
  500. self.emit_load(mem, OperandSize::S64, R11, RAX, insn.imm); // ld R0, mem[src+imm]
  501. }
  502. ebpf::LD_DW_IMM => {
  503. insn_ptr += 1;
  504. let second_part = ebpf::get_insn(prog, insn_ptr).imm as u64;
  505. let imm = (insn.imm as u32) as u64 | second_part.wrapping_shl(32);
  506. self.emit_load_imm(mem, dst, imm as i64);
  507. }
  508. // BPF_LDX class
  509. ebpf::LD_B_REG => self.emit_load(mem, OperandSize::S8, src, dst, insn.off as i32),
  510. ebpf::LD_H_REG => self.emit_load(mem, OperandSize::S16, src, dst, insn.off as i32),
  511. ebpf::LD_W_REG => self.emit_load(mem, OperandSize::S32, src, dst, insn.off as i32),
  512. ebpf::LD_DW_REG => self.emit_load(mem, OperandSize::S64, src, dst, insn.off as i32),
  513. // BPF_ST class
  514. ebpf::ST_B_IMM => {
  515. self.emit_store_imm32(mem, OperandSize::S8, dst, insn.off as i32, insn.imm)
  516. }
  517. ebpf::ST_H_IMM => {
  518. self.emit_store_imm32(mem, OperandSize::S16, dst, insn.off as i32, insn.imm)
  519. }
  520. ebpf::ST_W_IMM => {
  521. self.emit_store_imm32(mem, OperandSize::S32, dst, insn.off as i32, insn.imm)
  522. }
  523. ebpf::ST_DW_IMM => {
  524. self.emit_store_imm32(mem, OperandSize::S64, dst, insn.off as i32, insn.imm)
  525. }
  526. // BPF_STX class
  527. ebpf::ST_B_REG => self.emit_store(mem, OperandSize::S8, src, dst, insn.off as i32),
  528. ebpf::ST_H_REG => self.emit_store(mem, OperandSize::S16, src, dst, insn.off as i32),
  529. ebpf::ST_W_REG => self.emit_store(mem, OperandSize::S32, src, dst, insn.off as i32),
  530. ebpf::ST_DW_REG => {
  531. self.emit_store(mem, OperandSize::S64, src, dst, insn.off as i32)
  532. }
  533. ebpf::ST_W_XADD => unimplemented!(),
  534. ebpf::ST_DW_XADD => unimplemented!(),
  535. // BPF_ALU class
  536. ebpf::ADD32_IMM => self.emit_alu32_imm32(mem, 0x81, 0, dst, insn.imm),
  537. ebpf::ADD32_REG => self.emit_alu32(mem, 0x01, src, dst),
  538. ebpf::SUB32_IMM => self.emit_alu32_imm32(mem, 0x81, 5, dst, insn.imm),
  539. ebpf::SUB32_REG => self.emit_alu32(mem, 0x29, src, dst),
  540. ebpf::MUL32_IMM
  541. | ebpf::MUL32_REG
  542. | ebpf::DIV32_IMM
  543. | ebpf::DIV32_REG
  544. | ebpf::MOD32_IMM
  545. | ebpf::MOD32_REG => {
  546. self.emit_muldivmod(mem, insn_ptr as u16, insn.opc, src, dst, insn.imm)
  547. }
  548. ebpf::OR32_IMM => self.emit_alu32_imm32(mem, 0x81, 1, dst, insn.imm),
  549. ebpf::OR32_REG => self.emit_alu32(mem, 0x09, src, dst),
  550. ebpf::AND32_IMM => self.emit_alu32_imm32(mem, 0x81, 4, dst, insn.imm),
  551. ebpf::AND32_REG => self.emit_alu32(mem, 0x21, src, dst),
  552. ebpf::LSH32_IMM => self.emit_alu32_imm8(mem, 0xc1, 4, dst, insn.imm as i8),
  553. ebpf::LSH32_REG => {
  554. self.emit_mov(mem, src, RCX);
  555. self.emit_alu32(mem, 0xd3, 4, dst);
  556. }
  557. ebpf::RSH32_IMM => self.emit_alu32_imm8(mem, 0xc1, 5, dst, insn.imm as i8),
  558. ebpf::RSH32_REG => {
  559. self.emit_mov(mem, src, RCX);
  560. self.emit_alu32(mem, 0xd3, 5, dst);
  561. }
  562. ebpf::NEG32 => self.emit_alu32(mem, 0xf7, 3, dst),
  563. ebpf::XOR32_IMM => self.emit_alu32_imm32(mem, 0x81, 6, dst, insn.imm),
  564. ebpf::XOR32_REG => self.emit_alu32(mem, 0x31, src, dst),
  565. ebpf::MOV32_IMM => self.emit_alu32_imm32(mem, 0xc7, 0, dst, insn.imm),
  566. ebpf::MOV32_REG => self.emit_mov(mem, src, dst),
  567. ebpf::ARSH32_IMM => self.emit_alu32_imm8(mem, 0xc1, 7, dst, insn.imm as i8),
  568. ebpf::ARSH32_REG => {
  569. self.emit_mov(mem, src, RCX);
  570. self.emit_alu32(mem, 0xd3, 7, dst);
  571. }
  572. ebpf::LE => {} // No-op
  573. ebpf::BE => {
  574. match insn.imm {
  575. 16 => {
  576. // rol
  577. self.emit1(mem, 0x66); // 16-bit override
  578. self.emit_alu32_imm8(mem, 0xc1, 0, dst, 8);
  579. // and
  580. self.emit_alu32_imm32(mem, 0x81, 4, dst, 0xffff);
  581. }
  582. 32 | 64 => {
  583. // bswap
  584. let bit = match insn.imm {
  585. 64 => 1,
  586. _ => 0,
  587. };
  588. self.emit_basic_rex(mem, bit, 0, dst);
  589. self.emit1(mem, 0x0f);
  590. self.emit1(mem, 0xc8 | (dst & 0b111));
  591. }
  592. _ => unreachable!(), // Should have been caught by verifier
  593. }
  594. }
  595. // BPF_ALU64 class
  596. ebpf::ADD64_IMM => self.emit_alu64_imm32(mem, 0x81, 0, dst, insn.imm),
  597. ebpf::ADD64_REG => self.emit_alu64(mem, 0x01, src, dst),
  598. ebpf::SUB64_IMM => self.emit_alu64_imm32(mem, 0x81, 5, dst, insn.imm),
  599. ebpf::SUB64_REG => self.emit_alu64(mem, 0x29, src, dst),
  600. ebpf::MUL64_IMM
  601. | ebpf::MUL64_REG
  602. | ebpf::DIV64_IMM
  603. | ebpf::DIV64_REG
  604. | ebpf::MOD64_IMM
  605. | ebpf::MOD64_REG => {
  606. self.emit_muldivmod(mem, insn_ptr as u16, insn.opc, src, dst, insn.imm)
  607. }
  608. ebpf::OR64_IMM => self.emit_alu64_imm32(mem, 0x81, 1, dst, insn.imm),
  609. ebpf::OR64_REG => self.emit_alu64(mem, 0x09, src, dst),
  610. ebpf::AND64_IMM => self.emit_alu64_imm32(mem, 0x81, 4, dst, insn.imm),
  611. ebpf::AND64_REG => self.emit_alu64(mem, 0x21, src, dst),
  612. ebpf::LSH64_IMM => self.emit_alu64_imm8(mem, 0xc1, 4, dst, insn.imm as i8),
  613. ebpf::LSH64_REG => {
  614. self.emit_mov(mem, src, RCX);
  615. self.emit_alu64(mem, 0xd3, 4, dst);
  616. }
  617. ebpf::RSH64_IMM => self.emit_alu64_imm8(mem, 0xc1, 5, dst, insn.imm as i8),
  618. ebpf::RSH64_REG => {
  619. self.emit_mov(mem, src, RCX);
  620. self.emit_alu64(mem, 0xd3, 5, dst);
  621. }
  622. ebpf::NEG64 => self.emit_alu64(mem, 0xf7, 3, dst),
  623. ebpf::XOR64_IMM => self.emit_alu64_imm32(mem, 0x81, 6, dst, insn.imm),
  624. ebpf::XOR64_REG => self.emit_alu64(mem, 0x31, src, dst),
  625. ebpf::MOV64_IMM => self.emit_load_imm(mem, dst, insn.imm as i64),
  626. ebpf::MOV64_REG => self.emit_mov(mem, src, dst),
  627. ebpf::ARSH64_IMM => self.emit_alu64_imm8(mem, 0xc1, 7, dst, insn.imm as i8),
  628. ebpf::ARSH64_REG => {
  629. self.emit_mov(mem, src, RCX);
  630. self.emit_alu64(mem, 0xd3, 7, dst);
  631. }
  632. // BPF_JMP class
  633. ebpf::JA => self.emit_jmp(mem, target_pc),
  634. ebpf::JEQ_IMM => {
  635. self.emit_cmp_imm32(mem, dst, insn.imm);
  636. self.emit_jcc(mem, 0x84, target_pc);
  637. }
  638. ebpf::JEQ_REG => {
  639. self.emit_cmp(mem, src, dst);
  640. self.emit_jcc(mem, 0x84, target_pc);
  641. }
  642. ebpf::JGT_IMM => {
  643. self.emit_cmp_imm32(mem, dst, insn.imm);
  644. self.emit_jcc(mem, 0x87, target_pc);
  645. }
  646. ebpf::JGT_REG => {
  647. self.emit_cmp(mem, src, dst);
  648. self.emit_jcc(mem, 0x87, target_pc);
  649. }
  650. ebpf::JGE_IMM => {
  651. self.emit_cmp_imm32(mem, dst, insn.imm);
  652. self.emit_jcc(mem, 0x83, target_pc);
  653. }
  654. ebpf::JGE_REG => {
  655. self.emit_cmp(mem, src, dst);
  656. self.emit_jcc(mem, 0x83, target_pc);
  657. }
  658. ebpf::JLT_IMM => {
  659. self.emit_cmp_imm32(mem, dst, insn.imm);
  660. self.emit_jcc(mem, 0x82, target_pc);
  661. }
  662. ebpf::JLT_REG => {
  663. self.emit_cmp(mem, src, dst);
  664. self.emit_jcc(mem, 0x82, target_pc);
  665. }
  666. ebpf::JLE_IMM => {
  667. self.emit_cmp_imm32(mem, dst, insn.imm);
  668. self.emit_jcc(mem, 0x86, target_pc);
  669. }
  670. ebpf::JLE_REG => {
  671. self.emit_cmp(mem, src, dst);
  672. self.emit_jcc(mem, 0x86, target_pc);
  673. }
  674. ebpf::JSET_IMM => {
  675. self.emit_alu64_imm32(mem, 0xf7, 0, dst, insn.imm);
  676. self.emit_jcc(mem, 0x85, target_pc);
  677. }
  678. ebpf::JSET_REG => {
  679. self.emit_alu64(mem, 0x85, src, dst);
  680. self.emit_jcc(mem, 0x85, target_pc);
  681. }
  682. ebpf::JNE_IMM => {
  683. self.emit_cmp_imm32(mem, dst, insn.imm);
  684. self.emit_jcc(mem, 0x85, target_pc);
  685. }
  686. ebpf::JNE_REG => {
  687. self.emit_cmp(mem, src, dst);
  688. self.emit_jcc(mem, 0x85, target_pc);
  689. }
  690. ebpf::JSGT_IMM => {
  691. self.emit_cmp_imm32(mem, dst, insn.imm);
  692. self.emit_jcc(mem, 0x8f, target_pc);
  693. }
  694. ebpf::JSGT_REG => {
  695. self.emit_cmp(mem, src, dst);
  696. self.emit_jcc(mem, 0x8f, target_pc);
  697. }
  698. ebpf::JSGE_IMM => {
  699. self.emit_cmp_imm32(mem, dst, insn.imm);
  700. self.emit_jcc(mem, 0x8d, target_pc);
  701. }
  702. ebpf::JSGE_REG => {
  703. self.emit_cmp(mem, src, dst);
  704. self.emit_jcc(mem, 0x8d, target_pc);
  705. }
  706. ebpf::JSLT_IMM => {
  707. self.emit_cmp_imm32(mem, dst, insn.imm);
  708. self.emit_jcc(mem, 0x8c, target_pc);
  709. }
  710. ebpf::JSLT_REG => {
  711. self.emit_cmp(mem, src, dst);
  712. self.emit_jcc(mem, 0x8c, target_pc);
  713. }
  714. ebpf::JSLE_IMM => {
  715. self.emit_cmp_imm32(mem, dst, insn.imm);
  716. self.emit_jcc(mem, 0x8e, target_pc);
  717. }
  718. ebpf::JSLE_REG => {
  719. self.emit_cmp(mem, src, dst);
  720. self.emit_jcc(mem, 0x8e, target_pc);
  721. }
  722. // BPF_JMP32 class
  723. ebpf::JEQ_IMM32 => {
  724. self.emit_cmp32_imm32(mem, dst, insn.imm);
  725. self.emit_jcc(mem, 0x84, target_pc);
  726. }
  727. ebpf::JEQ_REG32 => {
  728. self.emit_cmp32(mem, src, dst);
  729. self.emit_jcc(mem, 0x84, target_pc);
  730. }
  731. ebpf::JGT_IMM32 => {
  732. self.emit_cmp32_imm32(mem, dst, insn.imm);
  733. self.emit_jcc(mem, 0x87, target_pc);
  734. }
  735. ebpf::JGT_REG32 => {
  736. self.emit_cmp32(mem, src, dst);
  737. self.emit_jcc(mem, 0x87, target_pc);
  738. }
  739. ebpf::JGE_IMM32 => {
  740. self.emit_cmp32_imm32(mem, dst, insn.imm);
  741. self.emit_jcc(mem, 0x83, target_pc);
  742. }
  743. ebpf::JGE_REG32 => {
  744. self.emit_cmp32(mem, src, dst);
  745. self.emit_jcc(mem, 0x83, target_pc);
  746. }
  747. ebpf::JLT_IMM32 => {
  748. self.emit_cmp32_imm32(mem, dst, insn.imm);
  749. self.emit_jcc(mem, 0x82, target_pc);
  750. }
  751. ebpf::JLT_REG32 => {
  752. self.emit_cmp32(mem, src, dst);
  753. self.emit_jcc(mem, 0x82, target_pc);
  754. }
  755. ebpf::JLE_IMM32 => {
  756. self.emit_cmp32_imm32(mem, dst, insn.imm);
  757. self.emit_jcc(mem, 0x86, target_pc);
  758. }
  759. ebpf::JLE_REG32 => {
  760. self.emit_cmp32(mem, src, dst);
  761. self.emit_jcc(mem, 0x86, target_pc);
  762. }
  763. ebpf::JSET_IMM32 => {
  764. self.emit_alu32_imm32(mem, 0xf7, 0, dst, insn.imm);
  765. self.emit_jcc(mem, 0x85, target_pc);
  766. }
  767. ebpf::JSET_REG32 => {
  768. self.emit_alu32(mem, 0x85, src, dst);
  769. self.emit_jcc(mem, 0x85, target_pc);
  770. }
  771. ebpf::JNE_IMM32 => {
  772. self.emit_cmp32_imm32(mem, dst, insn.imm);
  773. self.emit_jcc(mem, 0x85, target_pc);
  774. }
  775. ebpf::JNE_REG32 => {
  776. self.emit_cmp32(mem, src, dst);
  777. self.emit_jcc(mem, 0x85, target_pc);
  778. }
  779. ebpf::JSGT_IMM32 => {
  780. self.emit_cmp32_imm32(mem, dst, insn.imm);
  781. self.emit_jcc(mem, 0x8f, target_pc);
  782. }
  783. ebpf::JSGT_REG32 => {
  784. self.emit_cmp32(mem, src, dst);
  785. self.emit_jcc(mem, 0x8f, target_pc);
  786. }
  787. ebpf::JSGE_IMM32 => {
  788. self.emit_cmp32_imm32(mem, dst, insn.imm);
  789. self.emit_jcc(mem, 0x8d, target_pc);
  790. }
  791. ebpf::JSGE_REG32 => {
  792. self.emit_cmp32(mem, src, dst);
  793. self.emit_jcc(mem, 0x8d, target_pc);
  794. }
  795. ebpf::JSLT_IMM32 => {
  796. self.emit_cmp32_imm32(mem, dst, insn.imm);
  797. self.emit_jcc(mem, 0x8c, target_pc);
  798. }
  799. ebpf::JSLT_REG32 => {
  800. self.emit_cmp32(mem, src, dst);
  801. self.emit_jcc(mem, 0x8c, target_pc);
  802. }
  803. ebpf::JSLE_IMM32 => {
  804. self.emit_cmp32_imm32(mem, dst, insn.imm);
  805. self.emit_jcc(mem, 0x8e, target_pc);
  806. }
  807. ebpf::JSLE_REG32 => {
  808. self.emit_cmp32(mem, src, dst);
  809. self.emit_jcc(mem, 0x8e, target_pc);
  810. }
  811. ebpf::CALL => {
  812. // For JIT, helpers in use MUST be registered at compile time. They can be
  813. // updated later, but not created after compiling (we need the address of the
  814. // helper function in the JIT-compiled program).
  815. if let Some(helper) = helpers.get(&(insn.imm as u32)) {
  816. // We reserve RCX for shifts
  817. self.emit_mov(mem, R9, RCX);
  818. self.emit_call(mem, *helper as usize);
  819. } else {
  820. Err(Error::new(
  821. ErrorKind::Other,
  822. format!(
  823. "[JIT] Error: unknown helper function (id: {:#x})",
  824. insn.imm as u32
  825. ),
  826. ))?;
  827. };
  828. }
  829. ebpf::TAIL_CALL => {
  830. unimplemented!()
  831. }
  832. ebpf::EXIT => {
  833. if insn_ptr != prog.len() / ebpf::INSN_SIZE - 1 {
  834. self.emit_jmp(mem, TARGET_PC_EXIT);
  835. };
  836. }
  837. _ => {
  838. Err(Error::new(
  839. ErrorKind::Other,
  840. format!(
  841. "[JIT] Error: unknown eBPF opcode {:#2x} (insn #{insn_ptr:?})",
  842. insn.opc
  843. ),
  844. ))?;
  845. }
  846. }
  847. insn_ptr += 1;
  848. }
  849. // Epilogue
  850. self.set_anchor(mem, TARGET_PC_EXIT);
  851. // Move register 0 into rax
  852. if map_register(0) != RAX {
  853. self.emit_mov(mem, map_register(0), RAX);
  854. }
  855. // Deallocate stack space
  856. self.emit_alu64_imm32(mem, 0x81, 0, RSP, ebpf::STACK_SIZE as i32);
  857. self.emit_pop(mem, R15);
  858. self.emit_pop(mem, R14);
  859. self.emit_pop(mem, R13);
  860. self.emit_pop(mem, RBX);
  861. self.emit_pop(mem, RBP);
  862. self.emit1(mem, 0xc3); // ret
  863. Ok(())
  864. }
  865. fn resolve_jumps(&mut self, mem: &mut JitMemory) -> Result<(), Error> {
  866. for jump in &self.jumps {
  867. let target_loc = match self.special_targets.get(&jump.target_pc) {
  868. Some(target) => *target,
  869. None => self.pc_locs[jump.target_pc as usize],
  870. };
  871. // Assumes jump offset is at end of instruction
  872. unsafe {
  873. let offset_loc = jump.offset_loc as i32 + std::mem::size_of::<i32>() as i32;
  874. let rel = &(target_loc as i32 - offset_loc) as *const i32;
  875. let offset_ptr = mem.contents.as_ptr().add(jump.offset_loc);
  876. libc::memcpy(
  877. offset_ptr as *mut libc::c_void,
  878. rel as *const libc::c_void,
  879. std::mem::size_of::<i32>(),
  880. );
  881. }
  882. }
  883. Ok(())
  884. }
  885. } // impl JitCompiler
  886. pub struct JitMemory<'a> {
  887. contents: &'a mut [u8],
  888. offset: usize,
  889. }
  890. impl<'a> JitMemory<'a> {
  891. pub fn new(
  892. prog: &[u8],
  893. helpers: &HashMap<u32, ebpf::Helper>,
  894. use_mbuff: bool,
  895. update_data_ptr: bool,
  896. ) -> Result<JitMemory<'a>, Error> {
  897. let contents: &mut [u8];
  898. let mut raw: mem::MaybeUninit<*mut libc::c_void> = mem::MaybeUninit::uninit();
  899. unsafe {
  900. let size = NUM_PAGES * PAGE_SIZE;
  901. libc::posix_memalign(raw.as_mut_ptr(), PAGE_SIZE, size);
  902. libc::mprotect(
  903. *raw.as_mut_ptr(),
  904. size,
  905. libc::PROT_EXEC | libc::PROT_READ | libc::PROT_WRITE,
  906. );
  907. std::ptr::write_bytes(*raw.as_mut_ptr(), 0xc3, size); // for now, prepopulate with 'RET' calls
  908. contents =
  909. std::slice::from_raw_parts_mut(*raw.as_mut_ptr() as *mut u8, NUM_PAGES * PAGE_SIZE);
  910. raw.assume_init();
  911. }
  912. let mut mem = JitMemory {
  913. contents,
  914. offset: 0,
  915. };
  916. let mut jit = JitCompiler::new();
  917. jit.jit_compile(&mut mem, prog, use_mbuff, update_data_ptr, helpers)?;
  918. jit.resolve_jumps(&mut mem)?;
  919. Ok(mem)
  920. }
  921. pub fn get_prog(&self) -> MachineCode {
  922. unsafe { mem::transmute(self.contents.as_ptr()) }
  923. }
  924. }
  925. impl<'a> Index<usize> for JitMemory<'a> {
  926. type Output = u8;
  927. fn index(&self, _index: usize) -> &u8 {
  928. &self.contents[_index]
  929. }
  930. }
  931. impl<'a> IndexMut<usize> for JitMemory<'a> {
  932. fn index_mut(&mut self, _index: usize) -> &mut u8 {
  933. &mut self.contents[_index]
  934. }
  935. }
  936. impl<'a> Drop for JitMemory<'a> {
  937. fn drop(&mut self) {
  938. unsafe {
  939. libc::free(self.contents.as_mut_ptr() as *mut libc::c_void);
  940. }
  941. }
  942. }
  943. impl<'a> std::fmt::Debug for JitMemory<'a> {
  944. fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatterError> {
  945. fmt.write_str("JIT contents: [")?;
  946. fmt.write_str(" ] | ")?;
  947. fmt.debug_struct("JIT memory")
  948. .field("offset", &self.offset)
  949. .finish()
  950. }
  951. }