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_ ? §ions_ : &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