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_ ? §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 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