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.
26 /** @defgroup NPF_include NPF structures and definitions
56 /*! \brief A stream of X86 binary code.*/
57 typedef struct binary_stream
{
58 INT cur_ip
; ///< Current X86 instruction pointer.
59 INT bpf_pc
; ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter.
60 PCHAR ibuf
; ///< Instruction buffer, contains the X86 generated code.
61 PUINT refs
; ///< Jumps reference table.
65 /*! \brief Prototype of a filtering function created by the jitter.
67 The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter
68 is not among the parameters, because it is hardwired in the function.
70 typedef UINT (*BPF_filter_function
)( binary_stream
*, ULONG
, UINT
);
72 /*! \brief Prototype of the emit functions.
74 Different emit functions are used to create the reference table and to generate the actual filtering code.
75 This allows to have simpler instruction macros.
76 The first parameter is the stream that will receive the data. The secon one is a variable containing
77 the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
80 typedef void (*emit_func
)(binary_stream
*stream
, ULONG value
, UINT n
);
82 /*! \brief Structure describing a x86 filtering program created by the jitter.*/
83 typedef struct JIT_BPF_Filter
{
84 BPF_filter_function Function
; ///< The x86 filtering binary, in the form of a BPF_filter_function.
92 /**************************/
93 /* X86 INSTRUCTION MACROS */
94 /**************************/
97 #define MOVid(r32, i32) \
98 emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4);
101 #define MOVrd(dr32, sr32) \
102 emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
104 /// mov dr32,sr32[off]
105 #define MOVodd(dr32, sr32, off) \
106 emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
107 emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
108 emitm(&stream, off, 1);
110 /// mov dr32,sr32[or32]
111 #define MOVobd(dr32, sr32, or32) \
112 emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
113 emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
114 emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
116 /// mov dr16,sr32[or32]
117 #define MOVobw(dr32, sr32, or32) \
118 emitm(&stream, 0x66, 1); \
119 emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
120 emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
121 emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
123 /// mov dr8,sr32[or32]
124 #define MOVobb(dr8, sr32, or32) \
125 emitm(&stream, 0x8a, 1); \
126 emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\
127 emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
129 /// mov [dr32][or32],sr32
130 #define MOVomd(dr32, or32, sr32) \
131 emitm(&stream, 0x89, 1); \
132 emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\
133 emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
136 #define BSWAP(dr32) \
137 emitm(&stream, 0xf, 1); \
138 emitm(&stream, 0x19 << 3 | dr32 , 1);
142 emitm(&stream, 0x86, 1); \
143 emitm(&stream, 0xc4 , 1);
147 emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1);
151 emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1);
155 emitm(&stream, 12 << 4 | 0 << 3 | 3, 1);
158 #define ADDrd(dr32, sr32) \
159 emitm(&stream, 0x03, 1);\
160 emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
163 #define ADD_EAXi(i32) \
164 emitm(&stream, 0x05, 1);\
165 emitm(&stream, i32, 4);
168 #define ADDid(r32, i32) \
169 emitm(&stream, 0x81, 1);\
170 emitm(&stream, 24 << 3 | r32, 1);\
171 emitm(&stream, i32, 4);
174 #define ADDib(r32, i8) \
175 emitm(&stream, 0x83, 1);\
176 emitm(&stream, 24 << 3 | r32, 1);\
177 emitm(&stream, i8, 1);
180 #define SUBrd(dr32, sr32) \
181 emitm(&stream, 0x2b, 1);\
182 emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
185 #define SUB_EAXi(i32) \
186 emitm(&stream, 0x2d, 1);\
187 emitm(&stream, i32, 4);
191 emitm(&stream, 0xf7, 1);\
192 emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
196 emitm(&stream, 0xf7, 1);\
197 emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
200 #define ANDib(r8, i8) \
201 emitm(&stream, 0x80, 1);\
202 emitm(&stream, 7 << 5 | r8, 1);\
203 emitm(&stream, i8, 1);
206 #define ANDid(r32, i32) \
208 emitm(&stream, 0x25, 1);\
209 emitm(&stream, i32, 4);}\
211 emitm(&stream, 0x81, 1);\
212 emitm(&stream, 7 << 5 | r32, 1);\
213 emitm(&stream, i32, 4);}
216 #define ANDrd(dr32, sr32) \
217 emitm(&stream, 0x23, 1);\
218 emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
221 #define ORrd(dr32, sr32) \
222 emitm(&stream, 0x0b, 1);\
223 emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
226 #define ORid(r32, i32) \
228 emitm(&stream, 0x0d, 1);\
229 emitm(&stream, i32, 4);}\
231 emitm(&stream, 0x81, 1);\
232 emitm(&stream, 25 << 3 | r32, 1);\
233 emitm(&stream, i32, 4);}
236 #define SHLib(r32, i8) \
237 emitm(&stream, 0xc1, 1);\
238 emitm(&stream, 7 << 5 | r32 & 0x7, 1);\
239 emitm(&stream, i8, 1);
242 #define SHL_CLrb(dr32) \
243 emitm(&stream, 0xd3, 1);\
244 emitm(&stream, 7 << 5 | dr32 & 0x7, 1);
247 #define SHRib(r32, i8) \
248 emitm(&stream, 0xc1, 1);\
249 emitm(&stream, 29 << 3 | r32 & 0x7, 1);\
250 emitm(&stream, i8, 1);
253 #define SHR_CLrb(dr32) \
254 emitm(&stream, 0xd3, 1);\
255 emitm(&stream, 29 << 3 | dr32 & 0x7, 1);
259 emitm(&stream, 0xf7, 1);\
260 emitm(&stream, 27 << 3 | r32 & 0x7, 1);
262 /// cmp dr32,sr32[off]
263 #define CMPodd(dr32, sr32, off) \
264 emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \
265 emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
266 emitm(&stream, off, 1);
269 #define CMPrd(dr32, sr32) \
270 emitm(&stream, 0x3b, 1); \
271 emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
274 #define CMPid(dr32, i32) \
276 emitm(&stream, 0x3d, 1); \
277 emitm(&stream, i32, 4);} \
279 emitm(&stream, 0x81, 1); \
280 emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\
281 emitm(&stream, i32, 4);}
285 emitm(&stream, 0x75, 1);\
286 emitm(&stream, off8, 1);
290 emitm(&stream, 0x0f, 1);\
291 emitm(&stream, 0x84, 1);\
292 emitm(&stream, off32, 4);
296 emitm(&stream, 0x0f, 1);\
297 emitm(&stream, 0x8e, 1);\
298 emitm(&stream, off32, 4);
302 emitm(&stream, 0x7e, 1);\
303 emitm(&stream, off8, 1);
307 emitm(&stream, 0x0f, 1);\
308 emitm(&stream, 0x87, 1);\
309 emitm(&stream, off32, 4);
313 emitm(&stream, 0x0f, 1);\
314 emitm(&stream, 0x83, 1);\
315 emitm(&stream, off32, 4);
319 emitm(&stream, 0x0f, 1);\
320 emitm(&stream, 0x8f, 1);\
321 emitm(&stream, off32, 4);
325 emitm(&stream, 0x0f, 1);\
326 emitm(&stream, 0x8d, 1);\
327 emitm(&stream, off32, 4);
331 emitm(&stream, 0xe9, 1);\
332 emitm(&stream, off32, 4);
342 /**************************/
344 /**************************/
350 /** @defgroup NPF_code NPF functions
355 \brief BPF jitter, builds an x86 function from a BPF program.
356 \param fp The BPF pseudo-assembly filter that will be translated into x86 code.
357 \param nins Number of instructions of the input filter.
358 \return The JIT_BPF_Filter structure containing the x86 filtering binary.
360 BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp
363 JIT_BPF_Filter
* BPF_jitter(struct bpf_insn
*fp
, INT nins
);
366 \brief Translates a set of BPF instructions in a set of x86 ones.
367 \param ins Pointer to the BPF instructions that will be translated into x86 code.
368 \param nins Number of instructions to translate.
369 \param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor.
370 \return The x86 filtering function.
372 This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and
373 through the instruction macros defined in jitter.h it is able to create an function directly executable
376 BPF_filter_function
BPFtoX86(struct bpf_insn
*ins
, UINT nins
, INT
*mem
);
378 \brief Deletes a filtering function that was previously created by BPF_jitter().
379 \param Filter The filter to destroy.
381 This function frees the variuos buffers (code, memory, etc.) associated with a filtering function.
383 void BPF_Destroy_JIT_Filter(JIT_BPF_Filter
*Filter
);