[DTrace-devel] [PATCH] Add BPF verifier log post-processor scripts
Kris Van Hees
kris.van.hees at oracle.com
Thu Aug 19 23:47:53 PDT 2021
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
cmd/isolateFunc | 89 +++++++++++++
cmd/procVerifierLog | 316 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 405 insertions(+)
create mode 100755 cmd/isolateFunc
create mode 100755 cmd/procVerifierLog
diff --git a/cmd/isolateFunc b/cmd/isolateFunc
new file mode 100755
index 00000000..8afec455
--- /dev/null
+++ b/cmd/isolateFunc
@@ -0,0 +1,89 @@
+#!/usr/bin/awk -f
+
+BEGIN {
+ if ((!fname && !faddr) || (fname && faddr)) {
+ print "Syntax: isolateFunc -vfname=<NAME>";
+ print " isolateFunc -vfaddr=<ADDR>";
+ exit(1);
+ }
+
+ saddr = -1;
+ eaddr = -1;
+}
+
+$1 != "BPF:" {
+ next;
+}
+
+$2 ~ /^func#[0-9]/ {
+ addr = int(substr($3, 2));
+ if (NF >= 4)
+ fn[addr] = substr($4, 2, length($4) - 2);
+ else
+ fn[addr] = $2;
+
+ if (fname == fn[addr] || (NF >= 4 && fname == $2)) {
+ saddr = addr;
+ eaddr = -1;
+ } else if (addr <= faddr) {
+ saddr = addr;
+ eaddr = -1;
+ } else if (eaddr == -1)
+ eaddr = addr;
+
+ next;
+}
+
+$2 !~ /^func#[0-9]/ && eaddr == -1 {
+ eaddr = 1000000;
+}
+
+int($2) == 0 {
+ if (saddr == -1) {
+ printf "ERROR: function '%s' not found.\n", fname;
+ exit(1);
+ }
+}
+
+$2 ~ /^(R[0-9]|fp)/ {
+ rv[rc++] = $0;
+ next;
+}
+
+int($2) == saddr {
+ printf "Function <%s> [%d-%d]\n", fn[saddr], saddr, eaddr;
+}
+
+int($2) >= saddr && int($2) < eaddr {
+ pc = int($2)
+ if (pc < ppc)
+ print "BPF: ----------";
+ ppc = pc;
+
+ for (i = 0; i < rc; i++)
+ print rv[i];
+ print;
+}
+
+$2 ~ /^----------/ {
+ next;
+}
+
+/returning from/ && int($8) >= saddr && int($8) < eaddr {
+ print "BPF:";
+ print;
+ getline;
+ print;
+ next;
+}
+
+/returning from/ {
+ getline;
+ next;
+}
+
+$2 ~ /^[0-9]+:/ {
+ delete rv;
+ rc = 0;
+ next;
+}
diff --git a/cmd/procVerifierLog b/cmd/procVerifierLog
new file mode 100755
index 00000000..a7f1d544
--- /dev/null
+++ b/cmd/procVerifierLog
@@ -0,0 +1,316 @@
+#!/usr/bin/gawk -f
+
+BEGIN {
+ state = 0;
+
+ arith["+="] = "add";
+ arith["-="] = "sub";
+ arith["*="] = "mul";
+ arith["/="] = "div";
+ arith["|="] = "or";
+ arith["&="] = "and";
+ arith["<<="] = "lsh";
+ arith[">>="] = "rsh";
+ arith["%="] = "mod";
+ arith["^="] = "xor";
+ arith["s>>="] = "arsh";
+
+ cond["=="] = "jeq";
+ cond["!="] = "jne";
+ cond[">="] = "jge";
+ cond["<="] = "jle";
+ cond[">"] = "jgt";
+ cond["<"] = "jlt";
+ cond["s>="] = "jsge";
+ cond["s<="] = "jsle";
+ cond["s>"] = "jsgt";
+ cond["s<"] = "jslt";
+ cond["&"] = "jset";
+
+ ld[64] = "lddw";
+ ld[32] = "ldw";
+ ld[16] = "ldh";
+ ld[8] = "ldb";
+
+ st[64] = "stdw";
+ st[32] = "stw";
+ st[16] = "sth";
+ st[8] = "stb";
+}
+
+state == 0 && /^Disassembly of final program/ {
+ pn = $NF;
+ sub(/:$/, "", pn);
+ fa[0] = pn;
+ state = 1;
+}
+
+state == 1 && $1 == "BPF" && $2 == "OFFSET" {
+ state = 2;
+ print;
+ while (getline == 1) {
+ if (NF == 0)
+ break;
+
+ print;
+
+ if ($1 == "R_BPF_INSN_DISP32" && $4 ~ /^dt_/)
+ fa[int($3)] = $4;
+ }
+
+ asorti(fa, na)
+
+ delete na;
+}
+
+/^BPF: (frame[0-9]+|R[0-9]+)/ {
+ next;
+}
+
+/^BPF: func#[0-9]+ @[0-9]+$/ {
+ i = int(substr($3, 2));
+ if (i in fa) {
+ fn[i] = fa[i];
+ printf "BPF: %-8s %8s (%s)\n", $2, $3, fn[i];
+ } else {
+ fn[i] = $2;
+ printf "BPF: %-8s %8s\n", $2, $3;
+ }
+ next;
+}
+
+# Find a function name
+function fname(addr, fn, i) {
+ fn = "???";
+ for (i in fa) {
+ if (int(addr) < int(i))
+ break;
+
+ fn = fa[i];
+ }
+ return fn;
+}
+
+/^BPF: returning from callee:$/ {
+ $4 = fname(pc);
+ callfrom = $0;
+
+ getline;
+ if (match($0, / R0/) > 0) {
+ callretv = substr($0, RSTART + 1);
+ sub(/ (R|fp-)[0-9].*/, "", callretv);
+ } else
+ callretv = "R0=???";
+ next;
+}
+
+/^BPF: to caller at [0-9]+:$/ {
+ pc = int($5);
+ $3 = fname(pc);
+ $1 = "";
+ if (!callfrom)
+ callfrom = "BPF: returning";
+ print "BPF: ----------";
+ print callfrom $0;
+ printf "BPF: %s\n", callretv;
+ next;
+}
+
+/^BPF: [0-9]+: \(/ {
+ state = 3;
+ pc = int($2);
+ opc = $3;
+ $1 = $2 = $3 = "";
+ sub(/^ +/, "");
+
+ if (pc in fn)
+ ann = "<" fn[pc] ">";
+ else
+ ann = 0;
+
+ # The BPF verifier is reporting on an alternative branch or is trying
+ # an alternative speculative value for something. Either way, we went
+ # back to earlier code, so indicate a control flow boundary and reset
+ # the regstate so we report the initial register state for this
+ # section of instructions.
+ if (pc < ppc) {
+ print "BPF: ----------";
+ regstate = 0;
+ }
+
+ ppc = pc;
+
+ callfrom = 0;
+ callretv = 0;
+}
+
+/^BPF: [0-9]+: (frame[0-9]: )?R[0-9]+/ {
+ pc = int($2);
+ $1 = $2 = "";
+ sub(/^ +/, "");
+
+ if ($0 != regstate) {
+ regstate = $0;
+
+ if (match($0, /^frame[0-9]: /) > 0) {
+ printf "BPF: %s\n", substr($0, 1, RLENGTH - 1);
+ $0 = substr($0, RSTART + RLENGTH);
+ }
+
+ while (match($0, / R[0-9]+/) > 0) {
+ printf "BPF: %s\n", substr($0, 1, RSTART);
+ $0 = substr($0, RSTART + 1);
+ }
+
+ if (match($0, / fp-[0-9]+/) > 0) {
+ printf "BPF: %s\n", substr($0, 1, RSTART);
+ $0 = substr($0, RSTART + 1);
+ }
+
+ printf "BPF: %s\n", $0;
+ }
+ next;
+}
+
+state != 3 {
+ print;
+ next;
+}
+
+# Print an instruction
+function emit(ins, args, ann, s, n) {
+ gsub(/%r10/, "%fp", args);
+ s = sprintf("BPF: % 5d: %4.4s %-4.4s %s", pc, opc, ins, args);
+ if (ann) {
+ n = length(s);
+ if (n > 64)
+ n = 0;
+ else
+ n = 64 - n;
+ printf "%s%*s! %s\n", s, n, "", ann;
+ } else
+ print s;
+}
+
+# Register-to-register assignment
+/[rw][0-9]+ = [rw][0-9]+/ {
+ emit("mov", "%" $1 ", %" $3, ann);
+ next;
+}
+
+# Negate Register value
+/[rw][0-9]+ = -[rw][0-9]+/ {
+ emit("neg", "%" $1, ann);
+ next;
+}
+
+# Immediate-to-register assignment
+/^r[0-9]+ = [-0-9]+/ {
+ emit("mov", "%" $1 ", " $3, ann);
+ next;
+}
+
+# 64-bit value assignment
+/^r[0-9] = 0x[0-9a-f]+/ {
+ emit("lddw", "%" $1 ", " $3, ann);
+ next;
+}
+
+# Load from register
+/^r[0-9]+ = \*\(u[0-9]+ \*\)\(r[0-9]+ [-+][0-9]+\)/ {
+ sz = int(substr($3, 4));
+ sub(/\)/, "]", $5);
+ emit(ld[sz], "%" $1 ", [%" substr($4, 4) $5, ann);
+ next;
+}
+
+# Store from register
+/^\*\(u[0-9]+ \*\)\(r[0-9]+ [-+][0-9]+\) = r[0-9]+/ {
+ sz = int(substr($1, 4));
+ sub(/\)/, "]", $3);
+ emit(st[sz], "[%" substr($2, 4) $3 ", %" $5, ann);
+ next;
+}
+
+# Store from immediate
+/^\*\(u[0-9]+ \*\)\(r[0-9]+ [-+][0-9]+\) = [^r]/ {
+ sz = int(substr($1, 4));
+ sub(/\)/, "]", $3);
+ emit(st[sz], "[%" substr($2, 4) $3 ", " $5, ann);
+ next;
+}
+
+# Arithmetic with register
+/^[rw][0-9] [^=]+= [rw][0-9]/ {
+ emit(arith[$2], "%" $1 ", %" $3, ann);
+ next;
+}
+
+# Arithmetic with immediate value
+/^[rw][0-9] [^=]+= -?[0-9]+/ {
+ emit(arith[$2], "%" $1 ", " $3, ann);
+ next;
+}
+
+# BPF helper call
+/^call bpf/ {
+ sub(/#.*$/, "", $2);
+ emit("call", $2, ann);
+ next;
+}
+
+# Function call
+/^call pc[-+]/ {
+ off = int(substr($2, 3));
+ addr = pc + 1 + off;
+ if (addr in fn)
+ nm = fn[addr];
+ else
+ nm = $2;
+
+ if (ann)
+ emit("call", nm, ann " -> " addr);
+ else
+ emit("call", nm, "-> " addr);
+ next;
+}
+
+# Return
+/^exit/ {
+ emit("exit", "", ann);
+ next;
+}
+
+# Conditional branch
+/^if r[0-9]+ / {
+ off = int(substr($6, 3));
+ addr = pc + 1 + off;
+ t_branch[branchc] = addr;
+ f_branch[branchc] = pc + 1;
+ branchc++;
+
+ if ($4 ~ /^r/)
+ $4 = "%" $4;
+
+ if (ann)
+ emit(cond[$3], "%" $2 ", " $4 ", " off, ann " -> " addr);
+ else
+ emit(cond[$3], "%" $2 ", " $4 ", " off, "-> " addr);
+ next;
+}
+
+# Jump
+/^goto / {
+ off = int(substr($2, 3));
+ addr = pc + 1 + off;
+
+ if (ann)
+ emit("ja", off, ann " -> " addr);
+ else
+ emit("ja", off, "-> " addr);
+ next;
+}
+
+{
+ print;
+}
--
2.33.0
More information about the DTrace-devel
mailing list