3 * Politecnico di Torino. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28 #include <ddk/ntddk.h>
38 // emit routine to update the jump table
40 void emit_lenght(binary_stream *stream, ULONG value, UINT len)
42 (stream->refs)[stream->bpf_pc]+=len;
47 // emit routine to output the actual binary code
49 void emit_code(binary_stream *stream, ULONG value, UINT len)
55 stream->ibuf[stream->cur_ip]=(UCHAR)value;
60 *((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
65 *((ULONG*)(stream->ibuf+stream->cur_ip))=value;
78 // Function that does the real stuff
80 BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
87 // Allocate the reference table for the jumps
89 #define NPF_TAG_REFTABLE TAG('0', 'J', 'W', 'A')
90 stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), NPF_TAG_REFTABLE);
92 stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
99 // Reset the reference table
100 for(i=0; i< nins + 1; i++)
106 // the first pass will emit the lengths of the instructions
107 // to create the reference table
114 /* create the procedure header */
161 case BPF_LD|BPF_W|BPF_ABS:
165 ADDib(ECX,sizeof(INT))
166 CMPodd(ECX, EBP, 0x10)
174 MOVid(EAX,0) //this can be optimized with xor eax,eax
176 MOVobd(EAX, EBX, ESI)
181 case BPF_LD|BPF_H|BPF_ABS:
185 ADDib(ECX,sizeof(SHORT))
186 CMPodd(ECX, EBP, 0x10)
202 case BPF_LD|BPF_B|BPF_ABS:
205 CMPodd(ECX, EBP, 0x10)
220 case BPF_LD|BPF_W|BPF_LEN:
222 MOVodd(EAX, EBP, 0xc)
226 case BPF_LDX|BPF_W|BPF_LEN:
228 MOVodd(EDX, EBP, 0xc)
232 case BPF_LD|BPF_W|BPF_IND:
237 ADDib(ECX,sizeof(INT))
238 CMPodd(ECX, EBP, 0x10)
248 MOVobd(EAX, EBX, ESI)
253 case BPF_LD|BPF_H|BPF_IND:
258 ADDib(ECX,sizeof(SHORT))
259 CMPodd(ECX, EBP, 0x10)
275 case BPF_LD|BPF_B|BPF_IND:
279 CMPodd(ECX, EBP, 0x10)
294 case BPF_LDX|BPF_MSH|BPF_B:
297 CMPodd(ECX, EBP, 0x10)
320 case BPF_LDX|BPF_IMM:
330 MOVobd(EAX, ECX, ESI)
334 case BPF_LDX|BPF_MEM:
338 MOVobd(EDX, ECX, ESI)
344 // XXX: this command and the following could be optimized if the previous
345 // instruction was already of this type
348 MOVomd(ECX, ESI, EAX)
356 MOVomd(ECX, ESI, EDX)
361 JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc])
365 case BPF_JMP|BPF_JGT|BPF_K:
368 JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP
369 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
372 case BPF_JMP|BPF_JGE|BPF_K:
375 JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
376 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
380 case BPF_JMP|BPF_JEQ|BPF_K:
383 JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
384 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
388 case BPF_JMP|BPF_JSET|BPF_K:
392 JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
393 JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
397 case BPF_JMP|BPF_JGT|BPF_X:
400 JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
401 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
404 case BPF_JMP|BPF_JGE|BPF_X:
407 JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
408 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
412 case BPF_JMP|BPF_JEQ|BPF_X:
415 JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
416 JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
420 case BPF_JMP|BPF_JSET|BPF_X:
424 JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
425 JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
429 case BPF_ALU|BPF_ADD|BPF_X:
435 case BPF_ALU|BPF_SUB|BPF_X:
441 case BPF_ALU|BPF_MUL|BPF_X:
448 case BPF_ALU|BPF_DIV|BPF_X:
467 case BPF_ALU|BPF_AND|BPF_X:
473 case BPF_ALU|BPF_OR|BPF_X:
479 case BPF_ALU|BPF_LSH|BPF_X:
486 case BPF_ALU|BPF_RSH|BPF_X:
493 case BPF_ALU|BPF_ADD|BPF_K:
499 case BPF_ALU|BPF_SUB|BPF_K:
505 case BPF_ALU|BPF_MUL|BPF_K:
514 case BPF_ALU|BPF_DIV|BPF_K:
524 case BPF_ALU|BPF_AND|BPF_K:
530 case BPF_ALU|BPF_OR|BPF_K:
536 case BPF_ALU|BPF_LSH|BPF_K:
538 SHLib(EAX, (ins->k) & 255)
542 case BPF_ALU|BPF_RSH|BPF_K:
544 SHRib(EAX, (ins->k) & 255)
548 case BPF_ALU|BPF_NEG:
554 case BPF_MISC|BPF_TAX:
560 case BPF_MISC|BPF_TXA:
577 #define NPF_TAG_STREAMBUF TAG('1', 'J', 'W', 'A')
578 stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, NPF_TAG_STREAMBUF);
580 stream.ibuf=(CHAR*)malloc(stream.cur_ip);
582 if(stream.ibuf==NULL)
585 ExFreePool(stream.refs);
592 // modify the reference table to contain the offsets and not the lengths of the instructions
593 for(i=1; i< nins + 1; i++)
594 stream.refs[i]+=stream.refs[i-1];
596 // Reset the counters
599 // the second pass creates the actual code
604 // the reference table is needed only during compilation, now we can free it
606 ExFreePool(stream.refs);
610 return (BPF_filter_function)stream.ibuf;
615 JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins)
617 JIT_BPF_Filter *Filter;
620 // Allocate the filter structure
622 #define NPF_TAG_FILTSTRUCT TAG('2', 'J', 'W', 'A')
623 Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), NPF_TAG_FILTSTRUCT);
625 Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter));
632 // Allocate the filter's memory
634 #define NPF_TAG_FILTMEM TAG('3', 'J', 'W', 'A')
635 Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), NPF_TAG_FILTMEM);
637 Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
639 if(Filter->mem==NULL)
650 if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
653 ExFreePool(Filter->mem);
667 //////////////////////////////////////////////////////////////
669 void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
672 ExFreePool(Filter->mem);
673 ExFreePool(Filter->Function);
677 free(Filter->Function);