Skip to content

Commit eb0fa8b

Browse files
committed
[Clang][Attr] Support btf_type_tag attribute
This patch introduced btf_type_tag attribute. The attribute is a type attribute and intends to address the below linux use cases. typedef int __user *__intp; int foo(int __user *arg, ...) static int do_execve(struct filename *filename, const char __user *const __user *__argv, const char __user *const __user *__envp) Here __user in the kernel defined as __attribute__((noderef, address_space(__user))) for sparse ([1]) type checking mode. For normal clang compilation, we intend to replace it with __attribute__((btf_type_tag("user"))) and record such informaiton in dwarf and BTF so such information later can be used in kernel for bpf verification or for other tracing functionalities. [1] https://www.kernel.org/doc/html/v4.11/dev-tools/sparse.html Differential Revision: https://reviews.llvm.org/D111199
1 parent 76cbe62 commit eb0fa8b

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,6 +1845,13 @@ def BTFDeclTag : InheritableAttr {
18451845
let LangOpts = [COnly];
18461846
}
18471847

1848+
def BTFTypeTag : TypeAttr {
1849+
let Spellings = [Clang<"btf_type_tag">];
1850+
let Args = [StringArgument<"BTFTypeTag">];
1851+
let Documentation = [BTFTypeTagDocs];
1852+
let LangOpts = [COnly];
1853+
}
1854+
18481855
def WebAssemblyExportName : InheritableAttr,
18491856
TargetSpecificAttr<TargetWebAssembly> {
18501857
let Spellings = [Clang<"export_name">];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2023,6 +2023,23 @@ section too.
20232023
}];
20242024
}
20252025

2026+
def BTFTypeTagDocs : Documentation {
2027+
let Category = DocCatType;
2028+
let Content = [{
2029+
Clang supports the ``__attribute__((btf_type_tag("ARGUMENT")))`` attribute for
2030+
all targets. It only has effect when ``-g`` is specified on the command line and
2031+
is currently silently ignored when not applied to a pointer type (note: this
2032+
scenario may be diagnosed in the future).
2033+
2034+
The ``ARGUMENT`` string will be preserved in IR and emitted to DWARF for the
2035+
types used in variable declarations, function declarations, or typedef
2036+
declarations.
2037+
2038+
For BPF targets, the ``ARGUMENT`` string will also be emitted to .BTF ELF
2039+
section.
2040+
}];
2041+
}
2042+
20262043
def MipsInterruptDocs : Documentation {
20272044
let Category = DocCatFunction;
20282045
let Heading = "interrupt (MIPS)";

clang/lib/AST/TypePrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,9 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
17461746
case attr::ArmMveStrictPolymorphism:
17471747
OS << "__clang_arm_mve_strict_polymorphism";
17481748
break;
1749+
case attr::BTFTypeTag:
1750+
OS << "btf_type_tag";
1751+
break;
17491752
}
17501753
OS << "))";
17511754
}

clang/lib/Sema/SemaType.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5900,6 +5900,9 @@ namespace {
59005900
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
59015901
Visit(TL.getUnqualifiedLoc());
59025902
}
5903+
// Allow to fill pointee's type locations, e.g.,
5904+
// int __attr * __attr * __attr *p;
5905+
void VisitPointerTypeLoc(PointerTypeLoc TL) { Visit(TL.getNextTypeLoc()); }
59035906
void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
59045907
TL.setNameLoc(DS.getTypeSpecTypeLoc());
59055908
}
@@ -6500,6 +6503,34 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
65006503
return BuildAddressSpaceAttr(T, ASIdx, AddrSpace, AttrLoc);
65016504
}
65026505

6506+
static void HandleBTFTypeTagAttribute(QualType &Type, const ParsedAttr &Attr,
6507+
TypeProcessingState &State) {
6508+
Sema &S = State.getSema();
6509+
6510+
// Check the number of attribute arguments.
6511+
if (Attr.getNumArgs() != 1) {
6512+
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
6513+
<< Attr << 1;
6514+
Attr.setInvalid();
6515+
return;
6516+
}
6517+
6518+
// Ensure the argument is a string.
6519+
auto *StrLiteral = dyn_cast<StringLiteral>(Attr.getArgAsExpr(0));
6520+
if (!StrLiteral) {
6521+
S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
6522+
<< Attr << AANT_ArgumentString;
6523+
Attr.setInvalid();
6524+
return;
6525+
}
6526+
6527+
ASTContext &Ctx = S.Context;
6528+
StringRef BTFTypeTag = StrLiteral->getString();
6529+
Type = State.getAttributedType(
6530+
::new (Ctx) BTFTypeTagAttr(Ctx, Attr, BTFTypeTag), Type, Type);
6531+
return;
6532+
}
6533+
65036534
/// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
65046535
/// specified type. The attribute contains 1 argument, the id of the address
65056536
/// space for the type.
@@ -8129,6 +8160,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
81298160
case ParsedAttr::IgnoredAttribute:
81308161
break;
81318162

8163+
case ParsedAttr::AT_BTFTypeTag:
8164+
HandleBTFTypeTagAttribute(type, attr, state);
8165+
attr.setUsedAsTypeAttr();
8166+
break;
8167+
81328168
case ParsedAttr::AT_MayAlias:
81338169
// FIXME: This attribute needs to actually be handled, but if we ignore
81348170
// it it breaks large amounts of Linux software.

clang/test/Sema/attr-btf_type_tag.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -x c -triple x86_64-pc-linux-gnu -dwarf-version=4 -fsyntax-only -verify %s
2+
3+
#define __tag1 __attribute__((btf_type_tag("tag1")))
4+
#define __tag2 __attribute__((btf_type_tag("tag2")))
5+
#define __tag3 __attribute__((btf_type_tag("tag3")))
6+
#define __tag4 __attribute__((btf_type_tag("tag4")))
7+
#define __tag5 __attribute__((btf_type_tag("tag5")))
8+
#define __tag6 __attribute__((btf_type_tag("tag6")))
9+
10+
int __attribute__((btf_type_tag("tag1", "tag2"))) *invalid1; // expected-error {{'btf_type_tag' attribute takes one argument}}
11+
int __attribute__((btf_type_tag(2))) *invalid2; // expected-error {{'btf_type_tag' attribute requires a string}}
12+
13+
int * __tag1 __tag2 * __tag3 __tag4 * __tag5 __tag6 *g;
14+
15+
typedef void __fn_t(int);
16+
typedef __fn_t __tag1 __tag2 * __tag3 __tag4 *__fn2_t;
17+
struct t {
18+
int __tag1 * __tag2 * __tag3 *a;
19+
int __tag1 __tag2 __tag3 *b;
20+
__fn2_t c;
21+
long d;
22+
};
23+
int __tag4 * __tag5 * __tag6 *foo1(struct t __tag1 * __tag2 * __tag3 *a1) {
24+
return (int __tag4 * __tag5 * __tag6 *)a1[0][0]->d;
25+
}

0 commit comments

Comments
 (0)