jit.rs 38 KB

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