[clang] 3060304 - [Clang][BPF] Type print btf_type_tag properly

Yonghong Song via cfe-commits cfe-commits at lists.llvm.org
Mon May 8 07:42:28 PDT 2023


Author: Yonghong Song
Date: 2023-05-08T07:41:27-07:00
New Revision: 3060304906f08f933672f0a30cc57d5f09766444

URL: https://github.com/llvm/llvm-project/commit/3060304906f08f933672f0a30cc57d5f09766444
DIFF: https://github.com/llvm/llvm-project/commit/3060304906f08f933672f0a30cc57d5f09766444.diff

LOG: [Clang][BPF] Type print btf_type_tag properly

When running bcc tool execsnoop ([1]) which is built with latest llvm,
I hit the following error:
  $ sudo ./execsnoop.py
  /virtual/main.c:99:157: error: expected ')'
    data.ppid = ({ typeof(pid_t) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val),
       (void *)&({ typeof(struct task_struct  btf_type_tag(rcu)*) _val; __builtin_memset(&_val, 0, sizeof(_val));
                                              ^
        bpf_probe_read(&_val, sizeof(_val), (void *)&task->real_parent); _val; })->tgid); _val; });

The failure reason is due to that the bcc rewriter printed type like
  struct task_struct  btf_type_tag(rcu)*
where the compiler cannot recognize what 'btf_type_tag(rcu)' is.

The above type is printed in [2] by UnaryOperator->getType().getAsString() (from clang)
in function ProbeVisitor::VisitUnaryOperator.

The original source type looks like ([3])
  struct task_struct {
    ...
    struct task_struct __rcu	*real_parent;
    ...
  }
  where '__rcu' is a macro expanding to '__attribute__((btf_type_tag("rcu")))'.

Let us print btf_type_tag properly in clang so bcc tools and broader type printing
will work properly.

With this patch, the above rewrited source code looks like
    data.ppid = ({ typeof(pid_t) _val; __builtin_memset(&_val, 0, sizeof(_val)); bpf_probe_read(&_val, sizeof(_val),
       (void *)&({ typeof(struct task_struct  __attribute__((btf_type_tag("rcu")))*) _val; __builtin_memset(&_val, 0, sizeof(_val));
        bpf_probe_read(&_val, sizeof(_val), (void *)&task->real_parent); _val; })->tgid); _val; });

and execsnoop.py tool can run properly.

  [1] https://github.com/iovisor/bcc/blob/master/tools/exitsnoop.py
  [2] https://github.com/iovisor/bcc/blob/master/src/cc/frontends/clang/b_frontend_action.cc
  [3] https://github.com/torvalds/linux/blob/master/include/linux/sched.h

Differential Revision: https://reviews.llvm.org/D150017

Added: 
    clang/test/AST/ast-dump-bpf-attr.c

Modified: 
    clang/lib/AST/TypePrinter.cpp
    clang/test/Sema/attr-btf_type_tag.c
    clang/test/SemaCXX/sugar-common-types.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 408c7caa16c93..02e0793f5cb16 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1845,7 +1845,7 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
 void TypePrinter::printBTFTagAttributedBefore(const BTFTagAttributedType *T,
                                               raw_ostream &OS) {
   printBefore(T->getWrappedType(), OS);
-  OS << " btf_type_tag(" << T->getAttr()->getBTFTypeTag() << ")";
+  OS << " __attribute__((btf_type_tag(\"" << T->getAttr()->getBTFTypeTag() << "\")))";
 }
 
 void TypePrinter::printBTFTagAttributedAfter(const BTFTagAttributedType *T,

diff  --git a/clang/test/AST/ast-dump-bpf-attr.c b/clang/test/AST/ast-dump-bpf-attr.c
new file mode 100644
index 0000000000000..8899cecbb6e9f
--- /dev/null
+++ b/clang/test/AST/ast-dump-bpf-attr.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple bpf-pc-linux-gnu -ast-dump  %s \
+// RUN: | FileCheck --strict-whitespace %s
+
+int __attribute__((btf_type_tag("rcu"))) * g;
+// CHECK: VarDecl{{.*}}g 'int  __attribute__((btf_type_tag("rcu")))*'

diff  --git a/clang/test/Sema/attr-btf_type_tag.c b/clang/test/Sema/attr-btf_type_tag.c
index f7ba29b0aa657..a3ef404f38238 100644
--- a/clang/test/Sema/attr-btf_type_tag.c
+++ b/clang/test/Sema/attr-btf_type_tag.c
@@ -28,8 +28,8 @@ int __tag4 * __tag5 * __tag6 *foo1(struct t __tag1 * __tag2 * __tag3 *a1) {
 int g1 = _Generic((int *)0, int __tag1 *: 0);
 int g2 = _Generic((int __tag1 *)0, int *: 0);
 int g3 = _Generic(0,
-                  int __tag1 * : 0, // expected-note {{compatible type 'int  btf_type_tag(tag1)*' (aka 'int *') specified here}}
-                  int * : 0, // expected-error {{type 'int *' in generic association compatible with previously specified type 'int  btf_type_tag(tag1)*' (aka 'int *')}}
+                  int __tag1 * : 0, // expected-note {{compatible type 'int  __attribute__((btf_type_tag("tag1")))*' (aka 'int *') specified here}}
+                  int * : 0, // expected-error {{type 'int *' in generic association compatible with previously specified type 'int  __attribute__((btf_type_tag("tag1")))*' (aka 'int *')}}
                   default : 0);
 
 // The btf_type_tag attribute will be ignored during overloadable type matching

diff  --git a/clang/test/SemaCXX/sugar-common-types.cpp b/clang/test/SemaCXX/sugar-common-types.cpp
index f4e545bb9bceb..4a8ff2addb663 100644
--- a/clang/test/SemaCXX/sugar-common-types.cpp
+++ b/clang/test/SemaCXX/sugar-common-types.cpp
@@ -95,7 +95,7 @@ using SBTF2 = ::SS1 [[clang::btf_type_tag("1")]];
 using SBTF3 = ::SS1 [[clang::btf_type_tag("2")]];
 
 N t21 = 0 ? (SBTF1){} : (SBTF3){}; // expected-error {{from 'SS1'}}
-N t22 = 0 ? (SBTF1){} : (SBTF2){}; // expected-error {{from 'SS1 btf_type_tag(1)' (aka 'SS1')}}
+N t22 = 0 ? (SBTF1){} : (SBTF2){}; // expected-error {{from 'SS1 __attribute__((btf_type_tag("1")))' (aka 'SS1')}}
 
 using QX = const SB1 *;
 using QY = const ::SB1 *;


        


More information about the cfe-commits mailing list