source: lib/bpf-jit/bpf-jit.cc @ 322c516

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 322c516 was e966aa8, checked in by Shane Alcock <salcock@…>, 10 years ago
  • Fixed Perry's typo so that Perry can sleep at night
  • Property mode set to 100644
File size: 22.2 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*>(5,
277                        PointerType::get(IntegerType::get(getGlobalContext(), 8), 0), /*dest*/
278                        IntegerType::get(getGlobalContext(), 8),  /* i8 val */
279                        IntegerType::get(getGlobalContext(), 64), /* i64 len */
280                        IntegerType::get(getGlobalContext(), 32), /* i32 align */
281                        IntegerType::get(getGlobalContext(), 1)  /* i1 volatile */
282                        ),
283    /*isVarArg=*/false);
284 
285  // Function Declarations
286 
287  Function* func_bpf_run = Function::Create(
288    /*Type=*/FunctionType::get(
289        IntegerType::get(getGlobalContext(), 32),
290        construct_vector<const Type*>(2,
291                PointerType::get(IntegerType::get(getGlobalContext(), 8), 0),
292                IntegerType::get(getGlobalContext(), 32)),
293                false),
294    /*Linkage=*/GlobalValue::ExternalLinkage,
295    /*Name=*/"bpf_run", mod); 
296  func_bpf_run->setCallingConv(CallingConv::C);
297  AttrListPtr func_bpf_run_PAL;
298  {
299    SmallVector<AttributeWithIndex, 4> Attrs;
300    AttributeWithIndex PAWI;
301    PAWI.Index = 4294967295U; PAWI.Attrs = 0  | Attribute::NoUnwind;
302    Attrs.push_back(PAWI);
303    func_bpf_run_PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
304   
305  }
306  func_bpf_run->setAttributes(func_bpf_run_PAL);
307
308  Function* func_llvm_memset_i64 = Function::Create(
309    /*Type=*/memsetType,
310    /*Linkage=*/GlobalValue::ExternalLinkage,
311    /*Name=*/"llvm.memset.i64", mod); // (external, no body)
312  func_llvm_memset_i64->setCallingConv(CallingConv::C);
313  AttrListPtr func_llvm_memset_i64_PAL;
314  {
315    SmallVector<AttributeWithIndex, 4> Attrs;
316    AttributeWithIndex PAWI;
317    PAWI.Index = 1U; PAWI.Attrs = 0  | Attribute::NoCapture;
318    Attrs.push_back(PAWI);
319    PAWI.Index = 4294967295U; PAWI.Attrs = 0  | Attribute::NoUnwind;
320    Attrs.push_back(PAWI);
321    func_llvm_memset_i64_PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
322   
323  }
324  func_llvm_memset_i64->setAttributes(func_llvm_memset_i64_PAL);
325 
326 
327  // Global Variable Declarations
328
329 
330  // Constant Definitions
331  ConstantInt* const_int8_12 = ConstantInt::get(getGlobalContext(), APInt(8,  StringRef("0"), 10));
332  ConstantInt* const_int64_13 = ConstantInt::get(getGlobalContext(), APInt(64,  StringRef("1056"), 10));
333  ConstantInt* const_int32_14 = ConstantInt::get(getGlobalContext(), APInt(32,  StringRef("8"), 10));
334  ConstantInt* const_int1_false = ConstantInt::get(getGlobalContext(), APInt(1,  StringRef("0"), 10));
335 
336  // Function: bpf_run (func_bpf_run)
337  {
338    Function::arg_iterator args = func_bpf_run->arg_begin();
339    Value* ptr_packet = args++;
340    ptr_packet->setName("packet");
341    Value* int32_len = args++;
342    int32_len->setName("len");
343   
344    BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_bpf_run,0);
345   
346    // Block entry (label_entry)
347/* Create function variables */
348    AllocaInst* ptr_packet_addr = new AllocaInst(
349        PointerType::get(IntegerType::get(getGlobalContext(), 8), 0), "packet_addr", label_entry);
350    AllocaInst* ptr_len_addr = new AllocaInst(IntegerType::get(getGlobalContext(), 32), "len_addr", label_entry);
351    AllocaInst* ptr_retval = new AllocaInst(IntegerType::get(getGlobalContext(), 32), "retval", label_entry);
352    AllocaInst* ptr_state = new AllocaInst(mod->getTypeByName(std::string("struct.bpf_state_t")),
353                                 "state", label_entry);
354/* Store the arguments */
355     new StoreInst(ptr_packet, ptr_packet_addr, false, label_entry);
356     new StoreInst(int32_len, ptr_len_addr, false, label_entry);
357/* Memset state */
358    CastInst* ptr_state1 = new BitCastInst(ptr_state, 
359                PointerType::get(IntegerType::get(getGlobalContext(), 8), 0),
360                "state1", label_entry);
361    std::vector<Value*> void_25_params;
362    void_25_params.push_back(ptr_state1);       /* dest */
363    void_25_params.push_back(const_int8_12);    /* value */
364    void_25_params.push_back(const_int64_13);   /* length */
365    void_25_params.push_back(const_int32_14);   /* alignment */
366    void_25_params.push_back(const_int1_false); /* volatile */
367    CallInst* void_25 = CallInst::Create(func_llvm_memset_i64, 
368                void_25_params.begin(), void_25_params.end(), 
369                "", 
370                label_entry);
371    void_25->setCallingConv(CallingConv::C);
372    void_25->setTailCall(false);
373    AttrListPtr void_25_PAL;
374    void_25->setAttributes(void_25_PAL);
375 
376 /* set state->P */
377    std::vector<Value*> state_p_offset = construct_vector<Value*>(2, 
378                ConstantInt::get(getGlobalContext(),APInt(32,0)),
379                ConstantInt::get(getGlobalContext(),APInt(32,2)));
380
381    Instruction* state_p_ptr = GetElementPtrInst::Create(ptr_state, 
382        state_p_offset.begin(), 
383        state_p_offset.end(), "state_p_ptr", 
384        label_entry);
385
386    new StoreInst(new LoadInst(ptr_packet_addr, "load_ptr_packet_addr", false, label_entry), 
387        state_p_ptr, false, label_entry);
388
389 /* set state->len */
390    std::vector<Value*> state_len_offset = construct_vector<Value*>(2, 
391                ConstantInt::get(getGlobalContext(),APInt(32,0)),
392                ConstantInt::get(getGlobalContext(),APInt(32,3)));
393    Instruction* state_len_ptr = GetElementPtrInst::Create(ptr_state, state_len_offset.begin(), state_len_offset.end(), "state_len_ptr", label_entry);
394     new StoreInst(new LoadInst(ptr_len_addr, "len", false, label_entry), state_len_ptr, false, label_entry);
395   
396    // Build one block per bpf instruction in our program
397    std::map<int, BasicBlock *> blocks;
398    BasicBlock *fail = BasicBlock::Create(getGlobalContext(), "fail", func_bpf_run, 0);
399    BasicBlock *success = BasicBlock::Create(getGlobalContext(), "success", func_bpf_run, 0);
400    for(int i=0; i<plen; ++i) {
401            char name[32];
402            sprintf(name,"bpf_isn_%d",i);
403            blocks.insert(std::make_pair(i, 
404                BasicBlock::Create(getGlobalContext(), std::string(name), func_bpf_run, 0)));
405    }
406
407    BranchInst::Create(blocks[0], label_entry);
408
409    // For each opcode, generate a call to the opcode that implements that function
410    // check if the function returns "continue" (~0U) "fail" (0) or "success" (other wise)
411    for(int i=0; i<plen; ++i) {
412            BasicBlock *this_block = blocks[i];
413            BasicBlock *next_block;
414            if (blocks.find(i+1) != blocks.end()) 
415                    next_block = blocks[i+1];
416            else
417                    next_block = fail;
418
419            switch (insns[i].code) {
420                    case BPF_JMP+BPF_JGE+BPF_K:
421                        construct_jge_k(mod,i,insns[i],ptr_state,blocks);
422                        break;
423
424                    case BPF_JMP+BPF_JEQ+BPF_K:
425                        construct_jeq_k(mod,i,insns[i],ptr_state,blocks);
426                        break;
427
428                    case BPF_JMP+BPF_JGT+BPF_K:
429                        construct_jgt_k(mod,i,insns[i],ptr_state,blocks);
430                        break;
431
432                    case BPF_JMP+BPF_JSET+BPF_K:
433                        construct_jset_x(mod,i,insns[i],ptr_state,blocks);
434                        break;
435
436                    case BPF_JMP+BPF_JGE+BPF_X:
437                        construct_jge_x(mod,i,insns[i],ptr_state,blocks);
438                        break;
439
440                    case BPF_JMP+BPF_JEQ+BPF_X:
441                        construct_jeq_x(mod,i,insns[i],ptr_state,blocks);
442                        break;
443
444                    case BPF_JMP+BPF_JGT+BPF_X:
445                        construct_jgt_x(mod,i,insns[i],ptr_state,blocks);
446                        break;
447
448                    case BPF_JMP+BPF_JSET+BPF_X:
449                        abort();
450
451
452                    default:
453                            if (!opcode_names[insns[i].code])
454                                    printf("Unknown opcode %02x\n", insns[i].code);
455
456
457                            Function* func_opcode = mod->getFunction(opcode_names[insns[i].code]);
458                            if (!func_opcode) {
459                                    printf("Couldn't find function for %s\n",opcode_names[insns[i].code]);
460                            }
461
462                            std::vector<Value*> opcode_params;
463                            opcode_params.push_back(ptr_state);
464                            opcode_params.push_back(
465                                            ConstantInt::get(getGlobalContext(), APInt(8, insns[i].jt)));
466                            opcode_params.push_back(
467                                            ConstantInt::get(getGlobalContext(), APInt(8, insns[i].jf)));
468                            opcode_params.push_back(
469                                            ConstantInt::get(getGlobalContext(), APInt(64, insns[i].k)));
470
471                            CallInst* opcode = CallInst::Create(
472                                            func_opcode, 
473                                            opcode_params.begin(), 
474                                            opcode_params.end(), "bpf_opcode_call", 
475                                            this_block);
476                            opcode->setCallingConv(CallingConv::C);
477                            opcode->setTailCall(false);
478                            AttrListPtr opcode_PAL;
479                            {
480                                    SmallVector<AttributeWithIndex, 4> Attrs;
481                                    AttributeWithIndex PAWI;
482                                    PAWI.Index = 2U; PAWI.Attrs = 0  | Attribute::ZExt;
483                                    Attrs.push_back(PAWI);
484                                    PAWI.Index = 3U; PAWI.Attrs = 0  | Attribute::ZExt;
485                                    Attrs.push_back(PAWI);
486                                    PAWI.Index = 4294967295U; PAWI.Attrs = 0  | Attribute::NoUnwind;
487                                    Attrs.push_back(PAWI);
488                                    opcode_PAL = AttrListPtr::get(Attrs.begin(), Attrs.end());
489                            }
490                            opcode->setAttributes(opcode_PAL);
491
492                            new StoreInst(opcode, ptr_retval, this_block);
493
494                            ICmpInst *cmp = new ICmpInst(*this_block, ICmpInst::ICMP_NE, opcode, 
495                                            ConstantInt::get(getGlobalContext(), APInt(32, ~0U)),
496                                            "cmp_failure");
497
498                            BranchInst::Create(success, next_block, cmp, this_block);
499                            break;
500            }
501    }
502
503    /* Create an instruction so if we get here we fail */
504    ReturnInst::Create(getGlobalContext(), 
505        ConstantInt::get(getGlobalContext(), APInt(32, 0)),
506        fail);
507
508    /* Create a success return */
509    ReturnInst::Create(getGlobalContext(), 
510                    new LoadInst(ptr_retval, "retval", success),
511                    success);
512  }
513
514  return mod;
515 
516}
517
518void initialise_array(void)
519{
520        opcode_names[BPF_LD+BPF_W+BPF_ABS]      = "bpf_ldw_abs";
521        opcode_names[BPF_LD+BPF_H+BPF_ABS]      = "bpf_ldh_abs";
522        opcode_names[BPF_LD+BPF_B+BPF_ABS]      = "bpf_ldb_abs";
523        opcode_names[BPF_LD+BPF_W+BPF_IND]      = "bpf_ldw_ind";
524        opcode_names[BPF_LD+BPF_H+BPF_IND]      = "bpf_ldh_ind";
525        opcode_names[BPF_LD+BPF_B+BPF_IND]      = "bpf_ldb_ind";
526        opcode_names[BPF_LD+BPF_IMM]            = "bpf_ldb_imm";
527        opcode_names[BPF_LD+BPF_MEM]            = "bpf_ldb_mem";
528       
529        opcode_names[BPF_LDX+BPF_W+BPF_IMM]     = "bpf_ldx_imm";
530        opcode_names[BPF_LDX+BPF_W+BPF_MEM]     = "bpf_ldx_mem";
531        opcode_names[BPF_LDX+BPF_W+BPF_LEN]     = "bpf_ldx_len";
532        opcode_names[BPF_LDX+BPF_B+BPF_MSH]     = "bpf_ldx_msh";
533
534        opcode_names[BPF_ST]                    = "bpf_st";
535        opcode_names[BPF_STX]                   = "bpf_stx";
536
537        opcode_names[BPF_ALU+BPF_ADD+BPF_K]     = "bpf_alu_add_k";
538        opcode_names[BPF_ALU+BPF_SUB+BPF_K]     = "bpf_alu_sub_k";
539        opcode_names[BPF_ALU+BPF_MUL+BPF_K]     = "bpf_alu_mul_k";
540        opcode_names[BPF_ALU+BPF_DIV+BPF_K]     = "bpf_alu_div_k";
541        opcode_names[BPF_ALU+BPF_AND+BPF_K]     = "bpf_alu_and_k";
542        opcode_names[BPF_ALU+BPF_OR+BPF_K]      = "bpf_alu_or_k";
543        opcode_names[BPF_ALU+BPF_LSH+BPF_K]     = "bpf_alu_lsh_k";
544        opcode_names[BPF_ALU+BPF_RSH+BPF_K]     = "bpf_alu_rsh_k";
545
546        opcode_names[BPF_ALU+BPF_NEG]           = "bpf_alu_neg";
547
548        opcode_names[BPF_ALU+BPF_ADD+BPF_X]     = "bpf_alu_add_x";
549        opcode_names[BPF_ALU+BPF_SUB+BPF_X]     = "bpf_alu_sub_x";
550        opcode_names[BPF_ALU+BPF_MUL+BPF_X]     = "bpf_alu_mul_x";
551        opcode_names[BPF_ALU+BPF_DIV+BPF_X]     = "bpf_alu_div_x";
552        opcode_names[BPF_ALU+BPF_AND+BPF_X]     = "bpf_alu_and_x";
553        opcode_names[BPF_ALU+BPF_OR+BPF_X]      = "bpf_alu_or_x";
554        opcode_names[BPF_ALU+BPF_LSH+BPF_X]     = "bpf_alu_lsh_x";
555        opcode_names[BPF_ALU+BPF_RSH+BPF_X]     = "bpf_alu_rsh_x";
556
557        opcode_names[BPF_JMP+BPF_JA]            = "bpf_ja";
558        opcode_names[BPF_JMP+BPF_JGT+BPF_K]     = "bpf_gt_k";
559        opcode_names[BPF_JMP+BPF_JGE+BPF_K]     = "bpf_ge_k";
560        opcode_names[BPF_JMP+BPF_JEQ+BPF_K]     = "bpf_eq_k";
561        opcode_names[BPF_JMP+BPF_JSET+BPF_K]    = "bpf_set_k";
562        opcode_names[BPF_JMP+BPF_JGT+BPF_X]     = "bpf_gt_x";
563        opcode_names[BPF_JMP+BPF_JGE+BPF_X]     = "bpf_ge_x";
564        opcode_names[BPF_JMP+BPF_JEQ+BPF_X]     = "bpf_eq_x";
565        opcode_names[BPF_JMP+BPF_JSET+BPF_X]    = "bpf_set_x";
566
567        opcode_names[BPF_RET+BPF_A]             = "bpf_ret_a";
568        opcode_names[BPF_RET+BPF_K]             = "bpf_ret_k";
569
570        opcode_names[BPF_MISC+BPF_TAX]          = "bpf_tax";
571        opcode_names[BPF_MISC+BPF_TXA]          = "bpf_txa";
572
573}
574
575/* Sample BPF Program */
576struct bpf_insn insns[] = {
577        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),
578        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_REVARP, 0, 3),
579        BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 20),
580        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, /*REVARP_REQUEST*/6, 0, 1),
581        BPF_STMT(BPF_RET+BPF_K, sizeof(struct ether_arp) +
582                        sizeof(struct ether_header)),
583        BPF_STMT(BPF_RET+BPF_K, 0),
584};
585
586
587/* To external users we pass around a "bpf_jit_t", but actually it's layed out as a bpf_jit_private_t
588 * This is so people can use this from C, even tho we have C++ objects refered to from here.
589 */
590struct bpf_jit_private_t {
591        bpf_jit_t bpf_jit;
592        LLVMContext context;
593        ExecutionEngine *EE;
594};
595
596
597extern "C"
598bpf_jit_t *compile_program(struct bpf_insn insns[], int plen) 
599{
600  initialise_array();
601
602  struct bpf_jit_private_t * bpf_jitpriv
603        = (bpf_jit_private_t*)malloc(sizeof(bpf_jit_private_t));
604  Module *mod;
605
606  libtraceContext = new LLVMContext();
607  mod = build_bpf_program(insns,plen);
608
609  verifyModule(*mod, PrintMessageAction);
610
611  PassManager PM;
612
613  std::string errorStr;
614  PM.add(new TargetData(mod));
615
616#if OPTIMISE
617  /* We need -O3, because inlining is very important to us */
618  createStandardModulePasses(&PM, 
619        /* -O3 */ 3,
620        false,  /* Optimise for size? */
621        true,   /* UnitAtAtime -- Allow optimisations that may make global module changes*/
622        false,  /* Loop Unrolling? -- We don't support loops! */
623        true,   /* Simplify Library Calls */
624        false,  /* Exception support needed? */
625        createFunctionInliningPass() /* Inlining Pass To use */
626  );
627
628  createStandardLTOPasses(&PM,
629        false,  /* Internalize -- Useless, we've done it already */
630        true,   /* Run Inliner -- If anything hasn't been inlined, do it now */
631        false   /* Verify Each */
632  );
633#endif
634
635#if OUTPUT_COMPILED
636  /* Display the output */
637  PM.add(createPrintModulePass(&outs()));
638#endif
639
640  PM.run(*mod);
641
642  InitializeNativeTarget();
643
644  EngineBuilder EB = EngineBuilder(mod);
645  EB.setErrorStr(&errorStr);
646  EB.setEngineKind(EngineKind::JIT);
647
648  bpf_jitpriv->EE = EB.create();
649  if (!bpf_jitpriv->EE) {
650        std::cerr << "Failed to create JIT: " << errorStr << std::endl;
651  }
652  assert(bpf_jitpriv->EE);
653
654  bpf_jitpriv->bpf_jit.bpf_run = 
655        reinterpret_cast<bpf_run_t>(bpf_jitpriv->EE->getPointerToFunction(mod->getFunction("bpf_run")));
656
657
658/*
659  delete bpf_jit->EE;
660  delete libtraceContext;
661  free(bpf_jit);
662*/
663
664  return reinterpret_cast<bpf_jit_t*>(bpf_jitpriv);
665}
666
667extern "C"
668void destroy_program(struct bpf_jit_t *bpf_jit)
669{
670        struct bpf_jit_private_t *priv=reinterpret_cast<bpf_jit_private_t*>(bpf_jit);
671
672        delete priv->EE;
673        delete libtraceContext;
674        priv->bpf_jit.bpf_run = NULL;
675        free(bpf_jit);
676}
677
Note: See TracBrowser for help on using the repository browser.