bpf_jit_machdep.c revision 199531
1103856Stjr/*-
2103856Stjr * Copyright (C) 2002-2003 NetGroup, Politecnico di Torino (Italy)
3103856Stjr * Copyright (C) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
4103856Stjr * All rights reserved.
5103856Stjr *
6103856Stjr * Redistribution and use in source and binary forms, with or without
7103856Stjr * modification, are permitted provided that the following conditions
8227753Stheraven * are met:
9227753Stheraven *
10227753Stheraven * 1. Redistributions of source code must retain the above copyright
11227753Stheraven * notice, this list of conditions and the following disclaimer.
12227753Stheraven * 2. Redistributions in binary form must reproduce the above copyright
13103856Stjr * notice, this list of conditions and the following disclaimer in the
14103856Stjr * documentation and/or other materials provided with the distribution.
15103856Stjr * 3. Neither the name of the Politecnico di Torino nor the names of its
16103856Stjr * contributors may be used to endorse or promote products derived from
17103856Stjr * this software without specific prior written permission.
18103856Stjr *
19103856Stjr * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20103856Stjr * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21249808Semaste * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22103856Stjr * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23103856Stjr * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24103856Stjr * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25103856Stjr * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26103856Stjr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27103856Stjr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28103856Stjr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29103856Stjr * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30103856Stjr */
31103856Stjr
32103856Stjr#include <sys/cdefs.h>
33103856Stjr__FBSDID("$FreeBSD: head/sys/amd64/amd64/bpf_jit_machdep.c 199531 2009-11-19 15:45:24Z jkim $");
34103856Stjr
35103856Stjr#ifdef _KERNEL
36103856Stjr#include "opt_bpf.h"
37103856Stjr#include <sys/param.h>
38103856Stjr#include <sys/systm.h>
39103856Stjr#include <sys/kernel.h>
40103856Stjr#include <sys/socket.h>
41103856Stjr#include <sys/malloc.h>
42103856Stjr#include <net/if.h>
43128844Sobrien#else
44103856Stjr#include <stdlib.h>
45103856Stjr#include <sys/mman.h>
46103856Stjr#include <sys/param.h>
47103856Stjr#endif
48103856Stjr
49149313Sstefanf#include <sys/types.h>
50103856Stjr
51103856Stjr#include <net/bpf.h>
52103856Stjr#include <net/bpf_jitter.h>
53103856Stjr
54103856Stjr#include <amd64/amd64/bpf_jit_machdep.h>
55103856Stjr
56103856Stjrbpf_filter_func	bpf_jit_compile(struct bpf_insn *, u_int, size_t *, int *);
57103856Stjr
58103856Stjr/*
59103856Stjr * emit routine to update the jump table
60103856Stjr */
61227753Stheravenstatic void
62103856Stjremit_length(bpf_bin_stream *stream, __unused u_int value, u_int len)
63103856Stjr{
64103856Stjr
65103856Stjr	(stream->refs)[stream->bpf_pc] += len;
66103856Stjr	stream->cur_ip += len;
67103856Stjr}
68103856Stjr
69103856Stjr/*
70103856Stjr * emit routine to output the actual binary code
71103856Stjr */
72103856Stjrstatic void
73103856Stjremit_code(bpf_bin_stream *stream, u_int value, u_int len)
74103856Stjr{
75103856Stjr
76103856Stjr	switch (len) {
77103856Stjr	case 1:
78103856Stjr		stream->ibuf[stream->cur_ip] = (u_char)value;
79103856Stjr		stream->cur_ip++;
80103856Stjr		break;
81103856Stjr
82117249Stjr	case 2:
83117249Stjr		*((u_short *)(stream->ibuf + stream->cur_ip)) = (u_short)value;
84103856Stjr		stream->cur_ip += 2;
85103856Stjr		break;
86103856Stjr
87103856Stjr	case 4:
88103856Stjr		*((u_int *)(stream->ibuf + stream->cur_ip)) = value;
89125283Sdas		stream->cur_ip += 4;
90103856Stjr		break;
91103856Stjr	}
92103856Stjr
93103856Stjr	return;
94103856Stjr}
95103856Stjr
96103856Stjr/*
97103856Stjr * Function that does the real stuff
98103856Stjr */
99103856Stjrbpf_filter_func
100157381Sphkbpf_jit_compile(struct bpf_insn *prog, u_int nins, size_t *size, int *mem)
101227753Stheraven{
102157381Sphk	bpf_bin_stream stream;
103117249Stjr	struct bpf_insn *ins;
104234585Sdas	u_int i, pass;
105234585Sdas
106234585Sdas	/*
107234585Sdas	 * NOTE: do not modify the name of this variable, as it's used by
108234585Sdas	 * the macros to emit code.
109103856Stjr	 */
110234585Sdas	emit_func emitm;
111234585Sdas
112234585Sdas	/* Allocate the reference table for the jumps */
113234585Sdas#ifdef _KERNEL
114234585Sdas	stream.refs = (u_int *)malloc((nins + 1) * sizeof(u_int),
115234585Sdas	    M_BPFJIT, M_NOWAIT);
116234585Sdas#else
117234585Sdas	stream.refs = (u_int *)malloc((nins + 1) * sizeof(u_int));
118234585Sdas#endif
119234585Sdas	if (stream.refs == NULL)
120234585Sdas		return (NULL);
121234585Sdas
122234585Sdas	/* Reset the reference table */
123234585Sdas	for (i = 0; i < nins + 1; i++)
124234585Sdas		stream.refs[i] = 0;
125234585Sdas
126234585Sdas	stream.cur_ip = 0;
127234585Sdas	stream.bpf_pc = 0;
128234585Sdas
129234585Sdas	/*
130234585Sdas	 * the first pass will emit the lengths of the instructions
131234585Sdas	 * to create the reference table
132187422Sdas	 */
133187422Sdas	emitm = emit_length;
134103856Stjr
135234585Sdas	pass = 0;
136234585Sdas	for (;;) {
137234585Sdas		ins = prog;
138234585Sdas
139234585Sdas		/* create the procedure header */
140234585Sdas		MOVrq2(RBX, R8);
141234836Sdumbbell		MOVrq(RDI, RBX);
142234585Sdas		MOVrd2(ESI, R9D);
143234585Sdas		MOVrd(EDX, EDI);
144234585Sdas
145234585Sdas		for (i = 0; i < nins; i++) {
146234585Sdas			stream.bpf_pc++;
147234585Sdas
148234585Sdas			switch (ins->code) {
149234585Sdas			default:
150234825Sdas#ifdef _KERNEL
151234825Sdas				return (NULL);
152234585Sdas#else
153234585Sdas				abort();
154234585Sdas#endif
155234825Sdas
156234585Sdas			case BPF_RET|BPF_K:
157234585Sdas				MOVid(ins->k, EAX);
158234585Sdas				MOVrq3(R8, RBX);
159234585Sdas				RET();
160234585Sdas				break;
161234585Sdas
162234585Sdas			case BPF_RET|BPF_A:
163234585Sdas				MOVrq3(R8, RBX);
164234585Sdas				RET();
165234585Sdas				break;
166234585Sdas
167234585Sdas			case BPF_LD|BPF_W|BPF_ABS:
168234585Sdas				MOVid(ins->k, ESI);
169234585Sdas				CMPrd(EDI, ESI);
170234585Sdas				JAb(12);
171234585Sdas				MOVrd(EDI, ECX);
172234585Sdas				SUBrd(ESI, ECX);
173234585Sdas				CMPid(sizeof(int32_t), ECX);
174234585Sdas				JAEb(6);
175234585Sdas				ZEROrd(EAX);
176234585Sdas				MOVrq3(R8, RBX);
177234585Sdas				RET();
178234585Sdas				MOVobd(RBX, RSI, EAX);
179234585Sdas				BSWAP(EAX);
180234585Sdas				break;
181234585Sdas
182234836Sdumbbell			case BPF_LD|BPF_H|BPF_ABS:
183234585Sdas				ZEROrd(EAX);
184234585Sdas				MOVid(ins->k, ESI);
185234585Sdas				CMPrd(EDI, ESI);
186234585Sdas				JAb(12);
187234585Sdas				MOVrd(EDI, ECX);
188234585Sdas				SUBrd(ESI, ECX);
189234585Sdas				CMPid(sizeof(int16_t), ECX);
190234585Sdas				JAEb(4);
191234585Sdas				MOVrq3(R8, RBX);
192234585Sdas				RET();
193234825Sdas				MOVobw(RBX, RSI, AX);
194234825Sdas				SWAP_AX();
195234585Sdas				break;
196234585Sdas
197234585Sdas			case BPF_LD|BPF_B|BPF_ABS:
198234825Sdas				ZEROrd(EAX);
199234585Sdas				MOVid(ins->k, ESI);
200234585Sdas				CMPrd(EDI, ESI);
201234585Sdas				JBb(4);
202234585Sdas				MOVrq3(R8, RBX);
203234585Sdas				RET();
204234585Sdas				MOVobb(RBX, RSI, AL);
205234585Sdas				break;
206234585Sdas
207234585Sdas			case BPF_LD|BPF_W|BPF_LEN:
208234585Sdas				MOVrd3(R9D, EAX);
209234585Sdas				break;
210234585Sdas
211234585Sdas			case BPF_LDX|BPF_W|BPF_LEN:
212234585Sdas				MOVrd3(R9D, EDX);
213234585Sdas				break;
214234585Sdas
215234585Sdas			case BPF_LD|BPF_W|BPF_IND:
216234585Sdas				CMPrd(EDI, EDX);
217234585Sdas				JAb(27);
218234585Sdas				MOVid(ins->k, ESI);
219234585Sdas				MOVrd(EDI, ECX);
220234585Sdas				SUBrd(EDX, ECX);
221234585Sdas				CMPrd(ESI, ECX);
222234585Sdas				JBb(14);
223234585Sdas				ADDrd(EDX, ESI);
224234585Sdas				MOVrd(EDI, ECX);
225234585Sdas				SUBrd(ESI, ECX);
226234585Sdas				CMPid(sizeof(int32_t), ECX);
227234585Sdas				JAEb(6);
228234585Sdas				ZEROrd(EAX);
229234585Sdas				MOVrq3(R8, RBX);
230234585Sdas				RET();
231234585Sdas				MOVobd(RBX, RSI, EAX);
232234585Sdas				BSWAP(EAX);
233234585Sdas				break;
234234585Sdas
235234585Sdas			case BPF_LD|BPF_H|BPF_IND:
236234585Sdas				ZEROrd(EAX);
237234585Sdas				CMPrd(EDI, EDX);
238234585Sdas				JAb(27);
239234585Sdas				MOVid(ins->k, ESI);
240234836Sdumbbell				MOVrd(EDI, ECX);
241234585Sdas				SUBrd(EDX, ECX);
242234585Sdas				CMPrd(ESI, ECX);
243234585Sdas				JBb(14);
244234585Sdas				ADDrd(EDX, ESI);
245234585Sdas				MOVrd(EDI, ECX);
246234585Sdas				SUBrd(ESI, ECX);
247234585Sdas				CMPid(sizeof(int16_t), ECX);
248234585Sdas				JAEb(4);
249234825Sdas				MOVrq3(R8, RBX);
250234585Sdas				RET();
251234825Sdas				MOVobw(RBX, RSI, AX);
252234585Sdas				SWAP_AX();
253234585Sdas				break;
254234585Sdas
255234825Sdas			case BPF_LD|BPF_B|BPF_IND:
256234585Sdas				ZEROrd(EAX);
257234585Sdas				CMPrd(EDI, EDX);
258234585Sdas				JAEb(13);
259234585Sdas				MOVid(ins->k, ESI);
260234585Sdas				MOVrd(EDI, ECX);
261234585Sdas				SUBrd(EDX, ECX);
262234585Sdas				CMPrd(ESI, ECX);
263234585Sdas				JAb(4);
264234585Sdas				MOVrq3(R8, RBX);
265234585Sdas				RET();
266234585Sdas				ADDrd(EDX, ESI);
267234585Sdas				MOVobb(RBX, RSI, AL);
268234585Sdas				break;
269234585Sdas
270234585Sdas			case BPF_LDX|BPF_MSH|BPF_B:
271234585Sdas				MOVid(ins->k, ESI);
272234585Sdas				CMPrd(EDI, ESI);
273234585Sdas				JBb(6);
274234585Sdas				ZEROrd(EAX);
275234585Sdas				MOVrq3(R8, RBX);
276234585Sdas				RET();
277234585Sdas				ZEROrd(EDX);
278234585Sdas				MOVobb(RBX, RSI, DL);
279234585Sdas				ANDib(0x0f, DL);
280234585Sdas				SHLib(2, EDX);
281234585Sdas				break;
282234585Sdas
283234585Sdas			case BPF_LD|BPF_IMM:
284234585Sdas				MOVid(ins->k, EAX);
285234585Sdas				break;
286234585Sdas
287234585Sdas			case BPF_LDX|BPF_IMM:
288234585Sdas				MOVid(ins->k, EDX);
289234585Sdas				break;
290234585Sdas
291234585Sdas			case BPF_LD|BPF_MEM:
292234585Sdas				MOViq((uintptr_t)mem, RCX);
293234585Sdas				MOVid(ins->k * 4, ESI);
294234585Sdas				MOVobd(RCX, RSI, EAX);
295234585Sdas				break;
296234585Sdas
297234585Sdas			case BPF_LDX|BPF_MEM:
298234585Sdas				MOViq((uintptr_t)mem, RCX);
299234585Sdas				MOVid(ins->k * 4, ESI);
300234585Sdas				MOVobd(RCX, RSI, EDX);
301234585Sdas				break;
302234585Sdas
303234585Sdas			case BPF_ST:
304234585Sdas				/*
305234585Sdas				 * XXX this command and the following could
306234585Sdas				 * be optimized if the previous instruction
307234585Sdas				 * was already of this type
308234585Sdas				 */
309234585Sdas				MOViq((uintptr_t)mem, RCX);
310234585Sdas				MOVid(ins->k * 4, ESI);
311234585Sdas				MOVomd(EAX, RCX, RSI);
312234585Sdas				break;
313234585Sdas
314234585Sdas			case BPF_STX:
315234585Sdas				MOViq((uintptr_t)mem, RCX);
316234585Sdas				MOVid(ins->k * 4, ESI);
317234585Sdas				MOVomd(EDX, RCX, RSI);
318234585Sdas				break;
319234585Sdas
320234585Sdas			case BPF_JMP|BPF_JA:
321234585Sdas				JMP(stream.refs[stream.bpf_pc + ins->k] -
322234585Sdas				    stream.refs[stream.bpf_pc]);
323234585Sdas				break;
324234585Sdas
325234585Sdas			case BPF_JMP|BPF_JGT|BPF_K:
326234585Sdas				if (ins->jt == 0 && ins->jf == 0)
327234585Sdas					break;
328234585Sdas				CMPid(ins->k, EAX);
329234585Sdas				JCC(JA, JBE);
330234585Sdas				break;
331234585Sdas
332234585Sdas			case BPF_JMP|BPF_JGE|BPF_K:
333234585Sdas				if (ins->jt == 0 && ins->jf == 0)
334234585Sdas					break;
335234585Sdas				CMPid(ins->k, EAX);
336234585Sdas				JCC(JAE, JB);
337234585Sdas				break;
338234585Sdas
339234585Sdas			case BPF_JMP|BPF_JEQ|BPF_K:
340234585Sdas				if (ins->jt == 0 && ins->jf == 0)
341234585Sdas					break;
342234585Sdas				CMPid(ins->k, EAX);
343234585Sdas				JCC(JE, JNE);
344234585Sdas				break;
345234585Sdas
346234585Sdas			case BPF_JMP|BPF_JSET|BPF_K:
347234585Sdas				if (ins->jt == 0 && ins->jf == 0)
348234585Sdas					break;
349234585Sdas				TESTid(ins->k, EAX);
350234585Sdas				JCC(JNE, JE);
351234585Sdas				break;
352234585Sdas
353234585Sdas			case BPF_JMP|BPF_JGT|BPF_X:
354234585Sdas				if (ins->jt == 0 && ins->jf == 0)
355234585Sdas					break;
356234585Sdas				CMPrd(EDX, EAX);
357234585Sdas				JCC(JA, JBE);
358234585Sdas				break;
359234585Sdas
360234585Sdas			case BPF_JMP|BPF_JGE|BPF_X:
361234585Sdas				if (ins->jt == 0 && ins->jf == 0)
362234585Sdas					break;
363234585Sdas				CMPrd(EDX, EAX);
364234585Sdas				JCC(JAE, JB);
365234585Sdas				break;
366234585Sdas
367234585Sdas			case BPF_JMP|BPF_JEQ|BPF_X:
368234585Sdas				if (ins->jt == 0 && ins->jf == 0)
369234585Sdas					break;
370234585Sdas				CMPrd(EDX, EAX);
371234585Sdas				JCC(JE, JNE);
372234585Sdas				break;
373234585Sdas
374234585Sdas			case BPF_JMP|BPF_JSET|BPF_X:
375234836Sdumbbell				if (ins->jt == 0 && ins->jf == 0)
376234585Sdas					break;
377234585Sdas				TESTrd(EDX, EAX);
378234585Sdas				JCC(JNE, JE);
379234585Sdas				break;
380234585Sdas
381234585Sdas			case BPF_ALU|BPF_ADD|BPF_X:
382234585Sdas				ADDrd(EDX, EAX);
383234585Sdas				break;
384234585Sdas
385234585Sdas			case BPF_ALU|BPF_SUB|BPF_X:
386234585Sdas				SUBrd(EDX, EAX);
387234585Sdas				break;
388234585Sdas
389234585Sdas			case BPF_ALU|BPF_MUL|BPF_X:
390234585Sdas				MOVrd(EDX, ECX);
391234585Sdas				MULrd(EDX);
392234585Sdas				MOVrd(ECX, EDX);
393234585Sdas				break;
394234585Sdas
395234585Sdas			case BPF_ALU|BPF_DIV|BPF_X:
396234585Sdas				TESTrd(EDX, EDX);
397234585Sdas				JNEb(6);
398234585Sdas				ZEROrd(EAX);
399234585Sdas				MOVrq3(R8, RBX);
400234585Sdas				RET();
401234585Sdas				MOVrd(EDX, ECX);
402234585Sdas				ZEROrd(EDX);
403234585Sdas				DIVrd(ECX);
404234585Sdas				MOVrd(ECX, EDX);
405234585Sdas				break;
406234585Sdas
407234585Sdas			case BPF_ALU|BPF_AND|BPF_X:
408234585Sdas				ANDrd(EDX, EAX);
409234585Sdas				break;
410234585Sdas
411234585Sdas			case BPF_ALU|BPF_OR|BPF_X:
412234585Sdas				ORrd(EDX, EAX);
413234585Sdas				break;
414234585Sdas
415234585Sdas			case BPF_ALU|BPF_LSH|BPF_X:
416234585Sdas				MOVrd(EDX, ECX);
417234585Sdas				SHL_CLrb(EAX);
418234585Sdas				break;
419234585Sdas
420234585Sdas			case BPF_ALU|BPF_RSH|BPF_X:
421234585Sdas				MOVrd(EDX, ECX);
422103856Stjr				SHR_CLrb(EAX);
423103856Stjr				break;
424103856Stjr
425227753Stheraven			case BPF_ALU|BPF_ADD|BPF_K:
426227753Stheraven				ADD_EAXi(ins->k);
427103856Stjr				break;
428103856Stjr
429227753Stheraven			case BPF_ALU|BPF_SUB|BPF_K:
430103856Stjr				SUB_EAXi(ins->k);
431103856Stjr				break;
432103856Stjr
433227753Stheraven			case BPF_ALU|BPF_MUL|BPF_K:
434103856Stjr				MOVrd(EDX, ECX);
435103856Stjr				MOVid(ins->k, EDX);
436103856Stjr				MULrd(EDX);
437227753Stheraven				MOVrd(ECX, EDX);
438227753Stheraven				break;
439227753Stheraven
440227753Stheraven			case BPF_ALU|BPF_DIV|BPF_K:
441227753Stheraven				MOVrd(EDX, ECX);
442103856Stjr				ZEROrd(EDX);
443103856Stjr				MOVid(ins->k, ESI);
444103856Stjr				DIVrd(ESI);
445103856Stjr				MOVrd(ECX, EDX);
446103856Stjr				break;
447227753Stheraven
448227753Stheraven			case BPF_ALU|BPF_AND|BPF_K:
449103856Stjr				ANDid(ins->k, EAX);
450234585Sdas				break;
451103856Stjr
452103856Stjr			case BPF_ALU|BPF_OR|BPF_K:
453103856Stjr				ORid(ins->k, EAX);
454103856Stjr				break;
455103856Stjr
456234585Sdas			case BPF_ALU|BPF_LSH|BPF_K:
457103856Stjr				SHLib((ins->k) & 0xff, EAX);
458103856Stjr				break;
459234585Sdas
460103856Stjr			case BPF_ALU|BPF_RSH|BPF_K:
461103856Stjr				SHRib((ins->k) & 0xff, EAX);
462103856Stjr				break;
463103856Stjr
464103856Stjr			case BPF_ALU|BPF_NEG:
465103856Stjr				NEGd(EAX);
466234585Sdas				break;
467103856Stjr
468103856Stjr			case BPF_MISC|BPF_TAX:
469103856Stjr				MOVrd(EAX, EDX);
470103856Stjr				break;
471103856Stjr
472227753Stheraven			case BPF_MISC|BPF_TXA:
473227753Stheraven				MOVrd(EDX, EAX);
474234588Sdas				break;
475103856Stjr			}
476227753Stheraven			ins++;
477103856Stjr		}
478103856Stjr
479103856Stjr		pass++;
480103856Stjr		if (pass >= 2) {
481103856Stjr#ifndef _KERNEL
482103856Stjr			if (mprotect(stream.ibuf, stream.cur_ip,
483103856Stjr			    PROT_READ | PROT_EXEC) != 0) {
484103856Stjr				munmap(stream.ibuf, stream.cur_ip);
485103856Stjr				stream.ibuf = NULL;
486103856Stjr			}
487103856Stjr#endif
488103856Stjr			*size = stream.cur_ip;
489103856Stjr			break;
490103856Stjr		}
491227753Stheraven
492103856Stjr#ifdef _KERNEL
493103856Stjr		stream.ibuf = (char *)contigmalloc(stream.cur_ip, M_BPFJIT,
494227753Stheraven		    M_NOWAIT, 0, ~0UL, 16, 0);
495103856Stjr		if (stream.ibuf == NULL)
496103856Stjr			break;
497103856Stjr#else
498103856Stjr		stream.ibuf = (char *)mmap(NULL, stream.cur_ip,
499103856Stjr		    PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
500103856Stjr		if (stream.ibuf == MAP_FAILED) {
501103856Stjr			stream.ibuf = NULL;
502103856Stjr			break;
503103856Stjr		}
504103856Stjr#endif
505103856Stjr
506103856Stjr		/*
507103856Stjr		 * modify the reference table to contain the offsets and
508103856Stjr		 * not the lengths of the instructions
509103856Stjr		 */
510103856Stjr		for (i = 1; i < nins + 1; i++)
511103856Stjr			stream.refs[i] += stream.refs[i - 1];
512103856Stjr
513103856Stjr		/* Reset the counters */
514103856Stjr		stream.cur_ip = 0;
515103856Stjr		stream.bpf_pc = 0;
516103856Stjr
517103856Stjr		/* the second pass creates the actual code */
518103856Stjr		emitm = emit_code;
519103856Stjr	}
520103856Stjr
521103856Stjr	/*
522103856Stjr	 * the reference table is needed only during compilation,
523103856Stjr	 * now we can free it
524103856Stjr	 */
525103856Stjr#ifdef _KERNEL
526103856Stjr	free(stream.refs, M_BPFJIT);
527103856Stjr#else
528103856Stjr	free(stream.refs);
529103856Stjr#endif
530103856Stjr
531103856Stjr	return ((bpf_filter_func)stream.ibuf);
532103856Stjr}
533103856Stjr