Commit 81a783a8 authored by Brenden Blanco's avatar Brenden Blanco

Add debug flag to enable prints from kernel verifier

Add flag to BPF() to enable debug prints from the verifier. Use by
passing 0x2 to debug= in the constructor. Add docstring for BPF
constructor.

Also, optimize bpf_prog_load so that by default the kernel is not
asked to print the verbose output. The program will be "loaded" a second
time to capture the verifier failure message.

Fixes: #147
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent 88fda697
......@@ -122,8 +122,6 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
const char *license, unsigned kern_version,
char *log_buf, unsigned log_buf_size)
{
log_buf = log_buf ? log_buf : bpf_log_buf;
log_buf_size = log_buf_size ? log_buf_size : LOG_BUF_SIZE;
union bpf_attr attr = {
.prog_type = prog_type,
.insns = ptr_to_u64((void *) insns),
......@@ -131,14 +129,19 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
.license = ptr_to_u64((void *) license),
.log_buf = ptr_to_u64(log_buf),
.log_size = log_buf_size,
.log_level = 1,
.log_level = log_buf ? 1 : 0,
};
attr.kern_version = kern_version;
if (log_buf)
log_buf[0] = 0;
int ret = syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
if (ret < 0 && log_buf == bpf_log_buf) {
if (ret < 0 && !log_buf) {
// caller did not specify log_buf but failure should be printed,
// so call recursively and print the result to stderr
bpf_prog_load(prog_type, insns, prog_len, license, kern_version,
bpf_log_buf, LOG_BUF_SIZE);
fprintf(stderr, "bpf: %s\n%s\n", strerror(errno), bpf_log_buf);
}
return ret;
......
......@@ -259,6 +259,21 @@ class BPF(object):
return filename
def __init__(self, src_file="", hdr_file="", text=None, debug=0):
"""Create a a new BPF module with the given source code.
Note:
All fields are marked as optional, but either `src_file` or `text`
must be supplied, and not both.
Args:
src_file (Optional[str]): Path to a source file for the module
hdr_file (Optional[str]): Path to a helper header file for the `src_file`
text (Optional[str]): Contents of a source file for the module
debug (Optional[int]): Flags used for debug prints, can be |'d together
0x1: print LLVM IR to stderr
0x2: print BPF bytecode to stderr
"""
self.debug = debug
self.funcs = {}
self.tables = {}
......@@ -284,16 +299,19 @@ class BPF(object):
if lib.bpf_function_start(self.module, func_name.encode("ascii")) == None:
raise Exception("Unknown program %s" % func_name)
log_buf = ct.create_string_buffer(65536) if self.debug else None
fd = lib.bpf_prog_load(prog_type,
lib.bpf_function_start(self.module, func_name.encode("ascii")),
lib.bpf_function_size(self.module, func_name.encode("ascii")),
lib.bpf_module_license(self.module),
lib.bpf_module_kern_version(self.module),
None, 0)
log_buf, ct.sizeof(log_buf) if log_buf else 0)
if self.debug & 0x2:
print(log_buf.value.decode(), file=sys.stderr)
if fd < 0:
print((ct.c_char * 65536).in_dll(lib, "bpf_log_buf").value)
#print(ct.c_char_p.in_dll(lib, "bpf_log_buf").value)
raise Exception("Failed to load BPF program %s" % func_name)
fn = BPF.Function(self, func_name, fd)
......
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