File fix-alignment-issue-on-x86_64-due-to-consecutive-bit.patch of Package bcc.39855

From 734c06ef26d91918cd4d8df3f3faa48e6582d89c Mon Sep 17 00:00:00 2001
From: Shung-Hsi Yu <shung-hsi.yu@suse.com>
Date: Fri, 3 May 2024 21:11:18 +0800
Subject: [PATCH 1/1] Fix alignment issue on x86_64 due to consecutive bitfield
 (iovisor/bcc#4890)
Reference: bsc#1219096

With commit f35dae07 "adjust layout string in JIT with llvm11 128bit
spec support", the alignment of i128 type in LLVM's BPF backend is
explicitly defined, which made the alignment different from the those
used in LLVM's x86 IR. Such alignment difference can result in incorrect
offset, for example:

  struct my_struct
  {
      long: 64;
      long: 64;
      long: 64;
      void* ptr;
  };

  int kprobe__netif_rx(struct pt_regs *ctx)
  {
      struct event_t event = {};
      void* p1 = (void*)ctx->di;
      void* p2 = NULL;

      event.offset1 = ((long)&((struct my_struct*)p1)->ptr) - (long)p1;
      event.offset2 = ((long)&((struct my_struct*)p2)->ptr) - (long)p2;
      events.perf_submit(ctx, &event, sizeof(event));
      return 0;
  }

Will produce a BPF program seen below, where the struct my_struct.ptr
field is calculated to be 32 for p1, but 24 for p2, which is absurd
because both are suppose to be the offset of the same field.

  Disassembly of function kprobe__netif_rx
  ; { // Line  34
     0:   b7 02 00 00 18 00 00 00 r2 = 24
  ; event.offset2 = (long)&((struct my_struct*)p2)->ptr - (long)p2; // Line  41
     1:   7b 2a f8 ff 00 00 00 00 *(u64 *)(r10 - 8) = r2
     2:   b7 02 00 00 20 00 00 00 r2 = 32
  ; event.offset1 = (long)&((struct my_struct*)p1)->ptr - (long)p1; // Line  40
     3:   7b 2a f0 ff 00 00 00 00 *(u64 *)(r10 - 16) = r2
  ; bpf_perf_event_output(ctx, (void *)bpf_pseudo_fd(1, -1), CUR_CPU_IDENTIFIER, &event, sizeof(event)); // Line  42
     ...

This happens because the three consecutive `long :64` anonymous
bitfields were merged into a single i192 type, which uses the alignment
of the largest defined datatype, thus i128 for BPF and i64 for x86,
which were 16 and 8, respectively. Since this mismatch in alignment is
mainly an issue only where there's a large, undefined data type, we can
simply pass the -ffine-grained-bitfield-access to Clang during the x86
IR pass to prevent consecutive bitfield from being merged, and thus
workaround the issue.

Link: https://github.com/iovisor/bcc/issues/4890
Link: https://bugzilla.suse.com/show_bug.cgi?id=1219096
---
Note: this patch is not upstreamed because this is used to address issue
that occurs when bcc uses vmlinux.h generated by bpftool from runtime
kernel's BTF, which isn't support by upstream. But since working around
this issue with -ffine-grained-bitfield-accesses is deemed a relatively
safe change, we decide to carry this change as a downstream patch.
---
 src/cc/frontends/clang/kbuild_helper.cc | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/cc/frontends/clang/kbuild_helper.cc b/src/cc/frontends/clang/kbuild_helper.cc
index 50e2da9a..beb6fef2 100644
--- a/src/cc/frontends/clang/kbuild_helper.cc
+++ b/src/cc/frontends/clang/kbuild_helper.cc
@@ -136,6 +136,9 @@ int KBuildHelper::get_flags(const char *uname_machine, vector<string> *cflags) {
   cflags->push_back("-Wno-unused-value");
   cflags->push_back("-Wno-pointer-sign");
   cflags->push_back("-fno-stack-protector");
+#ifdef __x86_64__
+  cflags->push_back("-ffine-grained-bitfield-accesses");
+#endif
 
   return 0;
 }
-- 
2.44.0

openSUSE Build Service is sponsored by