bcc/tools: Fix renaming of the state field of task_struct

Kernel commit 2f064a59a1 ("sched: Change task_struct::state") changes
the name of task_struct::state to task_struct::__state, which breaks
several bcc tools. Fix this issue by checking field existence in vmlinux
BTF. Since this change was intruduce in kernel v5.14, we should have
BTF support. Closes #3658 .

Signed-off-by: Hengqi Chen <chenhengqi@outlook.com>
diff --git a/tools/runqslower.py b/tools/runqslower.py
index ef2bf28..6c94d6c 100755
--- a/tools/runqslower.py
+++ b/tools/runqslower.py
@@ -118,7 +118,7 @@
 
     // ivcsw: treat like an enqueue event and store timestamp
     prev_pid = prev->pid;
-    if (prev->state == TASK_RUNNING) {
+    if (prev->STATE_FIELD == TASK_RUNNING) {
         tgid = prev->tgid;
         u64 ts = bpf_ktime_get_ns();
         if (prev_pid != 0) {
@@ -185,7 +185,7 @@
     long state;
 
     // ivcsw: treat like an enqueue event and store timestamp
-    bpf_probe_read_kernel(&state, sizeof(long), (const void *)&prev->state);
+    bpf_probe_read_kernel(&state, sizeof(long), (const void *)&prev->STATE_FIELD);
     bpf_probe_read_kernel(&prev_pid, sizeof(prev->pid), &prev->pid);
     if (state == TASK_RUNNING) {
         bpf_probe_read_kernel(&tgid, sizeof(prev->tgid), &prev->tgid);
@@ -234,6 +234,10 @@
     bpf_text += bpf_text_kprobe
 
 # code substitutions
+if BPF.kernel_struct_has_field(b'task_struct', b'__state') == 1:
+    bpf_text = bpf_text.replace('STATE_FIELD', '__state')
+else:
+    bpf_text = bpf_text.replace('STATE_FIELD', 'state')
 if min_us == 0:
     bpf_text = bpf_text.replace('FILTER_US', '0')
 else: