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

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file was ee6e802, checked in by Shane Alcock <salcock@…>, 5 years ago

Updated copyright blurb on all source files

In some cases, this meant adding copyright blurbs to files that
had never had them before.

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