Commit 93588503 authored by Brenden Blanco's avatar Brenden Blanco

Add ability to set custom cflags when loading programs

Example:
b = bcc.BPF("myprog.c", cflags=["-DMYCUSTOMFLAG1", ...])
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent 43861954
...@@ -26,18 +26,18 @@ void * bpf_module_create_b(const char *filename, const char *proto_filename, uns ...@@ -26,18 +26,18 @@ void * bpf_module_create_b(const char *filename, const char *proto_filename, uns
return mod; return mod;
} }
void * bpf_module_create_c(const char *filename, unsigned flags) { void * bpf_module_create_c(const char *filename, unsigned flags, const char *cflags[], int ncflags) {
auto mod = new ebpf::BPFModule(flags); auto mod = new ebpf::BPFModule(flags);
if (mod->load_c(filename) != 0) { if (mod->load_c(filename, cflags, ncflags) != 0) {
delete mod; delete mod;
return nullptr; return nullptr;
} }
return mod; return mod;
} }
void * bpf_module_create_c_from_string(const char *text, unsigned flags) { void * bpf_module_create_c_from_string(const char *text, unsigned flags, const char *cflags[], int ncflags) {
auto mod = new ebpf::BPFModule(flags); auto mod = new ebpf::BPFModule(flags);
if (mod->load_string(text) != 0) { if (mod->load_string(text, cflags, ncflags) != 0) {
delete mod; delete mod;
return nullptr; return nullptr;
} }
......
...@@ -25,8 +25,8 @@ extern "C" { ...@@ -25,8 +25,8 @@ extern "C" {
#endif #endif
void * bpf_module_create_b(const char *filename, const char *proto_filename, unsigned flags); void * bpf_module_create_b(const char *filename, const char *proto_filename, unsigned flags);
void * bpf_module_create_c(const char *filename, unsigned flags); void * bpf_module_create_c(const char *filename, unsigned flags, const char *cflags[], int ncflags);
void * bpf_module_create_c_from_string(const char *text, unsigned flags); void * bpf_module_create_c_from_string(const char *text, unsigned flags, const char *cflags[], int ncflags);
void bpf_module_destroy(void *program); void bpf_module_destroy(void *program);
char * bpf_module_license(void *program); char * bpf_module_license(void *program);
unsigned bpf_module_kern_version(void *program); unsigned bpf_module_kern_version(void *program);
......
...@@ -299,9 +299,9 @@ unique_ptr<ExecutionEngine> BPFModule::finalize_rw(unique_ptr<Module> m) { ...@@ -299,9 +299,9 @@ unique_ptr<ExecutionEngine> BPFModule::finalize_rw(unique_ptr<Module> m) {
} }
// load an entire c file as a module // load an entire c file as a module
int BPFModule::load_cfile(const string &file, bool in_memory) { int BPFModule::load_cfile(const string &file, bool in_memory, const char *cflags[], int ncflags) {
clang_loader_ = make_unique<ClangLoader>(&*ctx_, flags_); clang_loader_ = make_unique<ClangLoader>(&*ctx_, flags_);
if (clang_loader_->parse(&mod_, &tables_, file, in_memory)) if (clang_loader_->parse(&mod_, &tables_, file, in_memory, cflags, ncflags))
return -1; return -1;
return 0; return 0;
} }
...@@ -313,7 +313,7 @@ int BPFModule::load_cfile(const string &file, bool in_memory) { ...@@ -313,7 +313,7 @@ int BPFModule::load_cfile(const string &file, bool in_memory) {
// build an ExecutionEngine. // build an ExecutionEngine.
int BPFModule::load_includes(const string &tmpfile) { int BPFModule::load_includes(const string &tmpfile) {
clang_loader_ = make_unique<ClangLoader>(&*ctx_, flags_); clang_loader_ = make_unique<ClangLoader>(&*ctx_, flags_);
if (clang_loader_->parse(&mod_, &tables_, tmpfile, false)) if (clang_loader_->parse(&mod_, &tables_, tmpfile, false, nullptr, 0))
return -1; return -1;
return 0; return 0;
} }
...@@ -668,7 +668,7 @@ int BPFModule::load_b(const string &filename, const string &proto_filename) { ...@@ -668,7 +668,7 @@ int BPFModule::load_b(const string &filename, const string &proto_filename) {
} }
// load a C file // load a C file
int BPFModule::load_c(const string &filename) { int BPFModule::load_c(const string &filename, const char *cflags[], int ncflags) {
if (!sections_.empty()) { if (!sections_.empty()) {
fprintf(stderr, "Program already initialized\n"); fprintf(stderr, "Program already initialized\n");
return -1; return -1;
...@@ -677,7 +677,7 @@ int BPFModule::load_c(const string &filename) { ...@@ -677,7 +677,7 @@ int BPFModule::load_c(const string &filename) {
fprintf(stderr, "Invalid filename\n"); fprintf(stderr, "Invalid filename\n");
return -1; return -1;
} }
if (int rc = load_cfile(filename, false)) if (int rc = load_cfile(filename, false, cflags, ncflags))
return rc; return rc;
if (int rc = annotate()) if (int rc = annotate())
return rc; return rc;
...@@ -687,12 +687,12 @@ int BPFModule::load_c(const string &filename) { ...@@ -687,12 +687,12 @@ int BPFModule::load_c(const string &filename) {
} }
// load a C text string // load a C text string
int BPFModule::load_string(const string &text) { int BPFModule::load_string(const string &text, const char *cflags[], int ncflags) {
if (!sections_.empty()) { if (!sections_.empty()) {
fprintf(stderr, "Program already initialized\n"); fprintf(stderr, "Program already initialized\n");
return -1; return -1;
} }
if (int rc = load_cfile(text, true)) if (int rc = load_cfile(text, true, cflags, ncflags))
return rc; return rc;
if (int rc = annotate()) if (int rc = annotate())
return rc; return rc;
......
...@@ -48,15 +48,15 @@ class BPFModule { ...@@ -48,15 +48,15 @@ class BPFModule {
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 &tmpfile); int load_includes(const std::string &tmpfile);
int load_cfile(const std::string &file, bool in_memory); 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);
public: public:
BPFModule(unsigned flags); BPFModule(unsigned flags);
~BPFModule(); ~BPFModule();
int load_b(const std::string &filename, const std::string &proto_filename); int load_b(const std::string &filename, const std::string &proto_filename);
int load_c(const std::string &filename); int load_c(const std::string &filename, const char *cflags[], int ncflags);
int load_string(const std::string &text); int load_string(const std::string &text, const char *cflags[], int ncflags);
size_t num_functions() const; size_t num_functions() const;
uint8_t * function_start(size_t id) const; uint8_t * function_start(size_t id) const;
uint8_t * function_start(const std::string &name) const; uint8_t * function_start(const std::string &name) const;
......
...@@ -65,7 +65,7 @@ ClangLoader::ClangLoader(llvm::LLVMContext *ctx, unsigned flags) ...@@ -65,7 +65,7 @@ ClangLoader::ClangLoader(llvm::LLVMContext *ctx, unsigned flags)
ClangLoader::~ClangLoader() {} ClangLoader::~ClangLoader() {}
int ClangLoader::parse(unique_ptr<llvm::Module> *mod, unique_ptr<vector<TableDesc>> *tables, int ClangLoader::parse(unique_ptr<llvm::Module> *mod, unique_ptr<vector<TableDesc>> *tables,
const string &file, bool in_memory) { const string &file, bool in_memory, const char *cflags[], int ncflags) {
using namespace clang; using namespace clang;
struct utsname un; struct utsname un;
...@@ -103,6 +103,10 @@ int ClangLoader::parse(unique_ptr<llvm::Module> *mod, unique_ptr<vector<TableDes ...@@ -103,6 +103,10 @@ int ClangLoader::parse(unique_ptr<llvm::Module> *mod, unique_ptr<vector<TableDes
kflags.push_back(BCC_INSTALL_PREFIX "/share/bcc/include"); kflags.push_back(BCC_INSTALL_PREFIX "/share/bcc/include");
for (auto it = kflags.begin(); it != kflags.end(); ++it) for (auto it = kflags.begin(); it != kflags.end(); ++it)
flags_cstr.push_back(it->c_str()); flags_cstr.push_back(it->c_str());
if (cflags) {
for (auto i = 0; i < ncflags; ++i)
flags_cstr.push_back(cflags[i]);
}
// set up the error reporting class // set up the error reporting class
IntrusiveRefCntPtr<DiagnosticOptions> diag_opts(new DiagnosticOptions()); IntrusiveRefCntPtr<DiagnosticOptions> diag_opts(new DiagnosticOptions());
......
...@@ -39,7 +39,7 @@ class ClangLoader { ...@@ -39,7 +39,7 @@ class ClangLoader {
explicit ClangLoader(llvm::LLVMContext *ctx, unsigned flags); explicit ClangLoader(llvm::LLVMContext *ctx, unsigned flags);
~ClangLoader(); ~ClangLoader();
int parse(std::unique_ptr<llvm::Module> *mod, std::unique_ptr<std::vector<TableDesc>> *tables, int parse(std::unique_ptr<llvm::Module> *mod, std::unique_ptr<std::vector<TableDesc>> *tables,
const std::string &file, bool in_memory); const std::string &file, bool in_memory, const char *cflags[], int ncflags);
private: private:
llvm::LLVMContext *ctx_; llvm::LLVMContext *ctx_;
unsigned flags_; unsigned flags_;
......
...@@ -30,9 +30,11 @@ lib = ct.CDLL("libbcc.so") ...@@ -30,9 +30,11 @@ lib = ct.CDLL("libbcc.so")
lib.bpf_module_create_b.restype = ct.c_void_p lib.bpf_module_create_b.restype = ct.c_void_p
lib.bpf_module_create_b.argtypes = [ct.c_char_p, ct.c_char_p, ct.c_uint] lib.bpf_module_create_b.argtypes = [ct.c_char_p, ct.c_char_p, ct.c_uint]
lib.bpf_module_create_c.restype = ct.c_void_p lib.bpf_module_create_c.restype = ct.c_void_p
lib.bpf_module_create_c.argtypes = [ct.c_char_p, ct.c_uint] lib.bpf_module_create_c.argtypes = [ct.c_char_p, ct.c_uint,
ct.POINTER(ct.c_char_p), ct.c_int]
lib.bpf_module_create_c_from_string.restype = ct.c_void_p lib.bpf_module_create_c_from_string.restype = ct.c_void_p
lib.bpf_module_create_c_from_string.argtypes = [ct.c_char_p, ct.c_uint] lib.bpf_module_create_c_from_string.argtypes = [ct.c_char_p, ct.c_uint,
ct.POINTER(ct.c_char_p), ct.c_int]
lib.bpf_module_destroy.restype = None lib.bpf_module_destroy.restype = None
lib.bpf_module_destroy.argtypes = [ct.c_void_p] lib.bpf_module_destroy.argtypes = [ct.c_void_p]
lib.bpf_module_license.restype = ct.c_char_p lib.bpf_module_license.restype = ct.c_char_p
...@@ -395,7 +397,7 @@ class BPF(object): ...@@ -395,7 +397,7 @@ class BPF(object):
raise Exception("Could not find file %s" % filename) raise Exception("Could not find file %s" % filename)
return filename return filename
def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0): def __init__(self, src_file="", hdr_file="", text=None, cb=None, debug=0, cflags=[]):
"""Create a a new BPF module with the given source code. """Create a a new BPF module with the given source code.
Note: Note:
...@@ -416,8 +418,11 @@ class BPF(object): ...@@ -416,8 +418,11 @@ class BPF(object):
self.debug = debug self.debug = debug
self.funcs = {} self.funcs = {}
self.tables = {} self.tables = {}
cflags_array = (ct.c_char_p * len(cflags))()
for i, s in enumerate(cflags): cflags_array[i] = s.encode("ascii")
if text: if text:
self.module = lib.bpf_module_create_c_from_string(text.encode("ascii"), self.debug) self.module = lib.bpf_module_create_c_from_string(text.encode("ascii"),
self.debug, cflags_array, len(cflags_array))
else: else:
src_file = BPF._find_file(src_file) src_file = BPF._find_file(src_file)
hdr_file = BPF._find_file(hdr_file) hdr_file = BPF._find_file(hdr_file)
...@@ -426,7 +431,7 @@ class BPF(object): ...@@ -426,7 +431,7 @@ class BPF(object):
hdr_file.encode("ascii"), self.debug) hdr_file.encode("ascii"), self.debug)
else: else:
self.module = lib.bpf_module_create_c(src_file.encode("ascii"), self.module = lib.bpf_module_create_c(src_file.encode("ascii"),
self.debug) self.debug, cflags_array, len(cflags_array))
if self.module == None: if self.module == None:
raise Exception("Failed to compile BPF module %s" % src_file) raise Exception("Failed to compile BPF module %s" % src_file)
......
...@@ -287,5 +287,13 @@ BPF_TABLE("array", int, union emptyu, t3, 1); ...@@ -287,5 +287,13 @@ BPF_TABLE("array", int, union emptyu, t3, 1);
import ctypes import ctypes
self.assertEqual(ctypes.sizeof(b["t3"].Leaf), 8) self.assertEqual(ctypes.sizeof(b["t3"].Leaf), 8)
def test_cflags(self):
text = """
#ifndef MYFLAG
#error "MYFLAG not set as expected"
#endif
"""
b = BPF(text=text, cflags=["-DMYFLAG"])
if __name__ == "__main__": if __name__ == "__main__":
main() main()
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