bpf_unparser should have a flag bpf_target() which distinguishes whether code is being generated for userspace-interpreter (no restrictions) or BPF kernel-interpreter (many restrictions). First this will enable better/simpler error checking logic. Down the line, this will allow adding more values to bpf_target() and generating certain constructs differently depending on whether they're targeting different versions of BPF (with different restrictions).
Added a 'target' field to struct program. Next step is to go through bpf-translate.cxx and spot all the places where we should be checking that 'target' field and signalling an error (or possibly generating different code) instead of crossing our fingers that the user knows which stap language constructs are and aren't supported by kernel bpf. That way, if we use the wrong construct in the wrong code, we won't be getting this type of cryptic madness anymore: $ sudo ~/stap-install/bin/stap --bpf -e 'global g probe kernel.function("vfs_read") { g["foo"] = "bar" foreach(k in g) { println(k) } }' Error loading /tmp/stapoSgfxZ/stap_25366.bo: bpf program load failed: Invalid argument back-edge from insn 1051 to 92 WARNING: /home/serhei/stap-install/bin/stapbpf exited with status: 1 Pass 5: run failed. [man error::pass5] Once the error messages work well (exist), I'll close this PR. But in general, this work should also allow the userspace interpreter's constraints to be relaxed (e.g. stack size or hard-register file could be increased) if or when that proves necessary down the line.
Added some basic checking and error messages. Keeping PR open since we also want to do a pass over tapset functions in case some are userspace-only. We could mark this with a /* bpf_userspace */ annotation (bikeshed colour choice pending).
Added a /* userspace */ annotation to all embeddedcode tapset functions that call a userspace-only helper.