Commit b493aa6c authored by 4ast's avatar 4ast Committed by GitHub

Merge pull request #1167 from iovisor/rw_finalize_defer

Use late-binding to finalize snprintf/sscanf
parents 4033200e dadea22d
...@@ -39,41 +39,27 @@ class BPFTableBase { ...@@ -39,41 +39,27 @@ class BPFTableBase {
size_t capacity() { return desc.max_entries; } size_t capacity() { return desc.max_entries; }
StatusTuple string_to_key(const std::string& key_str, KeyType* key) { StatusTuple string_to_key(const std::string& key_str, KeyType* key) {
if (!desc.key_sscanf) return desc.key_sscanf(key_str.c_str(), key);
return StatusTuple(-1, "Key sscanf not available");
if (desc.key_sscanf(key_str.c_str(), key) != 0)
return StatusTuple(-1, "Error on key_sscanff: %s", std::strerror(errno));
return StatusTuple(0);
} }
StatusTuple string_to_leaf(const std::string& value_str, ValueType* value) { StatusTuple string_to_leaf(const std::string& value_str, ValueType* value) {
if (!desc.leaf_sscanf) return desc.leaf_sscanf(value_str.c_str(), value);
return StatusTuple(-1, "Leaf sscanf not available");
if (desc.leaf_sscanf(value_str.c_str(), value) != 0)
return StatusTuple(-1, "Error on leaf_sscanff: %s", std::strerror(errno));
return StatusTuple(0);
} }
StatusTuple key_to_string(const KeyType* key, std::string& key_str) { StatusTuple key_to_string(const KeyType* key, std::string& key_str) {
char buf[8 * desc.key_size]; char buf[8 * desc.key_size];
if (!desc.key_snprintf) StatusTuple rc = desc.key_snprintf(buf, sizeof(buf), key);
return StatusTuple(-1, "Key snprintf not available"); if (!rc.code())
if (desc.key_snprintf(buf, sizeof(buf), key) < 0) key_str.assign(buf);
return StatusTuple(-1, "Error on key_sprintf: %s", std::strerror(errno)); return rc;
key_str.assign(buf);
return StatusTuple(0);
} }
StatusTuple leaf_to_string(const ValueType* value, std::string& value_str) { StatusTuple leaf_to_string(const ValueType* value, std::string& value_str) {
char buf[8 * desc.leaf_size]; char buf[8 * desc.leaf_size];
if (!desc.leaf_snprintf) StatusTuple rc = desc.leaf_snprintf(buf, sizeof(buf), value);
return StatusTuple(-1, "Leaf snprintf not available"); if (!rc.code())
if (desc.leaf_snprintf(buf, sizeof(buf), value) < 0) value_str.assign(buf);
return StatusTuple(-1, "Error on leaf_sprintf: %s", std::strerror(errno)); return rc;
value_str.assign(buf);
return StatusTuple(0);
} }
protected: protected:
......
...@@ -116,18 +116,25 @@ BPFModule::BPFModule(unsigned flags, TableStorage *ts) ...@@ -116,18 +116,25 @@ BPFModule::BPFModule(unsigned flags, TableStorage *ts)
} }
} }
static StatusTuple unimplemented_sscanf(const char *, void *) {
return StatusTuple(-1, "sscanf unimplemented");
}
static StatusTuple unimplemented_snprintf(char *, size_t, const void *) {
return StatusTuple(-1, "snprintf unimplemented");
}
BPFModule::~BPFModule() { BPFModule::~BPFModule() {
for (auto &v : tables_) {
v->key_sscanf = unimplemented_sscanf;
v->leaf_sscanf = unimplemented_sscanf;
v->key_snprintf = unimplemented_snprintf;
v->leaf_snprintf = unimplemented_snprintf;
}
engine_.reset(); engine_.reset();
rw_engine_.reset(); rw_engine_.reset();
ctx_.reset(); ctx_.reset();
for (auto &v : tables_) {
v->key_sscanf = nullptr;
v->leaf_sscanf = nullptr;
v->key_snprintf = nullptr;
v->leaf_snprintf = nullptr;
}
ts_->DeletePrefix(Path({id_})); ts_->DeletePrefix(Path({id_}));
} }
...@@ -189,7 +196,7 @@ static void parse_type(IRBuilder<> &B, vector<Value *> *args, string *fmt, ...@@ -189,7 +196,7 @@ static void parse_type(IRBuilder<> &B, vector<Value *> *args, string *fmt,
} }
} }
Function * BPFModule::make_reader(Module *mod, Type *type) { string BPFModule::make_reader(Module *mod, Type *type) {
auto fn_it = readers_.find(type); auto fn_it = readers_.find(type);
if (fn_it != readers_.end()) if (fn_it != readers_.end())
return fn_it->second; return fn_it->second;
...@@ -202,10 +209,11 @@ Function * BPFModule::make_reader(Module *mod, Type *type) { ...@@ -202,10 +209,11 @@ Function * BPFModule::make_reader(Module *mod, Type *type) {
IRBuilder<> B(*ctx_); IRBuilder<> B(*ctx_);
string name = "reader" + std::to_string(readers_.size());
vector<Type *> fn_args({B.getInt8PtrTy(), PointerType::getUnqual(type)}); vector<Type *> fn_args({B.getInt8PtrTy(), PointerType::getUnqual(type)});
FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false); FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false);
Function *fn = Function::Create(fn_type, GlobalValue::ExternalLinkage, Function *fn =
"reader" + std::to_string(readers_.size()), mod); Function::Create(fn_type, GlobalValue::ExternalLinkage, name, mod);
auto arg_it = fn->arg_begin(); auto arg_it = fn->arg_begin();
Argument *arg_in = &*arg_it; Argument *arg_in = &*arg_it;
++arg_it; ++arg_it;
...@@ -251,11 +259,11 @@ Function * BPFModule::make_reader(Module *mod, Type *type) { ...@@ -251,11 +259,11 @@ Function * BPFModule::make_reader(Module *mod, Type *type) {
B.SetInsertPoint(label_exit); B.SetInsertPoint(label_exit);
B.CreateRet(B.getInt32(0)); B.CreateRet(B.getInt32(0));
readers_[type] = fn; readers_[type] = name;
return fn; return name;
} }
Function * BPFModule::make_writer(Module *mod, Type *type) { string BPFModule::make_writer(Module *mod, Type *type) {
auto fn_it = writers_.find(type); auto fn_it = writers_.find(type);
if (fn_it != writers_.end()) if (fn_it != writers_.end())
return fn_it->second; return fn_it->second;
...@@ -266,10 +274,11 @@ Function * BPFModule::make_writer(Module *mod, Type *type) { ...@@ -266,10 +274,11 @@ Function * BPFModule::make_writer(Module *mod, Type *type) {
IRBuilder<> B(*ctx_); IRBuilder<> B(*ctx_);
string name = "writer" + std::to_string(writers_.size());
vector<Type *> fn_args({B.getInt8PtrTy(), B.getInt64Ty(), PointerType::getUnqual(type)}); vector<Type *> fn_args({B.getInt8PtrTy(), B.getInt64Ty(), PointerType::getUnqual(type)});
FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false); FunctionType *fn_type = FunctionType::get(B.getInt32Ty(), fn_args, /*isVarArg=*/false);
Function *fn = Function::Create(fn_type, GlobalValue::ExternalLinkage, Function *fn =
"writer" + std::to_string(writers_.size()), mod); Function::Create(fn_type, GlobalValue::ExternalLinkage, name, mod);
auto arg_it = fn->arg_begin(); auto arg_it = fn->arg_begin();
Argument *arg_out = &*arg_it; Argument *arg_out = &*arg_it;
++arg_it; ++arg_it;
...@@ -308,8 +317,8 @@ Function * BPFModule::make_writer(Module *mod, Type *type) { ...@@ -308,8 +317,8 @@ Function * BPFModule::make_writer(Module *mod, Type *type) {
B.CreateRet(call); B.CreateRet(call);
writers_[type] = fn; writers_[type] = name;
return fn; return name;
} }
unique_ptr<ExecutionEngine> BPFModule::finalize_rw(unique_ptr<Module> m) { unique_ptr<ExecutionEngine> BPFModule::finalize_rw(unique_ptr<Module> m) {
...@@ -355,15 +364,6 @@ int BPFModule::annotate() { ...@@ -355,15 +364,6 @@ int BPFModule::annotate() {
// separate module to hold the reader functions // separate module to hold the reader functions
auto m = ebpf::make_unique<Module>("sscanf", *ctx_); auto m = ebpf::make_unique<Module>("sscanf", *ctx_);
struct llvmfnpointers {
llvm::Function *key_sscanf;
llvm::Function *leaf_sscanf;
llvm::Function *key_snprintf;
llvm::Function *leaf_snprintf;
};
std::map<TableDesc *, llvmfnpointers> ptrs_map;
size_t id = 0; size_t id = 0;
Path path({id_}); Path path({id_});
for (auto it = ts_->lower_bound(path), up = ts_->upper_bound(path); it != up; ++it) { for (auto it = ts_->lower_bound(path), up = ts_->upper_bound(path); it != up; ++it) {
...@@ -378,48 +378,53 @@ int BPFModule::annotate() { ...@@ -378,48 +378,53 @@ int BPFModule::annotate() {
Type *key_type = st->elements()[0]; Type *key_type = st->elements()[0];
Type *leaf_type = st->elements()[1]; Type *leaf_type = st->elements()[1];
llvmfnpointers fns; using std::placeholders::_1;
using std::placeholders::_2;
fns.key_sscanf = make_reader(&*m, key_type); using std::placeholders::_3;
if (!fns.key_sscanf) table.key_sscanf = std::bind(&BPFModule::sscanf, this,
errs() << "Failed to compile sscanf for " << *key_type << "\n"; make_reader(&*m, key_type), _1, _2);
table.leaf_sscanf = std::bind(&BPFModule::sscanf, this,
fns.leaf_sscanf = make_reader(&*m, leaf_type); make_reader(&*m, leaf_type), _1, _2);
if (!fns.leaf_sscanf) table.key_snprintf = std::bind(&BPFModule::snprintf, this,
errs() << "Failed to compile sscanf for " << *leaf_type << "\n"; make_writer(&*m, key_type), _1, _2, _3);
table.leaf_snprintf =
fns.key_snprintf = make_writer(&*m, key_type); std::bind(&BPFModule::snprintf, this, make_writer(&*m, leaf_type),
if (!fns.key_snprintf) _1, _2, _3);
errs() << "Failed to compile snprintf for " << *key_type << "\n";
fns.leaf_snprintf = make_writer(&*m, leaf_type);
if (!fns.leaf_snprintf)
errs() << "Failed to compile snprintf for " << *leaf_type << "\n";
ptrs_map[&it->second] = fns;
} }
} }
} }
rw_engine_ = finalize_rw(move(m)); rw_engine_ = finalize_rw(move(m));
if (rw_engine_) if (!rw_engine_)
rw_engine_->finalizeObject(); return -1;
for (auto &it : ptrs_map) {
auto t = it.first;
auto ptr = it.second;
t->key_sscanf = (sscanf_fn)rw_engine_->getPointerToFunction(ptr.key_sscanf);
t->leaf_sscanf =
(sscanf_fn)rw_engine_->getPointerToFunction(ptr.leaf_sscanf);
t->key_snprintf =
(snprintf_fn)rw_engine_->getPointerToFunction(ptr.key_snprintf);
t->leaf_snprintf =
(snprintf_fn)rw_engine_->getPointerToFunction(ptr.leaf_snprintf);
}
return 0; return 0;
} }
StatusTuple BPFModule::sscanf(string fn_name, const char *str, void *val) {
auto fn =
(int (*)(const char *, void *))rw_engine_->getFunctionAddress(fn_name);
if (!fn)
return StatusTuple(-1, "sscanf not available");
int rc = fn(str, val);
if (rc < 0)
return StatusTuple(rc, "error in sscanf: %s", std::strerror(errno));
return StatusTuple(rc);
}
StatusTuple BPFModule::snprintf(string fn_name, char *str, size_t sz,
const void *val) {
auto fn = (int (*)(char *, size_t,
const void *))rw_engine_->getFunctionAddress(fn_name);
if (!fn)
return StatusTuple(-1, "snprintf not available");
int rc = fn(str, sz, val);
if (rc < 0)
return StatusTuple(rc, "error in snprintf: %s", std::strerror(errno));
if ((size_t)rc == sz)
return StatusTuple(-1, "buffer of size %zd too small", sz);
return StatusTuple(0);
}
void BPFModule::dump_ir(Module &mod) { void BPFModule::dump_ir(Module &mod) {
legacy::PassManager PM; legacy::PassManager PM;
PM.add(createPrintModulePass(errs())); PM.add(createPrintModulePass(errs()));
...@@ -649,17 +654,9 @@ int BPFModule::table_key_printf(size_t id, char *buf, size_t buflen, const void ...@@ -649,17 +654,9 @@ int BPFModule::table_key_printf(size_t id, char *buf, size_t buflen, const void
if (id >= tables_.size()) if (id >= tables_.size())
return -1; return -1;
const TableDesc &desc = *tables_[id]; const TableDesc &desc = *tables_[id];
if (!desc.key_snprintf) { StatusTuple rc = desc.key_snprintf(buf, buflen, key);
fprintf(stderr, "Key snprintf not available\n"); if (rc.code() < 0) {
return -1; fprintf(stderr, "%s\n", rc.msg().c_str());
}
int rc = desc.key_snprintf(buf, buflen, key);
if (rc < 0) {
perror("snprintf");
return -1;
}
if ((size_t)rc >= buflen) {
fprintf(stderr, "snprintf ran out of buffer space\n");
return -1; return -1;
} }
return 0; return 0;
...@@ -669,17 +666,9 @@ int BPFModule::table_leaf_printf(size_t id, char *buf, size_t buflen, const void ...@@ -669,17 +666,9 @@ int BPFModule::table_leaf_printf(size_t id, char *buf, size_t buflen, const void
if (id >= tables_.size()) if (id >= tables_.size())
return -1; return -1;
const TableDesc &desc = *tables_[id]; const TableDesc &desc = *tables_[id];
if (!desc.leaf_snprintf) { StatusTuple rc = desc.leaf_snprintf(buf, buflen, leaf);
fprintf(stderr, "Key snprintf not available\n"); if (rc.code() < 0) {
return -1; fprintf(stderr, "%s\n", rc.msg().c_str());
}
int rc = desc.leaf_snprintf(buf, buflen, leaf);
if (rc < 0) {
perror("snprintf");
return -1;
}
if ((size_t)rc >= buflen) {
fprintf(stderr, "snprintf ran out of buffer space\n");
return -1; return -1;
} }
return 0; return 0;
...@@ -689,13 +678,9 @@ int BPFModule::table_key_scanf(size_t id, const char *key_str, void *key) { ...@@ -689,13 +678,9 @@ int BPFModule::table_key_scanf(size_t id, const char *key_str, void *key) {
if (id >= tables_.size()) if (id >= tables_.size())
return -1; return -1;
const TableDesc &desc = *tables_[id]; const TableDesc &desc = *tables_[id];
if (!desc.key_sscanf) { StatusTuple rc = desc.key_sscanf(key_str, key);
fprintf(stderr, "Key sscanf not available\n"); if (rc.code() < 0) {
return -1; fprintf(stderr, "%s\n", rc.msg().c_str());
}
int rc = desc.key_sscanf(key_str, key);
if (rc != 0) {
perror("sscanf");
return -1; return -1;
} }
return 0; return 0;
...@@ -705,13 +690,9 @@ int BPFModule::table_leaf_scanf(size_t id, const char *leaf_str, void *leaf) { ...@@ -705,13 +690,9 @@ int BPFModule::table_leaf_scanf(size_t id, const char *leaf_str, void *leaf) {
if (id >= tables_.size()) if (id >= tables_.size())
return -1; return -1;
const TableDesc &desc = *tables_[id]; const TableDesc &desc = *tables_[id];
if (!desc.leaf_sscanf) { StatusTuple rc = desc.leaf_sscanf(leaf_str, leaf);
fprintf(stderr, "Key sscanf not available\n"); if (rc.code() < 0) {
return -1; fprintf(stderr, "%s\n", rc.msg().c_str());
}
int rc = desc.leaf_sscanf(leaf_str, leaf);
if (rc != 0) {
perror("sscanf");
return -1; return -1;
} }
return 0; return 0;
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "bcc_exception.h"
namespace llvm { namespace llvm {
class ExecutionEngine; class ExecutionEngine;
class Function; class Function;
...@@ -44,14 +46,18 @@ class BPFModule { ...@@ -44,14 +46,18 @@ class BPFModule {
int finalize(); int finalize();
int annotate(); int annotate();
std::unique_ptr<llvm::ExecutionEngine> finalize_rw(std::unique_ptr<llvm::Module> mod); std::unique_ptr<llvm::ExecutionEngine> finalize_rw(std::unique_ptr<llvm::Module> mod);
llvm::Function * make_reader(llvm::Module *mod, llvm::Type *type); std::string make_reader(llvm::Module *mod, llvm::Type *type);
llvm::Function * make_writer(llvm::Module *mod, llvm::Type *type); std::string make_writer(llvm::Module *mod, llvm::Type *type);
void dump_ir(llvm::Module &mod); void dump_ir(llvm::Module &mod);
int load_file_module(std::unique_ptr<llvm::Module> *mod, const std::string &file, bool in_memory); int load_file_module(std::unique_ptr<llvm::Module> *mod, const std::string &file, bool in_memory);
int load_includes(const std::string &text); int load_includes(const std::string &text);
int load_cfile(const std::string &file, bool in_memory, const char *cflags[], int ncflags); int load_cfile(const std::string &file, bool in_memory, const char *cflags[], int ncflags);
int kbuild_flags(const char *uname_release, std::vector<std::string> *cflags); int kbuild_flags(const char *uname_release, std::vector<std::string> *cflags);
int run_pass_manager(llvm::Module &mod); int run_pass_manager(llvm::Module &mod);
StatusTuple sscanf(std::string fn_name, const char *str, void *val);
StatusTuple snprintf(std::string fn_name, char *str, size_t sz,
const void *val);
public: public:
BPFModule(unsigned flags, TableStorage *ts = nullptr); BPFModule(unsigned flags, TableStorage *ts = nullptr);
~BPFModule(); ~BPFModule();
...@@ -106,8 +112,8 @@ class BPFModule { ...@@ -106,8 +112,8 @@ class BPFModule {
std::vector<TableDesc *> tables_; std::vector<TableDesc *> tables_;
std::map<std::string, size_t> table_names_; std::map<std::string, size_t> table_names_;
std::vector<std::string> function_names_; std::vector<std::string> function_names_;
std::map<llvm::Type *, llvm::Function *> readers_; std::map<llvm::Type *, std::string> readers_;
std::map<llvm::Type *, llvm::Function *> writers_; std::map<llvm::Type *, std::string> writers_;
std::string id_; std::string id_;
TableStorage *ts_; TableStorage *ts_;
std::unique_ptr<TableStorage> local_ts_; std::unique_ptr<TableStorage> local_ts_;
......
...@@ -18,15 +18,13 @@ ...@@ -18,15 +18,13 @@
#include <unistd.h> #include <unistd.h>
#include <cstdint> #include <cstdint>
#include <functional>
#include <memory> #include <memory>
#include <string> #include <string>
#include "bcc_exception.h"
#include "common.h" #include "common.h"
namespace llvm {
class Function;
}
namespace clang { namespace clang {
class ASTContext; class ASTContext;
class QualType; class QualType;
...@@ -34,8 +32,8 @@ class QualType; ...@@ -34,8 +32,8 @@ class QualType;
namespace ebpf { namespace ebpf {
typedef int (*sscanf_fn)(const char *, void *); typedef std::function<StatusTuple(const char *, void *)> sscanf_fn;
typedef int (*snprintf_fn)(char *, size_t, const void *); typedef std::function<StatusTuple(char *, size_t, const void *)> snprintf_fn;
/// TableDesc uniquely stores all of the runtime state for an active bpf table. /// TableDesc uniquely stores all of the runtime state for an active bpf table.
/// The copy constructor/assign operator are disabled since the file handles /// The copy constructor/assign operator are disabled since the file handles
...@@ -68,10 +66,6 @@ class TableDesc { ...@@ -68,10 +66,6 @@ class TableDesc {
leaf_size(0), leaf_size(0),
max_entries(0), max_entries(0),
flags(0), flags(0),
key_sscanf(nullptr),
leaf_sscanf(nullptr),
key_snprintf(nullptr),
leaf_snprintf(nullptr),
is_shared(false), is_shared(false),
is_extern(false) {} is_extern(false) {}
TableDesc(const std::string &name, FileDesc &&fd, int type, size_t key_size, TableDesc(const std::string &name, FileDesc &&fd, int type, size_t key_size,
...@@ -83,10 +77,6 @@ class TableDesc { ...@@ -83,10 +77,6 @@ class TableDesc {
leaf_size(leaf_size), leaf_size(leaf_size),
max_entries(max_entries), max_entries(max_entries),
flags(flags), flags(flags),
key_sscanf(nullptr),
leaf_sscanf(nullptr),
key_snprintf(nullptr),
leaf_snprintf(nullptr),
is_shared(false), is_shared(false),
is_extern(false) {} is_extern(false) {}
TableDesc(TableDesc &&that) = default; TableDesc(TableDesc &&that) = default;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment