source: lib/bpf-jit/bpf-jit.cc @ d48008d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since d48008d was d48008d, checked in by Perry Lorier <perry@…>, 11 years ago

Add JITting of BPF bytecode using LLVM

  • Property mode set to 100644
File size: 21.8 KB
Line 
1#define OPTIMISE 1
2#define OUTPUT_COMPILED 0
3
4#include "bpf-jit/bpf-jit.h"
5#include <llvm/LLVMContext.h>
6namespace llvm {
7class LLVMContext;
8LLVMContext *libtraceContext;
9}
10#define getGlobalContext() (*libtraceContext)
11#include <llvm/Module.h>
12#include <llvm/DerivedTypes.h>
13#include <llvm/Constants.h>
14#include <llvm/Instructions.h>
15#include <llvm/ModuleProvider.h>
16#include <llvm/Analysis/Verifier.h>
17#include <llvm/ExecutionEngine/JIT.h>
18#include <llvm/ExecutionEngine/Interpreter.h>
19#include <llvm/ExecutionEngine/GenericValue.h>
20
21#include <llvm/CallingConv.h>
22#include <llvm/PassManager.h>
23#include <llvm/Support/StandardPasses.h>
24#include <llvm/Target/TargetData.h>
25#include <llvm/Target/TargetSelect.h>
26#ifdef OUTPUT_COMPILED
27#include <llvm/Assembly/PrintModulePass.h>
28#include <llvm/Support/FormattedStream.h>
29#endif
30#include <llvm/LinkAllPasses.h>
31
32#include <iostream>
33#include <algorithm>
34#include <map>
35#include <stdarg.h>
36
37#include <pcap-bpf.h>
38#include <net/ethernet.h>
39#include <netinet/if_ether.h>
40#include <boost/lexical_cast.hpp>
41
42
43using namespace llvm;
44
45#include "bpf-jit/bpf-opcodes.llvm.cc"
46
47static const char *opcode_names[256];
48
49template <class X>
50static std::vector<X> construct_vector(int items, ...)
51{
52        std::vector<X> ret;
53        va_list va;
54        va_start(va,items);
55        for(int i=0;i<items;++i) {
56                ret.push_back(va_arg(va,X));
57        }
58        va_end(va);
59        return ret;
60}
61
62static void construct_jeq_k(Module *mod, int insnum, const struct bpf_insn &insn, 
63                AllocaInst *ptr_state,
64                std::map<int,BasicBlock *> &blocks)
65{
66        BasicBlock *this_block = blocks[insnum];
67        BasicBlock *true_block = blocks[insnum+1+insn.jt];
68        BasicBlock *false_block = blocks[insnum+1+insn.jf];
69
70        std::vector<Value*> a_offsets = construct_vector<Value*>(2,
71                ConstantInt::get(getGlobalContext(),APInt(32,0)),
72                ConstantInt::get(getGlobalContext(),APInt(32,0))
73        );
74
75        Instruction *a = GetElementPtrInst::Create(ptr_state,
76                        a_offsets.begin(), a_offsets.end(), "state_a", this_block);
77
78        ICmpInst *cmp = new ICmpInst(*this_block, ICmpInst::ICMP_EQ, 
79                                new LoadInst(a,"avalue", this_block),
80                                ConstantInt::get(getGlobalContext(), APInt(32, insn.k)),
81                                std::string("cmp_a_vs_")+boost::lexical_cast<std::string>(insn.k));
82
83        BranchInst::Create(true_block, false_block, cmp, this_block);
84}
85
86static void construct_jgt_k(Module *mod, int insnum, const struct bpf_insn &insn, 
87                AllocaInst *ptr_state,
88                std::map<int,BasicBlock *> &blocks)
89{
90        BasicBlock *this_block = blocks[insnum];
91        BasicBlock *true_block = blocks[insnum+1+insn.jt];
92        BasicBlock *false_block = blocks[insnum+1+insn.jf];
93
94        std::vector<Value*> a_offsets = construct_vector<Value*>(2,
95                ConstantInt::get(getGlobalContext(),APInt(32,0)),
96                ConstantInt::get(getGlobalContext(),APInt(32,0))
97        );
98
99        Instruction *a = GetElementPtrInst::Create(ptr_state,
100                        a_offsets.begin(), a_offsets.end(), "state_a", this_block);
101
102        ICmpInst *cmp = new ICmpInst(*this_block, ICmpInst::ICMP_UGT, 
103                                new LoadInst(a,"avalue", this_block),
104                                ConstantInt::get(getGlobalContext(), APInt(32, insn.k)),
105                                "cmp_a_vs_k");
106
107        BranchInst::Create(true_block, false_block, cmp, this_block);
108}
109
110static void construct_jge_k(Module *mod, int insnum, const struct bpf_insn &insn, 
111                AllocaInst *ptr_state,
112                std::map<int,BasicBlock *> &blocks)
113{
114        BasicBlock *this_block = blocks[insnum];
115        BasicBlock *true_block = blocks[insnum+1+insn.jt];
116        BasicBlock *false_block = blocks[insnum+1+insn.jf];
117
118        std::vector<Value*> a_offsets = construct_vector<Value*>(2,
119                ConstantInt::get(getGlobalContext(),APInt(32,0)),
120                ConstantInt::get(getGlobalContext(),APInt(32,0))
121        );
122
123        Instruction *a = GetElementPtrInst::Create(ptr_state,
124                        a_offsets.begin(), a_offsets.end(), "state_a", this_block);
125
126        ICmpInst *cmp = new ICmpInst(*this_block, ICmpInst::ICMP_UGE, 
127                                new LoadInst(a,"avalue", this_block),
128                                ConstantInt::get(getGlobalContext(), APInt(32, insn.k)),
129                                "cmp_a_vs_k");
130
131        BranchInst::Create(true_block, false_block, cmp, this_block);
132}
133
134static void construct_jeq_x(Module *mod, int insnum, const struct bpf_insn &insn, 
135                AllocaInst *ptr_state,
136                std::map<int,BasicBlock *> &blocks)
137{
138        BasicBlock *this_block = blocks[insnum];
139        BasicBlock *true_block = blocks[insnum+1+insn.jt];
140        BasicBlock *false_block = blocks[insnum+1+insn.jf];
141
142        std::vector<Value*> a_offsets = construct_vector<Value*>(2,
143                ConstantInt::get(getGlobalContext(),APInt(32,0)),
144                ConstantInt::get(getGlobalContext(),APInt(32,0))
145        );
146
147        std::vector<Value*> x_offsets = construct_vector<Value*>(2,
148                ConstantInt::get(getGlobalContext(),APInt(32,0)),
149                ConstantInt::get(getGlobalContext(),APInt(32,1))
150        );
151
152        Instruction *a = GetElementPtrInst::Create(ptr_state,
153                        a_offsets.begin(), a_offsets.end(), "state_a", this_block);
154
155        Instruction *x = GetElementPtrInst::Create(ptr_state,
156                        x_offsets.begin(), x_offsets.end(), "state_x", this_block);
157
158        ICmpInst *cmp = new ICmpInst(*this_block, ICmpInst::ICMP_EQ, 
159                                new LoadInst(a,"avalue", this_block),
160                                new LoadInst(x,"xvalue", this_block),
161                                "cmp_a_vs_x");
162
163        BranchInst::Create(true_block, false_block, cmp, this_block);
164}
165
166static void construct_jgt_x(Module *mod, int insnum, const struct bpf_insn &insn, 
167                AllocaInst *ptr_state,
168                std::map<int,BasicBlock *> &blocks)
169{
170        BasicBlock *this_block = blocks[insnum];
171        BasicBlock *true_block = blocks[insnum+1+insn.jt];
172        BasicBlock *false_block = blocks[insnum+1+insn.jf];
173
174        std::vector<Value*> a_offsets = construct_vector<Value*>(2,
175                ConstantInt::get(getGlobalContext(),APInt(32,0)),
176                ConstantInt::get(getGlobalContext(),APInt(32,0))
177        );
178
179        std::vector<Value*> x_offsets = construct_vector<Value*>(2,
180                ConstantInt::get(getGlobalContext(),APInt(32,0)),
181                ConstantInt::get(getGlobalContext(),APInt(32,1))
182        );
183
184        Instruction *a = GetElementPtrInst::Create(ptr_state,
185                        a_offsets.begin(), a_offsets.end(), "state_a", this_block);
186
187        Instruction *x = GetElementPtrInst::Create(ptr_state,
188                        x_offsets.begin(), x_offsets.end(), "state_x", this_block);
189
190        ICmpInst *cmp = new ICmpInst(*this_block, ICmpInst::ICMP_UGT, 
191                                new LoadInst(a,"avalue", this_block),
192                                new LoadInst(x,"xvalue", this_block),
193                                "cmp_a_vs_x");
194
195        BranchInst::Create(true_block, false_block, cmp, this_block);
196}
197
198static void construct_jset_x(Module *mod, int insnum, const struct bpf_insn &insn, 
199                AllocaInst *ptr_state,
200                std::map<int,BasicBlock *> &blocks)
201{
202        BasicBlock *this_block = blocks[insnum];
203        BasicBlock *true_block = blocks[insnum+1+insn.jt];
204        BasicBlock *false_block = blocks[insnum+1+insn.jf];
205
206        std::vector<Value*> a_offsets = construct_vector<Value*>(2,
207                ConstantInt::get(getGlobalContext(),APInt(32,0)),
208                ConstantInt::get(getGlobalContext(),APInt(32,0))
209        );
210
211        std::vector<Value*> x_offsets = construct_vector<Value*>(2,
212                ConstantInt::get(getGlobalContext(),APInt(32,0)),
213                ConstantInt::get(getGlobalContext(),APInt(32,1))
214        );
215
216        Instruction *a = GetElementPtrInst::Create(ptr_state,
217                        a_offsets.begin(), a_offsets.end(), "state_a", this_block);
218
219        Instruction *x = GetElementPtrInst::Create(ptr_state,
220                        x_offsets.begin(), x_offsets.end(), "state_x", this_block);
221
222        BinaryOperator* band = BinaryOperator::Create(Instruction::And, 
223                                new LoadInst(a,"valuea_", this_block),
224                                new LoadInst(a,"valuex_", this_block),
225                                "and_a_and_x_",
226                                this_block
227                                );
228
229        ICmpInst *cmp = new ICmpInst(*this_block, ICmpInst::ICMP_EQ, 
230                                band,
231                                ConstantInt::get(getGlobalContext(), APInt(32, 0)),
232                                "cmp_a_and_x");
233
234        BranchInst::Create(true_block, false_block, cmp, this_block);
235}
236
237static void construct_jge_x(Module *mod, int insnum, const struct bpf_insn &insn, 
238                AllocaInst *ptr_state,
239                std::map<int,BasicBlock *> &blocks)
240{
241        BasicBlock *this_block = blocks[insnum];
242        BasicBlock *true_block = blocks[insnum+1+insn.jt];
243        BasicBlock *false_block = blocks[insnum+1+insn.jf];
244
245        std::vector<Value*> a_offsets = construct_vector<Value*>(2,
246                ConstantInt::get(getGlobalContext(),APInt(32,0)),
247                ConstantInt::get(getGlobalContext(),APInt(32,0))
248        );
249
250        std::vector<Value*> x_offsets = construct_vector<Value*>(2,
251                ConstantInt::get(getGlobalContext(),APInt(32,0)),
252                ConstantInt::get(getGlobalContext(),APInt(32,1))
253        );
254
255        Instruction *a = GetElementPtrInst::Create(ptr_state,
256                        a_offsets.begin(), a_offsets.end(), "state_a", this_block);
257
258        Instruction *x = GetElementPtrInst::Create(ptr_state,
259                        x_offsets.begin(), x_offsets.end(), "state_x", this_block);
260
261        ICmpInst *cmp = new ICmpInst(*this_block, ICmpInst::ICMP_UGE, 
262                                new LoadInst(a,"avalue", this_block),
263                                new LoadInst(x,"xvalue", this_block),
264                                "cmp_a_vs_x");
265
266        BranchInst::Create(true_block, false_block, cmp, this_block);
267}
268
269Module* build_bpf_program(struct bpf_insn insns[], int plen) 
270{
271  // Module Construction
272  Module* mod = makeLLVMModule();
273 
274  FunctionType* memsetType = FunctionType::get(
275    /*Result=*/Type::getVoidTy(getGlobalContext()),
276                construct_vector<const Type*>(4,
277                        PointerType::get(IntegerType::get(getGlobalContext(), 8), 0),
278                        IntegerType::get(getGlobalContext(), 8),
279                        IntegerType::get(getGlobalContext(), 64),
280                        IntegerType::get(getGlobalContext(), 32)),
281    /*isVarArg=*/false);
282 
283  // Function Declarations
284 
285  Function* func_bpf_run = Function::Create(
286    /*Type=*/FunctionType::get(
287        IntegerType::get(getGlobalContext(), 32),
288        construct_vector<const Type*>(2,
289                PointerType::get(IntegerType::get(getGlobalContext(), 8), 0),
290                IntegerType::get(getGlobalContext(), 32)),
291                false),
292    /*Linkage=*/GlobalValue::ExternalLinkage,
293    /*Name=*/"bpf_run", mod); 
294  func_bpf_run->setCallingConv(CallingConv::C);
295  AttrListPtr func_bpf_run_PAL;
296  {
297    SmallVector<AttributeWithIndex, 4> Attrs;
298    AttributeWithIndex PAWI;
299    PAWI.Index = 4294967295U; PAWI.Attrs = 0  | Attribute::NoUnwind;
300    Attrs.push_back(PAWI);
301    func_bpf_run_PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
302   
303  }
304  func_bpf_run->setAttributes(func_bpf_run_PAL);
305
306  Function* func_llvm_memset_i64 = Function::Create(
307    /*Type=*/memsetType,
308    /*Linkage=*/GlobalValue::ExternalLinkage,
309    /*Name=*/"llvm.memset.i64", mod); // (external, no body)
310  func_llvm_memset_i64->setCallingConv(CallingConv::C);
311  AttrListPtr func_llvm_memset_i64_PAL;
312  {
313    SmallVector<AttributeWithIndex, 4> Attrs;
314    AttributeWithIndex PAWI;
315    PAWI.Index = 1U; PAWI.Attrs = 0  | Attribute::NoCapture;
316    Attrs.push_back(PAWI);
317    PAWI.Index = 4294967295U; PAWI.Attrs = 0  | Attribute::NoUnwind;
318    Attrs.push_back(PAWI);
319    func_llvm_memset_i64_PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
320   
321  }
322  func_llvm_memset_i64->setAttributes(func_llvm_memset_i64_PAL);
323 
324 
325  // Global Variable Declarations
326
327 
328  // Constant Definitions
329  ConstantInt* const_int8_12 = ConstantInt::get(getGlobalContext(), APInt(8,  StringRef("0"), 10));
330  ConstantInt* const_int64_13 = ConstantInt::get(getGlobalContext(), APInt(64,  StringRef("1056"), 10));
331  ConstantInt* const_int32_14 = ConstantInt::get(getGlobalContext(), APInt(32,  StringRef("8"), 10));
332 
333  // Function: bpf_run (func_bpf_run)
334  {
335    Function::arg_iterator args = func_bpf_run->arg_begin();
336    Value* ptr_packet = args++;
337    ptr_packet->setName("packet");
338    Value* int32_len = args++;
339    int32_len->setName("len");
340   
341    BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_bpf_run,0);
342   
343    // Block entry (label_entry)
344/* Create function variables */
345    AllocaInst* ptr_packet_addr = new AllocaInst(
346        PointerType::get(IntegerType::get(getGlobalContext(), 8), 0), "packet_addr", label_entry);
347    AllocaInst* ptr_len_addr = new AllocaInst(IntegerType::get(getGlobalContext(), 32), "len_addr", label_entry);
348    AllocaInst* ptr_retval = new AllocaInst(IntegerType::get(getGlobalContext(), 32), "retval", label_entry);
349    AllocaInst* ptr_state = new AllocaInst(mod->getTypeByName(std::string("struct.bpf_state_t")),
350                                 "state", label_entry);
351/* Store the arguments */
352     new StoreInst(ptr_packet, ptr_packet_addr, false, label_entry);
353     new StoreInst(int32_len, ptr_len_addr, false, label_entry);
354/* Memset state */
355    CastInst* ptr_state1 = new BitCastInst(ptr_state, 
356                PointerType::get(IntegerType::get(getGlobalContext(), 8), 0),
357                "state1", label_entry);
358    std::vector<Value*> void_25_params;
359    void_25_params.push_back(ptr_state1);
360    void_25_params.push_back(const_int8_12);
361    void_25_params.push_back(const_int64_13);
362    void_25_params.push_back(const_int32_14);
363    CallInst* void_25 = CallInst::Create(func_llvm_memset_i64, void_25_params.begin(), void_25_params.end(), "", label_entry);
364    void_25->setCallingConv(CallingConv::C);
365    void_25->setTailCall(false);AttrListPtr void_25_PAL;
366    void_25->setAttributes(void_25_PAL);
367 
368 /* set state->P */
369    std::vector<Value*> state_p_offset = construct_vector<Value*>(2, 
370                ConstantInt::get(getGlobalContext(),APInt(32,0)),
371                ConstantInt::get(getGlobalContext(),APInt(32,2)));
372
373    Instruction* state_p_ptr = GetElementPtrInst::Create(ptr_state, 
374        state_p_offset.begin(), 
375        state_p_offset.end(), "state_p_ptr", 
376        label_entry);
377
378    new StoreInst(new LoadInst(ptr_packet_addr, "load_ptr_packet_addr", false, label_entry), 
379        state_p_ptr, false, label_entry);
380
381 /* set state->len */
382    std::vector<Value*> state_len_offset = construct_vector<Value*>(2, 
383                ConstantInt::get(getGlobalContext(),APInt(32,0)),
384                ConstantInt::get(getGlobalContext(),APInt(32,3)));
385    Instruction* state_len_ptr = GetElementPtrInst::Create(ptr_state, state_len_offset.begin(), state_len_offset.end(), "state_len_ptr", label_entry);
386     new StoreInst(new LoadInst(ptr_len_addr, "len", false, label_entry), state_len_ptr, false, label_entry);
387   
388    // Build one block per bpf instruction in our program
389    std::map<int, BasicBlock *> blocks;
390    BasicBlock *fail = BasicBlock::Create(getGlobalContext(), "fail", func_bpf_run, 0);
391    BasicBlock *success = BasicBlock::Create(getGlobalContext(), "success", func_bpf_run, 0);
392    for(int i=0; i<plen; ++i) {
393            char name[32];
394            sprintf(name,"bpf_isn_%d",i);
395            blocks.insert(std::make_pair(i, 
396                BasicBlock::Create(getGlobalContext(), std::string(name), func_bpf_run, 0)));
397    }
398
399    BranchInst::Create(blocks[0], label_entry);
400
401    // For each opcode, generate a call to the opcode that implements that function
402    // check if the function returns "continue" (~0U) "fail" (0) or "success" (other wise)
403    for(int i=0; i<plen; ++i) {
404            BasicBlock *this_block = blocks[i];
405            BasicBlock *next_block;
406            if (blocks.find(i+1) != blocks.end()) 
407                    next_block = blocks[i+1];
408            else
409                    next_block = fail;
410
411            switch (insns[i].code) {
412                    case BPF_JMP+BPF_JGE+BPF_K:
413                        construct_jge_k(mod,i,insns[i],ptr_state,blocks);
414                        break;
415
416                    case BPF_JMP+BPF_JEQ+BPF_K:
417                        construct_jeq_k(mod,i,insns[i],ptr_state,blocks);
418                        break;
419
420                    case BPF_JMP+BPF_JGT+BPF_K:
421                        construct_jgt_k(mod,i,insns[i],ptr_state,blocks);
422                        break;
423
424                    case BPF_JMP+BPF_JSET+BPF_K:
425                        construct_jset_x(mod,i,insns[i],ptr_state,blocks);
426                        break;
427
428                    case BPF_JMP+BPF_JGE+BPF_X:
429                        construct_jge_x(mod,i,insns[i],ptr_state,blocks);
430                        break;
431
432                    case BPF_JMP+BPF_JEQ+BPF_X:
433                        construct_jeq_x(mod,i,insns[i],ptr_state,blocks);
434                        break;
435
436                    case BPF_JMP+BPF_JGT+BPF_X:
437                        construct_jgt_x(mod,i,insns[i],ptr_state,blocks);
438                        break;
439
440                    case BPF_JMP+BPF_JSET+BPF_X:
441                        abort();
442
443
444                    default:
445                            if (!opcode_names[insns[i].code])
446                                    printf("Unknown opcode %02x\n", insns[i].code);
447
448
449                            Function* func_opcode = mod->getFunction(opcode_names[insns[i].code]);
450                            if (!func_opcode) {
451                                    printf("Couldn't find function for %s\n",opcode_names[insns[i].code]);
452                            }
453
454                            std::vector<Value*> opcode_params;
455                            opcode_params.push_back(ptr_state);
456                            opcode_params.push_back(
457                                            ConstantInt::get(getGlobalContext(), APInt(8, insns[i].jt)));
458                            opcode_params.push_back(
459                                            ConstantInt::get(getGlobalContext(), APInt(8, insns[i].jf)));
460                            opcode_params.push_back(
461                                            ConstantInt::get(getGlobalContext(), APInt(64, insns[i].k)));
462
463                            CallInst* opcode = CallInst::Create(
464                                            func_opcode, 
465                                            opcode_params.begin(), 
466                                            opcode_params.end(), "bpf_opcode_call", 
467                                            this_block);
468                            opcode->setCallingConv(CallingConv::C);
469                            opcode->setTailCall(false);
470                            AttrListPtr opcode_PAL;
471                            {
472                                    SmallVector<AttributeWithIndex, 4> Attrs;
473                                    AttributeWithIndex PAWI;
474                                    PAWI.Index = 2U; PAWI.Attrs = 0  | Attribute::ZExt;
475                                    Attrs.push_back(PAWI);
476                                    PAWI.Index = 3U; PAWI.Attrs = 0  | Attribute::ZExt;
477                                    Attrs.push_back(PAWI);
478                                    PAWI.Index = 4294967295U; PAWI.Attrs = 0  | Attribute::NoUnwind;
479                                    Attrs.push_back(PAWI);
480                                    opcode_PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
481                            }
482                            opcode->setAttributes(opcode_PAL);
483
484                            new StoreInst(opcode, ptr_retval, this_block);
485
486                            ICmpInst *cmp = new ICmpInst(*this_block, ICmpInst::ICMP_NE, opcode, 
487                                            ConstantInt::get(getGlobalContext(), APInt(32, ~0U)),
488                                            "cmp_failure");
489
490                            BranchInst::Create(success, next_block, cmp, this_block);
491                            break;
492            }
493    }
494
495    /* Create an instruction so if we get here we fail */
496    ReturnInst::Create(getGlobalContext(), 
497        ConstantInt::get(getGlobalContext(), APInt(32, 0)),
498        fail);
499
500    /* Create a success return */
501    ReturnInst::Create(getGlobalContext(), 
502                    new LoadInst(ptr_retval, "retval", success),
503                    success);
504  }
505
506  return mod;
507 
508}
509
510void initialise_array(void)
511{
512        opcode_names[BPF_LD+BPF_W+BPF_ABS]      = "bpf_ldw_abs";
513        opcode_names[BPF_LD+BPF_H+BPF_ABS]      = "bpf_ldh_abs";
514        opcode_names[BPF_LD+BPF_B+BPF_ABS]      = "bpf_ldb_abs";
515        opcode_names[BPF_LD+BPF_W+BPF_IND]      = "bpf_ldw_ind";
516        opcode_names[BPF_LD+BPF_H+BPF_IND]      = "bpf_ldh_ind";
517        opcode_names[BPF_LD+BPF_B+BPF_IND]      = "bpf_ldb_ind";
518        opcode_names[BPF_LD+BPF_IMM]            = "bpf_ldb_imm";
519        opcode_names[BPF_LD+BPF_MEM]            = "bpf_ldb_mem";
520       
521        opcode_names[BPF_LDX+BPF_W+BPF_IMM]     = "bpf_ldx_imm";
522        opcode_names[BPF_LDX+BPF_W+BPF_MEM]     = "bpf_ldx_mem";
523        opcode_names[BPF_LDX+BPF_W+BPF_LEN]     = "bpf_ldx_len";
524        opcode_names[BPF_LDX+BPF_B+BPF_MSH]     = "bpf_ldx_msh";
525
526        opcode_names[BPF_ST]                    = "bpf_st";
527        opcode_names[BPF_STX]                   = "bpf_stx";
528
529        opcode_names[BPF_ALU+BPF_ADD+BPF_K]     = "bpf_alu_add_k";
530        opcode_names[BPF_ALU+BPF_SUB+BPF_K]     = "bpf_alu_sub_k";
531        opcode_names[BPF_ALU+BPF_MUL+BPF_K]     = "bpf_alu_mul_k";
532        opcode_names[BPF_ALU+BPF_DIV+BPF_K]     = "bpf_alu_div_k";
533        opcode_names[BPF_ALU+BPF_AND+BPF_K]     = "bpf_alu_and_k";
534        opcode_names[BPF_ALU+BPF_OR+BPF_K]      = "bpf_alu_or_k";
535        opcode_names[BPF_ALU+BPF_LSH+BPF_K]     = "bpf_alu_lsh_k";
536        opcode_names[BPF_ALU+BPF_RSH+BPF_K]     = "bpf_alu_rsh_k";
537
538        opcode_names[BPF_ALU+BPF_NEG]           = "bpf_alu_neg";
539
540        opcode_names[BPF_ALU+BPF_ADD+BPF_X]     = "bpf_alu_add_x";
541        opcode_names[BPF_ALU+BPF_SUB+BPF_X]     = "bpf_alu_sub_x";
542        opcode_names[BPF_ALU+BPF_MUL+BPF_X]     = "bpf_alu_mul_x";
543        opcode_names[BPF_ALU+BPF_DIV+BPF_X]     = "bpf_alu_div_x";
544        opcode_names[BPF_ALU+BPF_AND+BPF_X]     = "bpf_alu_and_x";
545        opcode_names[BPF_ALU+BPF_OR+BPF_X]      = "bpf_alu_or_x";
546        opcode_names[BPF_ALU+BPF_LSH+BPF_X]     = "bpf_alu_lsh_x";
547        opcode_names[BPF_ALU+BPF_RSH+BPF_X]     = "bpf_alu_rsh_x";
548
549        opcode_names[BPF_JMP+BPF_JA]            = "bpf_ja";
550        opcode_names[BPF_JMP+BPF_JGT+BPF_K]     = "bpf_gt_k";
551        opcode_names[BPF_JMP+BPF_JGE+BPF_K]     = "bpf_ge_k";
552        opcode_names[BPF_JMP+BPF_JEQ+BPF_K]     = "bpf_eq_k";
553        opcode_names[BPF_JMP+BPF_JSET+BPF_K]    = "bpf_set_k";
554        opcode_names[BPF_JMP+BPF_JGT+BPF_X]     = "bpf_gt_x";
555        opcode_names[BPF_JMP+BPF_JGE+BPF_X]     = "bpf_ge_x";
556        opcode_names[BPF_JMP+BPF_JEQ+BPF_X]     = "bpf_eq_x";
557        opcode_names[BPF_JMP+BPF_JSET+BPF_X]    = "bpf_set_x";
558
559        opcode_names[BPF_RET+BPF_A]             = "bpf_ret_a";
560        opcode_names[BPF_RET+BPF_K]             = "bpf_ret_k";
561
562        opcode_names[BPF_MISC+BPF_TAX]          = "bpf_tax";
563        opcode_names[BPF_MISC+BPF_TXA]          = "bpf_tax";
564
565}
566
567/* Sample BPF Program */
568struct bpf_insn insns[] = {
569        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
570        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_REVARP, 0, 3),
571        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
572        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, /*REVARP_REQUEST*/6, 0, 1),
573        BPF_STMT(BPF_RET+BPF_K, sizeof(struct ether_arp) +
574                        sizeof(struct ether_header)),
575        BPF_STMT(BPF_RET+BPF_K, 0),
576};
577
578
579/* To external users we pass around a "bpf_jit_t", but actually it's layed out as a bpf_jit_private_t
580 * This is so people can use this from C, even tho we have C++ objects refered to from here.
581 */
582struct bpf_jit_private_t {
583        bpf_jit_t bpf_jit;
584        LLVMContext context;
585        ExecutionEngine *EE;
586};
587
588
589extern "C"
590bpf_jit_t *compile_program(struct bpf_insn insns[], int plen) 
591{
592  initialise_array();
593
594  struct bpf_jit_private_t * bpf_jitpriv
595        = (bpf_jit_private_t*)malloc(sizeof(bpf_jit_private_t));
596  Module *mod;
597
598  libtraceContext = new LLVMContext();
599  mod = build_bpf_program(insns,plen);
600
601  verifyModule(*mod, PrintMessageAction);
602
603  PassManager PM;
604
605  std::string errorStr;
606  PM.add(new TargetData(mod));
607
608#if OPTIMISE
609  /* We need -O3, because inlining is very important to us */
610  createStandardModulePasses(&PM, 
611        /* -O3 */ 3,
612        false,  /* Optimise for size? */
613        true,   /* UnitAtAtime -- Allow optimisations that may make global module changes*/
614        false,  /* Loop Unrolling? -- We don't support loops! */
615        true,   /* Simplify Library Calls */
616        false,  /* Exception support needed? */
617        createFunctionInliningPass() /* Inlining Pass To use */
618  );
619
620  createStandardLTOPasses(&PM,
621        false,  /* Internalize -- Useless, we've done it already */
622        true,   /* Run Inliner -- If anything hasn't been inlined, do it now */
623        false   /* Verify Each */
624  );
625#endif
626
627#if OUTPUT_COMPILED
628  /* Display the output */
629  PM.add(createPrintModulePass(&outs()));
630#endif
631
632  PM.run(*mod);
633
634  InitializeNativeTarget();
635
636  EngineBuilder EB = EngineBuilder(mod);
637  EB.setErrorStr(&errorStr);
638  EB.setEngineKind(EngineKind::JIT);
639
640  bpf_jitpriv->EE = EB.create();
641  if (!bpf_jitpriv->EE) {
642        std::cerr << "Failed to create JIT: " << errorStr << std::endl;
643  }
644  assert(bpf_jitpriv->EE);
645
646  bpf_jitpriv->bpf_jit.bpf_run = 
647        reinterpret_cast<bpf_run_t>(bpf_jitpriv->EE->getPointerToFunction(mod->getFunction("bpf_run")));
648
649
650/*
651  delete bpf_jit->EE;
652  delete libtraceContext;
653  free(bpf_jit);
654*/
655
656  return reinterpret_cast<bpf_jit_t*>(bpf_jitpriv);
657}
658
659extern "C"
660void destroy_program(struct bpf_jit_t *bpf_jit)
661{
662        struct bpf_jit_private_t *priv=reinterpret_cast<bpf_jit_private_t*>(bpf_jit);
663
664        delete priv->EE;
665        delete libtraceContext;
666        priv->bpf_jit.bpf_run = NULL;
667        free(bpf_jit);
668}
669
Note: See TracBrowser for help on using the repository browser.