• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MyMemoryManager(map<string,tuple<uint8_t *,uintptr_t>> * sections)76   explicit MyMemoryManager(map<string, tuple<uint8_t *, uintptr_t>> *sections)
77       : sections_(sections) {
78   }
79 
~MyMemoryManager()80   virtual ~MyMemoryManager() {}
allocateCodeSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName)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   }
allocateDataSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,StringRef SectionName,bool isReadOnly)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 
BPFModule(unsigned flags,TableStorage * ts,bool rw_engine_enabled,const std::string & maps_ns)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 
unimplemented_sscanf(const char *,void *)130 static StatusTuple unimplemented_sscanf(const char *, void *) {
131   return StatusTuple(-1, "sscanf unimplemented");
132 }
unimplemented_snprintf(char *,size_t,const void *)133 static StatusTuple unimplemented_snprintf(char *, size_t, const void *) {
134   return StatusTuple(-1, "snprintf unimplemented");
135 }
136 
~BPFModule()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 
debug_printf(Module * mod,IRBuilder<> & B,const string & fmt,vector<Value * > args)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 
finish_sscanf(IRBuilder<> & B,vector<Value * > * args,string * fmt,const map<string,Value * > & locals,bool exact_args)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
parse_type(IRBuilder<> & B,vector<Value * > * args,string * fmt,Type * type,Value * out,const map<string,Value * > & locals,bool is_writer)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 .. ] }
make_reader(Module * mod,Type * type)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 .. ] }
make_writer(Module * mod,Type * type)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 
finalize_rw(unique_ptr<Module> m)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
load_cfile(const string & file,bool in_memory,const char * cflags[],int ncflags)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.
load_includes(const string & text)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 
annotate_light()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 
annotate()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 
sscanf(string fn_name,const char * str,void * val)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 
snprintf(string fn_name,char * str,size_t sz,const void * val)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 
dump_ir(Module & mod)583 void BPFModule::dump_ir(Module &mod) {
584   legacy::PassManager PM;
585   PM.add(createPrintModulePass(errs()));
586   PM.run(mod);
587 }
588 
run_pass_manager(Module & mod)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 
finalize()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 
num_functions() const675 size_t BPFModule::num_functions() const {
676   return function_names_.size();
677 }
678 
function_name(size_t id) const679 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 
function_start(size_t id) const685 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 
function_start(const string & name) const694 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 
function_source(const string & name) const702 const char * BPFModule::function_source(const string &name) const {
703   return func_src_->src(name);
704 }
705 
function_source_rewritten(const string & name) const706 const char * BPFModule::function_source_rewritten(const string &name) const {
707   return func_src_->src_rewritten(name);
708 }
709 
annotate_prog_tag(const string & name,int prog_fd,struct bpf_insn * insns,int prog_len)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 
function_size(size_t id) const778 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 
function_size(const string & name) const787 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 
license() const795 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 
kern_version() const803 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 
num_tables() const811 size_t BPFModule::num_tables() const { return tables_.size(); }
812 
table_id(const string & name) const813 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 
table_fd(const string & name) const819 int BPFModule::table_fd(const string &name) const {
820   return table_fd(table_id(name));
821 }
822 
table_fd(size_t id) const823 int BPFModule::table_fd(size_t id) const {
824   if (id >= tables_.size())
825     return -1;
826   return tables_[id]->fd;
827 }
828 
table_type(const string & name) const829 int BPFModule::table_type(const string &name) const {
830   return table_type(table_id(name));
831 }
832 
table_type(size_t id) const833 int BPFModule::table_type(size_t id) const {
834   if (id >= tables_.size())
835     return -1;
836   return tables_[id]->type;
837 }
838 
table_max_entries(const string & name) const839 size_t BPFModule::table_max_entries(const string &name) const {
840   return table_max_entries(table_id(name));
841 }
842 
table_max_entries(size_t id) const843 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 
table_flags(const string & name) const849 int BPFModule::table_flags(const string &name) const {
850   return table_flags(table_id(name));
851 }
852 
table_flags(size_t id) const853 int BPFModule::table_flags(size_t id) const {
854   if (id >= tables_.size())
855     return -1;
856   return tables_[id]->flags;
857 }
858 
table_name(size_t id) const859 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 
table_key_desc(size_t id) const865 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 
table_key_desc(const string & name) const872 const char * BPFModule::table_key_desc(const string &name) const {
873   return table_key_desc(table_id(name));
874 }
875 
table_leaf_desc(size_t id) const876 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 
table_leaf_desc(const string & name) const883 const char * BPFModule::table_leaf_desc(const string &name) const {
884   return table_leaf_desc(table_id(name));
885 }
table_key_size(size_t id) const886 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 }
table_key_size(const string & name) const891 size_t BPFModule::table_key_size(const string &name) const {
892   return table_key_size(table_id(name));
893 }
894 
table_leaf_size(size_t id) const895 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 }
table_leaf_size(const string & name) const900 size_t BPFModule::table_leaf_size(const string &name) const {
901   return table_leaf_size(table_id(name));
902 }
903 
904 struct TableIterator {
TableIteratorebpf::TableIterator905   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 
table_key_printf(size_t id,char * buf,size_t buflen,const void * key)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 
table_leaf_printf(size_t id,char * buf,size_t buflen,const void * leaf)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 
table_key_scanf(size_t id,const char * key_str,void * key)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 
table_leaf_scanf(size_t id,const char * leaf_str,void * leaf)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
load_b(const string & filename,const string & proto_filename)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
load_c(const string & filename,const char * cflags[],int ncflags)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
load_string(const string & text,const char * cflags[],int ncflags)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