Home | History | Annotate | Download | only in cc
      1 /*
      2  * Copyright (c) 2015 PLUMgrid, Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #include <algorithm>
     17 #include <fcntl.h>
     18 #include <ftw.h>
     19 #include <map>
     20 #include <stdio.h>
     21 #include <string>
     22 #include <sys/stat.h>
     23 #include <sys/utsname.h>
     24 #include <unistd.h>
     25 #include <vector>
     26 #include <linux/bpf.h>
     27 
     28 #include <llvm/ADT/STLExtras.h>
     29 #include <llvm/ExecutionEngine/MCJIT.h>
     30 #include <llvm/ExecutionEngine/SectionMemoryManager.h>
     31 #include <llvm/IRReader/IRReader.h>
     32 #include <llvm/IR/IRBuilder.h>
     33 #include <llvm/IR/IRPrintingPasses.h>
     34 #include <llvm/IR/LegacyPassManager.h>
     35 #include <llvm/IR/LLVMContext.h>
     36 #include <llvm/IR/Module.h>
     37 #include <llvm/IR/Verifier.h>
     38 #include <llvm/Object/ObjectFile.h>
     39 #include <llvm/Support/FormattedStream.h>
     40 #include <llvm/Support/Host.h>
     41 #include <llvm/Support/SourceMgr.h>
     42 #include <llvm/Support/TargetSelect.h>
     43 #include <llvm/Transforms/IPO.h>
     44 #include <llvm/Transforms/IPO/PassManagerBuilder.h>
     45 #include <llvm-c/Transforms/IPO.h>
     46 
     47 #include "common.h"
     48 #include "bcc_debug.h"
     49 #include "bcc_exception.h"
     50 #include "frontends/b/loader.h"
     51 #include "frontends/clang/loader.h"
     52 #include "frontends/clang/b_frontend_action.h"
     53 #include "bpf_module.h"
     54 #include "exported_files.h"
     55 #include "kbuild_helper.h"
     56 #include "libbpf.h"
     57 
     58 namespace ebpf {
     59 
     60 using std::get;
     61 using std::make_tuple;
     62 using std::map;
     63 using std::move;
     64 using std::string;
     65 using std::tuple;
     66 using std::unique_ptr;
     67 using std::vector;
     68 using namespace llvm;
     69 
     70 const string BPFModule::FN_PREFIX = BPF_FN_PREFIX;
     71 
     72 // Snooping class to remember the sections as the JIT creates them
     73 class MyMemoryManager : public SectionMemoryManager {
     74  public:
     75 
     76   explicit MyMemoryManager(map<string, tuple<uint8_t *, uintptr_t>> *sections)
     77       : sections_(sections) {
     78   }
     79 
     80   virtual ~MyMemoryManager() {}
     81   uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
     82                                unsigned SectionID,
     83                                StringRef SectionName) override {
     84     uint8_t *Addr = SectionMemoryManager::allocateCodeSection(Size, Alignment, SectionID, SectionName);
     85     //printf("allocateCodeSection: %s Addr %p Size %ld Alignment %d SectionID %d\n",
     86     //       SectionName.str().c_str(), (void *)Addr, Size, Alignment, SectionID);
     87     (*sections_)[SectionName.str()] = make_tuple(Addr, Size);
     88     return Addr;
     89   }
     90   uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
     91                                unsigned SectionID, StringRef SectionName,
     92                                bool isReadOnly) override {
     93     uint8_t *Addr = SectionMemoryManager::allocateDataSection(Size, Alignment, SectionID, SectionName, isReadOnly);
     94     //printf("allocateDataSection: %s Addr %p Size %ld Alignment %d SectionID %d RO %d\n",
     95     //       SectionName.str().c_str(), (void *)Addr, Size, Alignment, SectionID, isReadOnly);
     96     (*sections_)[SectionName.str()] = make_tuple(Addr, Size);
     97     return Addr;
     98   }
     99   map<string, tuple<uint8_t *, uintptr_t>> *sections_;
    100 };
    101 
    102 BPFModule::BPFModule(unsigned flags, TableStorage *ts, bool rw_engine_enabled,
    103                      const std::string &maps_ns)
    104     : flags_(flags),
    105       rw_engine_enabled_(rw_engine_enabled),
    106       used_b_loader_(false),
    107       ctx_(new LLVMContext),
    108       id_(std::to_string((uintptr_t)this)),
    109       maps_ns_(maps_ns),
    110       ts_(ts) {
    111   InitializeNativeTarget();
    112   InitializeNativeTargetAsmPrinter();
    113   LLVMInitializeBPFTarget();
    114   LLVMInitializeBPFTargetMC();
    115   LLVMInitializeBPFTargetInfo();
    116   LLVMInitializeBPFAsmPrinter();
    117 #if LLVM_MAJOR_VERSION >= 6
    118   LLVMInitializeBPFAsmParser();
    119   if (flags & DEBUG_SOURCE)
    120     LLVMInitializeBPFDisassembler();
    121 #endif
    122   LLVMLinkInMCJIT(); /* call empty function to force linking of MCJIT */
    123   if (!ts_) {
    124     local_ts_ = createSharedTableStorage();
    125     ts_ = &*local_ts_;
    126   }
    127   func_src_ = ebpf::make_unique<FuncSource>();
    128 }
    129 
    130 static StatusTuple unimplemented_sscanf(const char *, void *) {
    131   return StatusTuple(-1, "sscanf unimplemented");
    132 }
    133 static StatusTuple unimplemented_snprintf(char *, size_t, const void *) {
    134   return StatusTuple(-1, "snprintf unimplemented");
    135 }
    136 
    137 BPFModule::~BPFModule() {
    138   for (auto &v : tables_) {
    139     v->key_sscanf = unimplemented_sscanf;
    140     v->leaf_sscanf = unimplemented_sscanf;
    141     v->key_snprintf = unimplemented_snprintf;
    142     v->leaf_snprintf = unimplemented_snprintf;
    143   }
    144 
    145   if (!rw_engine_enabled_) {
    146     for (auto section : sections_)
    147       delete[] get<0>(section.second);
    148   }
    149 
    150   engine_.reset();
    151   rw_engine_.reset();
    152   ctx_.reset();
    153   func_src_.reset();
    154 
    155   ts_->DeletePrefix(Path({id_}));
    156 }
    157 
    158 static void debug_printf(Module *mod, IRBuilder<> &B, const string &fmt, vector<Value *> args) {
    159   GlobalVariable *fmt_gvar = B.CreateGlobalString(fmt, "fmt");
    160   args.insert(args.begin(), B.CreateInBoundsGEP(fmt_gvar, vector<Value *>({B.getInt64(0), B.getInt64(0)})));
    161   args.insert(args.begin(), B.getInt64((uintptr_t)stderr));
    162   Function *fprintf_fn = mod->getFunction("fprintf");
    163   if (!fprintf_fn) {
    164     vector<Type *> fprintf_fn_args({B.getInt64Ty(), B.getInt8PtrTy()});
    165     FunctionType *fprintf_fn_type = FunctionType::get(B.getInt32Ty(), fprintf_fn_args, /*isvarArg=*/true);
    166     fprintf_fn = Function::Create(fprintf_fn_type, GlobalValue::ExternalLinkage, "fprintf", mod);
    167     fprintf_fn->setCallingConv(CallingConv::C);
    168     fprintf_fn->addFnAttr(Attribute::NoUnwind);
    169   }
    170   B.CreateCall(fprintf_fn, args);
    171 }
    172 
    173 static void finish_sscanf(IRBuilder<> &B, vector<Value *> *args, string *fmt,
    174                           const map<string, Value *> &locals, bool exact_args) {
    175   // fmt += "%n";
    176   // int nread = 0;
    177   // int n = sscanf(s, fmt, args..., &nread);
    178   // if (n < 0) return -1;
    179   // s = &s[nread];
    180   Value *sptr = locals.at("sptr");
    181   Value *nread = locals.at("nread");
    182   Function *cur_fn = B.GetInsertBlock()->getParent();
    183   Function *sscanf_fn = B.GetInsertBlock()->getModule()->getFunction("sscanf");
    184   *fmt += "%n";
    185   B.CreateStore(B.getInt32(0), nread);
    186   GlobalVariable *fmt_gvar = B.CreateGlobalString(*fmt, "fmt");
    187   (*args)[1] = B.CreateInBoundsGEP(fmt_gvar, {B.getInt64(0), B.getInt64(0)});
    188   (*args)[0] = B.CreateLoad(sptr);
    189   args->push_back(nread);
    190   CallInst *call = B.CreateCall(sscanf_fn, *args);
    191   call->setTailCall(true);
    192 
    193   BasicBlock *label_true = BasicBlock::Create(B.getContext(), "", cur_fn);
    194   BasicBlock *label_false = BasicBlock::Create(B.getContext(), "", cur_fn);
    195 
    196   // exact_args means fail if don't consume exact number of "%" inputs
    197   // exact_args is disabled for string parsing (empty case)
    198   Value *cond = exact_args ? B.CreateICmpNE(call, B.getInt32(args->size() - 3))
    199                            : B.CreateICmpSLT(call, B.getInt32(0));
    200   B.CreateCondBr(cond, label_true, label_false);
    201 
    202   B.SetInsertPoint(label_true);
    203   B.CreateRet(B.getInt32(-1));
    204 
    205   B.SetInsertPoint(label_false);
    206   // s = &s[nread];
    207   B.CreateStore(
    208       B.CreateInBoundsGEP(B.CreateLoad(sptr), B.CreateLoad(nread, true)), sptr);
    209 
    210   args->resize(2);
    211   fmt->clear();
    212 }
    213 
    214 // recursive helper to capture the arguments
    215 static void parse_type(IRBuilder<> &B, vector<Value *> *args, string *fmt,
    216                        Type *type, Value *out,
    217                        const map<string, Value *> &locals, bool is_writer) {
    218   if (StructType *st = dyn_cast<StructType>(type)) {
    219     *fmt += "{ ";
    220     unsigned idx = 0;
    221     for (auto field : st->elements()) {
    222       parse_type(B, args, fmt, field, B.CreateStructGEP(type, out, idx++),
    223                  locals, is_writer);
    224       *fmt += " ";
    225     }
    226     *fmt += "}";
    227   } else if (ArrayType *at = dyn_cast<ArrayType>(type)) {
    228     if (at->getElementType() == B.getInt8Ty()) {
    229       // treat i8[] as a char string instead of as an array of u8's
    230       if (is_writer) {
    231         *fmt += "\"%s\"";
    232         args->push_back(out);
    233       } else {
    234         // When reading strings, scanf doesn't support empty "", so we need to
    235         // break this up into multiple scanf calls. To understand it, let's take
    236         // an example:
    237         // struct Event {
    238         //   u32 a;
    239         //   struct {
    240         //     char x[64];
    241         //     int y;
    242         //   } b[2];
    243         //   u32 c;
    244         // };
    245         // The writer string would look like:
    246         //  "{ 0x%x [ { \"%s\" 0x%x } { \"%s\" 0x%x } ] 0x%x }"
    247         // But the reader string needs to restart at each \"\".
    248         //  reader0(const char *s, struct Event *val) {
    249         //    int nread, rc;
    250         //    nread = 0;
    251         //    rc = sscanf(s, "{ %i [ { \"%n", &val->a, &nread);
    252         //    if (rc != 1) return -1;
    253         //    s += nread; nread = 0;
    254         //    rc = sscanf(s, "%[^\"]%n", &val->b[0].x, &nread);
    255         //    if (rc < 0) return -1;
    256         //    s += nread; nread = 0;
    257         //    rc = sscanf(s, "\" %i } { \"%n", &val->b[0].y, &nread);
    258         //    if (rc != 1) return -1;
    259         //    s += nread; nread = 0;
    260         //    rc = sscanf(s, "%[^\"]%n", &val->b[1].x, &nread);
    261         //    if (rc < 0) return -1;
    262         //    s += nread; nread = 0;
    263         //    rc = sscanf(s, "\" %i } ] %i }%n", &val->b[1].y, &val->c, &nread);
    264         //    if (rc != 2) return -1;
    265         //    s += nread; nread = 0;
    266         //    return 0;
    267         //  }
    268         *fmt += "\"";
    269         finish_sscanf(B, args, fmt, locals, true);
    270 
    271         *fmt = "%[^\"]";
    272         args->push_back(out);
    273         finish_sscanf(B, args, fmt, locals, false);
    274 
    275         *fmt = "\"";
    276       }
    277     } else {
    278       *fmt += "[ ";
    279       for (size_t i = 0; i < at->getNumElements(); ++i) {
    280         parse_type(B, args, fmt, at->getElementType(),
    281                    B.CreateStructGEP(type, out, i), locals, is_writer);
    282         *fmt += " ";
    283       }
    284       *fmt += "]";
    285     }
    286   } else if (isa<PointerType>(type)) {
    287     *fmt += "0xl";
    288     if (is_writer)
    289       *fmt += "x";
    290     else
    291       *fmt += "i";
    292   } else if (IntegerType *it = dyn_cast<IntegerType>(type)) {
    293     if (is_writer)
    294       *fmt += "0x";
    295     if (it->getBitWidth() <= 8)
    296       *fmt += "%hh";
    297     else if (it->getBitWidth() <= 16)
    298       *fmt += "%h";
    299     else if (it->getBitWidth() <= 32)
    300       *fmt += "%";
    301     else
    302       *fmt += "%l";
    303     if (is_writer)
    304       *fmt += "x";
    305     else
    306       *fmt += "i";
    307     args->push_back(is_writer ? B.CreateLoad(out) : out);
    308   }
    309 }
    310 
    311 // make_reader generates a dynamic function in the instruction set of the host
    312 // (not bpf) that is able to convert c-strings in the pretty-print format of
    313 // make_writer back into binary representations. The encoding of the string
    314 // takes the llvm ir structure format, which closely maps the c structure but
    315 // not exactly (no support for unions for instance).
    316 // The general algorithm is:
    317 //  pod types (u8..u64)                <= %i
    318 //  array types
    319 //   u8[]  no nested quotes :(         <= "..."
    320 //   !u8[]                             <= [ %i %i ... ]
    321 //  struct types
    322 //   struct { u8 a; u64 b; }           <= { %i %i }
    323 //  nesting is supported
    324 //   struct { struct { u8 a[]; }; }    <= { "" }
    325 //   struct { struct { u64 a[]; }; }   <= { [ %i %i .. ] }
    326 string BPFModule::make_reader(Module *mod, Type *type) {
    327   auto fn_it = readers_.find(type);
    328   if (fn_it != readers_.end())
    329     return fn_it->second;
    330 
    331   // int read(const char *in, Type *out) {
    332   //   int n = sscanf(in, "{ %i ... }", &out->field1, ...);
    333   //   if (n != num_fields) return -1;
    334   //   return 0;
    335   // }
    336 
    337   IRBuilder<> B(*ctx_);
    338 
    339   FunctionType *sscanf_fn_type = FunctionType::get(
    340       B.getInt32Ty(), {B.getInt8PtrTy(), B.getInt8PtrTy()}, /*isVarArg=*/true);
    341   Function *sscanf_fn = mod->getFunction("sscanf");
    342   if (!sscanf_fn) {
    343     sscanf_fn = Function::Create(sscanf_fn_type, GlobalValue::ExternalLinkage,
    344                                  "sscanf", mod);
    345     sscanf_fn->setCallingConv(CallingConv::C);
    346     sscanf_fn->addFnAttr(Attribute::NoUnwind);
    347   }
    348 
    349   string name = "reader" + std::to_string(readers_.size());
    350   vector<Type *> fn_args({B.getInt8PtrTy(), PointerType::getUnqual(type)});
    351   FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false);
    352   Function *fn =
    353       Function::Create(fn_type, GlobalValue::ExternalLinkage, name, mod);
    354   auto arg_it = fn->arg_begin();
    355   Argument *arg_in = &*arg_it;
    356   ++arg_it;
    357   arg_in->setName("in");
    358   Argument *arg_out = &*arg_it;
    359   ++arg_it;
    360   arg_out->setName("out");
    361 
    362   BasicBlock *label_entry = BasicBlock::Create(*ctx_, "entry", fn);
    363   B.SetInsertPoint(label_entry);
    364 
    365   Value *nread = B.CreateAlloca(B.getInt32Ty());
    366   Value *sptr = B.CreateAlloca(B.getInt8PtrTy());
    367   map<string, Value *> locals{{"nread", nread}, {"sptr", sptr}};
    368   B.CreateStore(arg_in, sptr);
    369   vector<Value *> args({nullptr, nullptr});
    370   string fmt;
    371   parse_type(B, &args, &fmt, type, arg_out, locals, false);
    372 
    373   if (0)
    374     debug_printf(mod, B, "%p %p\n", vector<Value *>({arg_in, arg_out}));
    375 
    376   finish_sscanf(B, &args, &fmt, locals, true);
    377 
    378   B.CreateRet(B.getInt32(0));
    379 
    380   readers_[type] = name;
    381   return name;
    382 }
    383 
    384 // make_writer generates a dynamic function in the instruction set of the host
    385 // (not bpf) that is able to pretty-print key/leaf entries as a c-string. The
    386 // encoding of the string takes the llvm ir structure format, which closely maps
    387 // the c structure but not exactly (no support for unions for instance).
    388 // The general algorithm is:
    389 //  pod types (u8..u64)                => 0x%x
    390 //  array types
    391 //   u8[]                              => "..."
    392 //   !u8[]                             => [ 0x%x 0x%x ... ]
    393 //  struct types
    394 //   struct { u8 a; u64 b; }           => { 0x%x 0x%x }
    395 //  nesting is supported
    396 //   struct { struct { u8 a[]; }; }    => { "" }
    397 //   struct { struct { u64 a[]; }; }   => { [ 0x%x 0x%x .. ] }
    398 string BPFModule::make_writer(Module *mod, Type *type) {
    399   auto fn_it = writers_.find(type);
    400   if (fn_it != writers_.end())
    401     return fn_it->second;
    402 
    403   // int write(int len, char *out, Type *in) {
    404   //   return snprintf(out, len, "{ %i ... }", out->field1, ...);
    405   // }
    406 
    407   IRBuilder<> B(*ctx_);
    408 
    409   string name = "writer" + std::to_string(writers_.size());
    410   vector<Type *> fn_args({B.getInt8PtrTy(), B.getInt64Ty(), PointerType::getUnqual(type)});
    411   FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false);
    412   Function *fn =
    413       Function::Create(fn_type, GlobalValue::ExternalLinkage, name, mod);
    414   auto arg_it = fn->arg_begin();
    415   Argument *arg_out = &*arg_it;
    416   ++arg_it;
    417   arg_out->setName("out");
    418   Argument *arg_len = &*arg_it;
    419   ++arg_it;
    420   arg_len->setName("len");
    421   Argument *arg_in = &*arg_it;
    422   ++arg_it;
    423   arg_in->setName("in");
    424 
    425   BasicBlock *label_entry = BasicBlock::Create(*ctx_, "entry", fn);
    426   B.SetInsertPoint(label_entry);
    427 
    428   map<string, Value *> locals{
    429       {"nread", B.CreateAlloca(B.getInt64Ty())},
    430   };
    431   vector<Value *> args({arg_out, B.CreateZExt(arg_len, B.getInt64Ty()), nullptr});
    432   string fmt;
    433   parse_type(B, &args, &fmt, type, arg_in, locals, true);
    434 
    435   GlobalVariable *fmt_gvar = B.CreateGlobalString(fmt, "fmt");
    436 
    437   args[2] = B.CreateInBoundsGEP(fmt_gvar, vector<Value *>({B.getInt64(0), B.getInt64(0)}));
    438 
    439   if (0)
    440     debug_printf(mod, B, "%d %p %p\n", vector<Value *>({arg_len, arg_out, arg_in}));
    441 
    442   vector<Type *> snprintf_fn_args({B.getInt8PtrTy(), B.getInt64Ty(), B.getInt8PtrTy()});
    443   FunctionType *snprintf_fn_type = FunctionType::get(B.getInt32Ty(), snprintf_fn_args, /*isVarArg=*/true);
    444   Function *snprintf_fn = mod->getFunction("snprintf");
    445   if (!snprintf_fn)
    446     snprintf_fn = Function::Create(snprintf_fn_type, GlobalValue::ExternalLinkage, "snprintf", mod);
    447   snprintf_fn->setCallingConv(CallingConv::C);
    448   snprintf_fn->addFnAttr(Attribute::NoUnwind);
    449 
    450   CallInst *call = B.CreateCall(snprintf_fn, args);
    451   call->setTailCall(true);
    452 
    453   B.CreateRet(call);
    454 
    455   writers_[type] = name;
    456   return name;
    457 }
    458 
    459 unique_ptr<ExecutionEngine> BPFModule::finalize_rw(unique_ptr<Module> m) {
    460   Module *mod = &*m;
    461 
    462   run_pass_manager(*mod);
    463 
    464   string err;
    465   EngineBuilder builder(move(m));
    466   builder.setErrorStr(&err);
    467   builder.setUseOrcMCJITReplacement(false);
    468   auto engine = unique_ptr<ExecutionEngine>(builder.create());
    469   if (!engine)
    470     fprintf(stderr, "Could not create ExecutionEngine: %s\n", err.c_str());
    471   return engine;
    472 }
    473 
    474 // load an entire c file as a module
    475 int BPFModule::load_cfile(const string &file, bool in_memory, const char *cflags[], int ncflags) {
    476   ClangLoader clang_loader(&*ctx_, flags_);
    477   if (clang_loader.parse(&mod_, *ts_, file, in_memory, cflags, ncflags, id_,
    478                          *func_src_, mod_src_, maps_ns_))
    479     return -1;
    480   return 0;
    481 }
    482 
    483 // NOTE: this is a duplicate of the above, but planning to deprecate if we
    484 // settle on clang as the frontend
    485 
    486 // Load in a pre-built list of functions into the initial Module object, then
    487 // build an ExecutionEngine.
    488 int BPFModule::load_includes(const string &text) {
    489   ClangLoader clang_loader(&*ctx_, flags_);
    490   if (clang_loader.parse(&mod_, *ts_, text, true, nullptr, 0, "", *func_src_,
    491                          mod_src_, ""))
    492     return -1;
    493   return 0;
    494 }
    495 
    496 void BPFModule::annotate_light() {
    497   for (auto fn = mod_->getFunctionList().begin(); fn != mod_->getFunctionList().end(); ++fn)
    498     if (!fn->hasFnAttribute(Attribute::NoInline))
    499       fn->addFnAttr(Attribute::AlwaysInline);
    500 
    501   size_t id = 0;
    502   Path path({id_});
    503   for (auto it = ts_->lower_bound(path), up = ts_->upper_bound(path); it != up; ++it) {
    504     TableDesc &table = it->second;
    505     tables_.push_back(&it->second);
    506     table_names_[table.name] = id++;
    507   }
    508 }
    509 
    510 int BPFModule::annotate() {
    511   for (auto fn = mod_->getFunctionList().begin(); fn != mod_->getFunctionList().end(); ++fn)
    512     if (!fn->hasFnAttribute(Attribute::NoInline))
    513       fn->addFnAttr(Attribute::AlwaysInline);
    514 
    515   // separate module to hold the reader functions
    516   auto m = ebpf::make_unique<Module>("sscanf", *ctx_);
    517 
    518   size_t id = 0;
    519   Path path({id_});
    520   for (auto it = ts_->lower_bound(path), up = ts_->upper_bound(path); it != up; ++it) {
    521     TableDesc &table = it->second;
    522     tables_.push_back(&it->second);
    523     table_names_[table.name] = id++;
    524     GlobalValue *gvar = mod_->getNamedValue(table.name);
    525     if (!gvar) continue;
    526     if (PointerType *pt = dyn_cast<PointerType>(gvar->getType())) {
    527       if (StructType *st = dyn_cast<StructType>(pt->getElementType())) {
    528         if (st->getNumElements() < 2) continue;
    529         Type *key_type = st->elements()[0];
    530         Type *leaf_type = st->elements()[1];
    531 
    532         using std::placeholders::_1;
    533         using std::placeholders::_2;
    534         using std::placeholders::_3;
    535         table.key_sscanf = std::bind(&BPFModule::sscanf, this,
    536                                      make_reader(&*m, key_type), _1, _2);
    537         table.leaf_sscanf = std::bind(&BPFModule::sscanf, this,
    538                                       make_reader(&*m, leaf_type), _1, _2);
    539         table.key_snprintf = std::bind(&BPFModule::snprintf, this,
    540                                        make_writer(&*m, key_type), _1, _2, _3);
    541         table.leaf_snprintf =
    542             std::bind(&BPFModule::snprintf, this, make_writer(&*m, leaf_type),
    543                       _1, _2, _3);
    544       }
    545     }
    546   }
    547 
    548   rw_engine_ = finalize_rw(move(m));
    549   if (!rw_engine_)
    550     return -1;
    551   return 0;
    552 }
    553 
    554 StatusTuple BPFModule::sscanf(string fn_name, const char *str, void *val) {
    555   if (!rw_engine_enabled_)
    556     return StatusTuple(-1, "rw_engine not enabled");
    557   auto fn =
    558       (int (*)(const char *, void *))rw_engine_->getFunctionAddress(fn_name);
    559   if (!fn)
    560     return StatusTuple(-1, "sscanf not available");
    561   int rc = fn(str, val);
    562   if (rc < 0)
    563     return StatusTuple(rc, "error in sscanf: %s", std::strerror(errno));
    564   return StatusTuple(rc);
    565 }
    566 
    567 StatusTuple BPFModule::snprintf(string fn_name, char *str, size_t sz,
    568                                 const void *val) {
    569   if (!rw_engine_enabled_)
    570     return StatusTuple(-1, "rw_engine not enabled");
    571   auto fn = (int (*)(char *, size_t,
    572                      const void *))rw_engine_->getFunctionAddress(fn_name);
    573   if (!fn)
    574     return StatusTuple(-1, "snprintf not available");
    575   int rc = fn(str, sz, val);
    576   if (rc < 0)
    577     return StatusTuple(rc, "error in snprintf: %s", std::strerror(errno));
    578   if ((size_t)rc == sz)
    579     return StatusTuple(-1, "buffer of size %zd too small", sz);
    580   return StatusTuple(0);
    581 }
    582 
    583 void BPFModule::dump_ir(Module &mod) {
    584   legacy::PassManager PM;
    585   PM.add(createPrintModulePass(errs()));
    586   PM.run(mod);
    587 }
    588 
    589 int BPFModule::run_pass_manager(Module &mod) {
    590   if (verifyModule(mod, &errs())) {
    591     if (flags_ & DEBUG_LLVM_IR)
    592       dump_ir(mod);
    593     return -1;
    594   }
    595 
    596   legacy::PassManager PM;
    597   PassManagerBuilder PMB;
    598   PMB.OptLevel = 3;
    599   PM.add(createFunctionInliningPass());
    600   /*
    601    * llvm < 4.0 needs
    602    * PM.add(createAlwaysInlinerPass());
    603    * llvm >= 4.0 needs
    604    * PM.add(createAlwaysInlinerLegacyPass());
    605    * use below 'stable' workaround
    606    */
    607   LLVMAddAlwaysInlinerPass(reinterpret_cast<LLVMPassManagerRef>(&PM));
    608   PMB.populateModulePassManager(PM);
    609   if (flags_ & DEBUG_LLVM_IR)
    610     PM.add(createPrintModulePass(outs()));
    611   PM.run(mod);
    612   return 0;
    613 }
    614 
    615 int BPFModule::finalize() {
    616   Module *mod = &*mod_;
    617   std::map<std::string, std::tuple<uint8_t *, uintptr_t>> tmp_sections,
    618       *sections_p;
    619 
    620   mod->setTargetTriple("bpf-pc-linux");
    621   sections_p = rw_engine_enabled_ ? &sections_ : &tmp_sections;
    622 
    623   string err;
    624   EngineBuilder builder(move(mod_));
    625   builder.setErrorStr(&err);
    626   builder.setMCJITMemoryManager(ebpf::make_unique<MyMemoryManager>(sections_p));
    627   builder.setMArch("bpf");
    628   builder.setUseOrcMCJITReplacement(false);
    629   engine_ = unique_ptr<ExecutionEngine>(builder.create());
    630   if (!engine_) {
    631     fprintf(stderr, "Could not create ExecutionEngine: %s\n", err.c_str());
    632     return -1;
    633   }
    634 
    635   if (flags_ & DEBUG_SOURCE)
    636     engine_->setProcessAllSections(true);
    637 
    638   if (int rc = run_pass_manager(*mod))
    639     return rc;
    640 
    641   engine_->finalizeObject();
    642 
    643   if (flags_ & DEBUG_SOURCE) {
    644     SourceDebugger src_debugger(mod, *sections_p, FN_PREFIX, mod_src_,
    645                                 src_dbg_fmap_);
    646     src_debugger.dump();
    647   }
    648 
    649   if (!rw_engine_enabled_) {
    650     // Setup sections_ correctly and then free llvm internal memory
    651     for (auto section : tmp_sections) {
    652       auto fname = section.first;
    653       uintptr_t size = get<1>(section.second);
    654       uint8_t *tmp_p = NULL;
    655       // Only copy data for non-map sections
    656       if (strncmp("maps/", section.first.c_str(), 5)) {
    657         uint8_t *addr = get<0>(section.second);
    658         tmp_p = new uint8_t[size];
    659         memcpy(tmp_p, addr, size);
    660       }
    661       sections_[fname] = make_tuple(tmp_p, size);
    662     }
    663     engine_.reset();
    664     ctx_.reset();
    665   }
    666 
    667   // give functions an id
    668   for (auto section : sections_)
    669     if (!strncmp(FN_PREFIX.c_str(), section.first.c_str(), FN_PREFIX.size()))
    670       function_names_.push_back(section.first);
    671 
    672   return 0;
    673 }
    674 
    675 size_t BPFModule::num_functions() const {
    676   return function_names_.size();
    677 }
    678 
    679 const char * BPFModule::function_name(size_t id) const {
    680   if (id >= function_names_.size())
    681     return nullptr;
    682   return function_names_[id].c_str() + FN_PREFIX.size();
    683 }
    684 
    685 uint8_t * BPFModule::function_start(size_t id) const {
    686   if (id >= function_names_.size())
    687     return nullptr;
    688   auto section = sections_.find(function_names_[id]);
    689   if (section == sections_.end())
    690     return nullptr;
    691   return get<0>(section->second);
    692 }
    693 
    694 uint8_t * BPFModule::function_start(const string &name) const {
    695   auto section = sections_.find(FN_PREFIX + name);
    696   if (section == sections_.end())
    697     return nullptr;
    698 
    699   return get<0>(section->second);
    700 }
    701 
    702 const char * BPFModule::function_source(const string &name) const {
    703   return func_src_->src(name);
    704 }
    705 
    706 const char * BPFModule::function_source_rewritten(const string &name) const {
    707   return func_src_->src_rewritten(name);
    708 }
    709 
    710 int BPFModule::annotate_prog_tag(const string &name, int prog_fd,
    711                                  struct bpf_insn *insns, int prog_len) {
    712   unsigned long long tag1, tag2;
    713   int err;
    714 
    715   err = bpf_prog_compute_tag(insns, prog_len, &tag1);
    716   if (err)
    717     return err;
    718   err = bpf_prog_get_tag(prog_fd, &tag2);
    719   if (err)
    720     return err;
    721   if (tag1 != tag2) {
    722     fprintf(stderr, "prog tag mismatch %llx %llx\n", tag1, tag2);
    723     return -1;
    724   }
    725 
    726   err = mkdir(BCC_PROG_TAG_DIR, 0777);
    727   if (err && errno != EEXIST) {
    728     fprintf(stderr, "cannot create " BCC_PROG_TAG_DIR "\n");
    729     return -1;
    730   }
    731 
    732   char buf[128];
    733   ::snprintf(buf, sizeof(buf), BCC_PROG_TAG_DIR "/bpf_prog_%llx", tag1);
    734   err = mkdir(buf, 0777);
    735   if (err && errno != EEXIST) {
    736     fprintf(stderr, "cannot create %s\n", buf);
    737     return -1;
    738   }
    739 
    740   ::snprintf(buf, sizeof(buf), BCC_PROG_TAG_DIR "/bpf_prog_%llx/%s.c",
    741              tag1, name.data());
    742   FileDesc fd(open(buf, O_CREAT | O_WRONLY | O_TRUNC, 0644));
    743   if (fd < 0) {
    744     fprintf(stderr, "cannot create %s\n", buf);
    745     return -1;
    746   }
    747 
    748   const char *src = function_source(name);
    749   write(fd, src, strlen(src));
    750 
    751   ::snprintf(buf, sizeof(buf), BCC_PROG_TAG_DIR "/bpf_prog_%llx/%s.rewritten.c",
    752              tag1, name.data());
    753   fd = open(buf, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    754   if (fd < 0) {
    755     fprintf(stderr, "cannot create %s\n", buf);
    756     return -1;
    757   }
    758 
    759   src = function_source_rewritten(name);
    760   write(fd, src, strlen(src));
    761 
    762   if (!src_dbg_fmap_[name].empty()) {
    763     ::snprintf(buf, sizeof(buf), BCC_PROG_TAG_DIR "/bpf_prog_%llx/%s.dis.txt",
    764                tag1, name.data());
    765     fd = open(buf, O_CREAT | O_WRONLY | O_TRUNC, 0644);
    766     if (fd < 0) {
    767       fprintf(stderr, "cannot create %s\n", buf);
    768       return -1;
    769     }
    770 
    771     const char *src = src_dbg_fmap_[name].c_str();
    772     write(fd, src, strlen(src));
    773   }
    774 
    775   return 0;
    776 }
    777 
    778 size_t BPFModule::function_size(size_t id) const {
    779   if (id >= function_names_.size())
    780     return 0;
    781   auto section = sections_.find(function_names_[id]);
    782   if (section == sections_.end())
    783     return 0;
    784   return get<1>(section->second);
    785 }
    786 
    787 size_t BPFModule::function_size(const string &name) const {
    788   auto section = sections_.find(FN_PREFIX + name);
    789   if (section == sections_.end())
    790     return 0;
    791 
    792   return get<1>(section->second);
    793 }
    794 
    795 char * BPFModule::license() const {
    796   auto section = sections_.find("license");
    797   if (section == sections_.end())
    798     return nullptr;
    799 
    800   return (char *)get<0>(section->second);
    801 }
    802 
    803 unsigned BPFModule::kern_version() const {
    804   auto section = sections_.find("version");
    805   if (section == sections_.end())
    806     return 0;
    807 
    808   return *(unsigned *)get<0>(section->second);
    809 }
    810 
    811 size_t BPFModule::num_tables() const { return tables_.size(); }
    812 
    813 size_t BPFModule::table_id(const string &name) const {
    814   auto it = table_names_.find(name);
    815   if (it == table_names_.end()) return ~0ull;
    816   return it->second;
    817 }
    818 
    819 int BPFModule::table_fd(const string &name) const {
    820   return table_fd(table_id(name));
    821 }
    822 
    823 int BPFModule::table_fd(size_t id) const {
    824   if (id >= tables_.size())
    825     return -1;
    826   return tables_[id]->fd;
    827 }
    828 
    829 int BPFModule::table_type(const string &name) const {
    830   return table_type(table_id(name));
    831 }
    832 
    833 int BPFModule::table_type(size_t id) const {
    834   if (id >= tables_.size())
    835     return -1;
    836   return tables_[id]->type;
    837 }
    838 
    839 size_t BPFModule::table_max_entries(const string &name) const {
    840   return table_max_entries(table_id(name));
    841 }
    842 
    843 size_t BPFModule::table_max_entries(size_t id) const {
    844   if (id >= tables_.size())
    845     return 0;
    846   return tables_[id]->max_entries;
    847 }
    848 
    849 int BPFModule::table_flags(const string &name) const {
    850   return table_flags(table_id(name));
    851 }
    852 
    853 int BPFModule::table_flags(size_t id) const {
    854   if (id >= tables_.size())
    855     return -1;
    856   return tables_[id]->flags;
    857 }
    858 
    859 const char * BPFModule::table_name(size_t id) const {
    860   if (id >= tables_.size())
    861     return nullptr;
    862   return tables_[id]->name.c_str();
    863 }
    864 
    865 const char * BPFModule::table_key_desc(size_t id) const {
    866   if (used_b_loader_) return nullptr;
    867   if (id >= tables_.size())
    868     return nullptr;
    869   return tables_[id]->key_desc.c_str();
    870 }
    871 
    872 const char * BPFModule::table_key_desc(const string &name) const {
    873   return table_key_desc(table_id(name));
    874 }
    875 
    876 const char * BPFModule::table_leaf_desc(size_t id) const {
    877   if (used_b_loader_) return nullptr;
    878   if (id >= tables_.size())
    879     return nullptr;
    880   return tables_[id]->leaf_desc.c_str();
    881 }
    882 
    883 const char * BPFModule::table_leaf_desc(const string &name) const {
    884   return table_leaf_desc(table_id(name));
    885 }
    886 size_t BPFModule::table_key_size(size_t id) const {
    887   if (id >= tables_.size())
    888     return 0;
    889   return tables_[id]->key_size;
    890 }
    891 size_t BPFModule::table_key_size(const string &name) const {
    892   return table_key_size(table_id(name));
    893 }
    894 
    895 size_t BPFModule::table_leaf_size(size_t id) const {
    896   if (id >= tables_.size())
    897     return 0;
    898   return tables_[id]->leaf_size;
    899 }
    900 size_t BPFModule::table_leaf_size(const string &name) const {
    901   return table_leaf_size(table_id(name));
    902 }
    903 
    904 struct TableIterator {
    905   TableIterator(size_t key_size, size_t leaf_size)
    906       : key(new uint8_t[key_size]), leaf(new uint8_t[leaf_size]) {
    907   }
    908   unique_ptr<uint8_t[]> key;
    909   unique_ptr<uint8_t[]> leaf;
    910   uint8_t keyb[512];
    911 };
    912 
    913 int BPFModule::table_key_printf(size_t id, char *buf, size_t buflen, const void *key) {
    914   if (id >= tables_.size())
    915     return -1;
    916   const TableDesc &desc = *tables_[id];
    917   StatusTuple rc = desc.key_snprintf(buf, buflen, key);
    918   if (rc.code() < 0) {
    919     fprintf(stderr, "%s\n", rc.msg().c_str());
    920     return -1;
    921   }
    922   return 0;
    923 }
    924 
    925 int BPFModule::table_leaf_printf(size_t id, char *buf, size_t buflen, const void *leaf) {
    926   if (id >= tables_.size())
    927     return -1;
    928   const TableDesc &desc = *tables_[id];
    929   StatusTuple rc = desc.leaf_snprintf(buf, buflen, leaf);
    930   if (rc.code() < 0) {
    931     fprintf(stderr, "%s\n", rc.msg().c_str());
    932     return -1;
    933   }
    934   return 0;
    935 }
    936 
    937 int BPFModule::table_key_scanf(size_t id, const char *key_str, void *key) {
    938   if (id >= tables_.size())
    939     return -1;
    940   const TableDesc &desc = *tables_[id];
    941   StatusTuple rc = desc.key_sscanf(key_str, key);
    942   if (rc.code() < 0) {
    943     fprintf(stderr, "%s\n", rc.msg().c_str());
    944     return -1;
    945   }
    946   return 0;
    947 }
    948 
    949 int BPFModule::table_leaf_scanf(size_t id, const char *leaf_str, void *leaf) {
    950   if (id >= tables_.size())
    951     return -1;
    952   const TableDesc &desc = *tables_[id];
    953   StatusTuple rc = desc.leaf_sscanf(leaf_str, leaf);
    954   if (rc.code() < 0) {
    955     fprintf(stderr, "%s\n", rc.msg().c_str());
    956     return -1;
    957   }
    958   return 0;
    959 }
    960 
    961 // load a B file, which comes in two parts
    962 int BPFModule::load_b(const string &filename, const string &proto_filename) {
    963   if (!sections_.empty()) {
    964     fprintf(stderr, "Program already initialized\n");
    965     return -1;
    966   }
    967   if (filename.empty() || proto_filename.empty()) {
    968     fprintf(stderr, "Invalid filenames\n");
    969     return -1;
    970   }
    971 
    972   // Helpers are inlined in the following file (C). Load the definitions and
    973   // pass the partially compiled module to the B frontend to continue with.
    974   auto helpers_h = ExportedFiles::headers().find("/virtual/include/bcc/helpers.h");
    975   if (helpers_h == ExportedFiles::headers().end()) {
    976     fprintf(stderr, "Internal error: missing bcc/helpers.h");
    977     return -1;
    978   }
    979   if (int rc = load_includes(helpers_h->second))
    980     return rc;
    981 
    982   BLoader b_loader(flags_);
    983   used_b_loader_ = true;
    984   if (int rc = b_loader.parse(&*mod_, filename, proto_filename, *ts_, id_,
    985                               maps_ns_))
    986     return rc;
    987   if (rw_engine_enabled_) {
    988     if (int rc = annotate())
    989       return rc;
    990   } else {
    991     annotate_light();
    992   }
    993   if (int rc = finalize())
    994     return rc;
    995   return 0;
    996 }
    997 
    998 // load a C file
    999 int BPFModule::load_c(const string &filename, const char *cflags[], int ncflags) {
   1000   if (!sections_.empty()) {
   1001     fprintf(stderr, "Program already initialized\n");
   1002     return -1;
   1003   }
   1004   if (filename.empty()) {
   1005     fprintf(stderr, "Invalid filename\n");
   1006     return -1;
   1007   }
   1008   if (int rc = load_cfile(filename, false, cflags, ncflags))
   1009     return rc;
   1010   if (rw_engine_enabled_) {
   1011     if (int rc = annotate())
   1012       return rc;
   1013   } else {
   1014     annotate_light();
   1015   }
   1016   if (int rc = finalize())
   1017     return rc;
   1018   return 0;
   1019 }
   1020 
   1021 // load a C text string
   1022 int BPFModule::load_string(const string &text, const char *cflags[], int ncflags) {
   1023   if (!sections_.empty()) {
   1024     fprintf(stderr, "Program already initialized\n");
   1025     return -1;
   1026   }
   1027   if (int rc = load_cfile(text, true, cflags, ncflags))
   1028     return rc;
   1029   if (rw_engine_enabled_) {
   1030     if (int rc = annotate())
   1031       return rc;
   1032   } else {
   1033     annotate_light();
   1034   }
   1035 
   1036   if (int rc = finalize())
   1037     return rc;
   1038   return 0;
   1039 }
   1040 
   1041 } // namespace ebpf
   1042