0

I keep getting this missing terminating character error with my code. My goal is to just print the string word by word. Here is the code.

bpfprogram = """

int helloworld2(void *ctx)
{

    const char *str = "here are some words";
    int length = sizeof(str);
    int start = 0;
    for (int i = 0; i < length; i++) {
        if (str[i] == ' ') {
            bpf_trace_printk("%.*s\n", i - start, str + start);
            start = i + 1;
        }
    }
    bpf_trace_printk("%.*s\n", length - start, str + start);

    return 0;
}
"""
# This compiles the program defined by the bpfprogram string into bpf bytecode and
#loads it to the kernel BPF verifier.
b = BPF(text=bpfprogram)
# This attaches the compiled BPF program to a kernel event of your choosing,
#in this case to the sys_clone syscall which will cause the BPF program to run
#everytime the sys_clone call occurs.
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="helloworld2")
# Capture and print the BPF program's trace output
b.trace_print()

And this is the terminating error I keep getting hit with. I am sure the quotes are fine but I am unsure where my error is at this point.

> /virtual/main.c:11:30: warning: missing terminating '"' character [-Winvalid-pp-token]
            bpf_trace_printk("%.*s
                             ^
/virtual/main.c:11:30: error: expected expression
/virtual/main.c:12:1: warning: missing terminating '"' character [-Winvalid-pp-token]
", i - start, str + start);
^
/virtual/main.c:16:22: warning: missing terminating '"' character [-Winvalid-pp-token]
    bpf_trace_printk("%.*s
                     ^
/virtual/main.c:16:22: error: expected expression
/virtual/main.c:17:1: warning: missing terminating '"' character [-Winvalid-pp-token]
", length - start, str + start);
^
/virtual/main.c:20:2: error: expected '}'
}
 ^
/virtual/main.c:9:38: note: to match this '{'
    for (int i = 0; i < length; i++) {
                                     ^
/virtual/main.c:20:2: error: expected '}'
}
 ^
/virtual/main.c:4:1: note: to match this '{'
{
^
4 warnings and 4 errors generated.
Traceback (most recent call last):
  File "BPFHelloWorld.py", line 26, in <module>
    b = BPF(text=bpfprogram)
  File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 347, in __init__
    raise Exception("Failed to compile BPF module %s" % (src_file or "<text>"))
Exception: Failed to compile BPF module <te

xt>

1 Answers1

0

I am sure the quotes are fine

But they are not :)

All your eBPF code is inside of a Python multiline string (""" block). In this string, the line break (\n) is interpreted normally, which means that a line break is inserted when Python uses it, and the line which is passed to clang is:

bpf_trace_printk("%.*s

... where the ending quotes are, indeed, missing. Just escape this backslash, as in the other BCC examples:

bpf_trace_printk("%.*s\\n", ...);
Qeole
  • 8,284
  • 1
  • 24
  • 52
  • Thank you for the solution! I am left with a back-edge from insn 32 to 33 error after this and I am stuck once more. Do you have an idea of how I can get this to print maybe? – maxterthrowaway Jul 19 '21 at 01:42
  • Back edge is likely from your `for` loop. I'd expect clang to replace `length` with a constant, because the string is a `const`, but maybe it doesn't. Try using a constant instead of `length`. Oh and this is only for kernels 5.3+, which have support for bounded loops. Before that you must unroll the loop at compilation (search for `pragma unroll`, for example [here](https://docs.cilium.io/en/latest/bpf)). – Qeole Jul 19 '21 at 20:16