From d129ac27e872e189363e3d8cd6bc4e2152cd73ec Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20M=C3=BCller?= Date: Wed, 29 Jun 2022 18:20:37 -0700 Subject: [PATCH] [BPF] Introduce support for type match relocations Among others, BPF currently supports the type-exists CO-RE relocation (e.g., see D83878 & D83242). Its intention, as the name tries to convey, is to be used for checking existence of a type in a target. While that check is useful and has its place, we would also like to be able to perform stricter type queries: instead of just checking mere existence, we want to make sure that members match up in composite types, that enum variants are present, etc. We refer to this as "type match". This change proposes the addition of a new relocation variant/value that we intend to use for establishing this match relation. Differential Revision: https://reviews.llvm.org/D126838 --- llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp | 5 +- llvm/lib/Target/BPF/BPFCORE.h | 2 + .../BPF/CORE/intrinsic-typeinfo-type-match.ll | 103 +++++++++++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-type-match.ll diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp index 293b4cd..349cdd9 100644 --- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp +++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp @@ -332,6 +332,8 @@ bool BPFAbstractMemberAccess::IsPreserveDIAccessIndexCall(const CallInst *Call, report_fatal_error("Incorrect flag for llvm.bpf.preserve.type.info intrinsic"); if (Flag == BPFCoreSharedInfo::PRESERVE_TYPE_INFO_EXISTENCE) CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_EXISTENCE; + else if (Flag == BPFCoreSharedInfo::PRESERVE_TYPE_INFO_MATCH) + CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_MATCH; else CInfo.AccessIndex = BPFCoreSharedInfo::TYPE_SIZE; return true; @@ -933,7 +935,8 @@ MDNode *BPFAbstractMemberAccess::computeAccessKey(CallInst *Call, int64_t PatchImm; std::string AccessStr("0"); - if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_EXISTENCE) { + if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_EXISTENCE || + CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_MATCH) { PatchImm = 1; } else if (CInfo.AccessIndex == BPFCoreSharedInfo::TYPE_SIZE) { // typedef debuginfo type has size 0, get the eventual base type. diff --git a/llvm/lib/Target/BPF/BPFCORE.h b/llvm/lib/Target/BPF/BPFCORE.h index 0c50441..c9aa135 100644 --- a/llvm/lib/Target/BPF/BPFCORE.h +++ b/llvm/lib/Target/BPF/BPFCORE.h @@ -32,6 +32,7 @@ public: TYPE_SIZE, ENUM_VALUE_EXISTENCE, ENUM_VALUE, + TYPE_MATCH, MAX_FIELD_RELOC_KIND, }; @@ -46,6 +47,7 @@ public: enum PreserveTypeInfo : uint32_t { PRESERVE_TYPE_INFO_EXISTENCE = 0, PRESERVE_TYPE_INFO_SIZE, + PRESERVE_TYPE_INFO_MATCH, MAX_PRESERVE_TYPE_INFO_FLAG, }; diff --git a/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-type-match.ll b/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-type-match.ll new file mode 100644 index 0000000..8a8fd1e --- /dev/null +++ b/llvm/test/CodeGen/BPF/CORE/intrinsic-typeinfo-type-match.ll @@ -0,0 +1,103 @@ +; RUN: opt -O2 %s | llvm-dis > %t1 +; RUN: llc -filetype=asm -o - %t1 | FileCheck %s +; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s +; +; Source: +; enum AA { VAL = 100 }; +; typedef int (*func_t)(void); +; struct s2 { int a[10]; }; +; int test() { +; return __builtin_preserve_type_info(*(func_t *)0, 2) + +; __builtin_preserve_type_info(*(struct s2 *)0, 2) + +; __builtin_preserve_type_info(*(enum AA *)0, 2); +; } +; Compiler flag to generate IR: +; clang -target bpf -S -O2 -g -emit-llvm -Xclang -disable-llvm-passes t1.c + +source_filename = "t1.c" +target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" +target triple = "bpf" + +; Function Attrs: nounwind +define dso_local i32 @test() #0 !dbg !18 { + %1 = call i32 @llvm.bpf.preserve.type.info(i32 0, i64 2), !dbg !20, !llvm.preserve.access.index !8 + %2 = call i32 @llvm.bpf.preserve.type.info(i32 1, i64 2), !dbg !21, !llvm.preserve.access.index !22 + %3 = add i32 %1, %2, !dbg !28 + %4 = call i32 @llvm.bpf.preserve.type.info(i32 2, i64 2), !dbg !29, !llvm.preserve.access.index !3 + %5 = add i32 %3, %4, !dbg !30 + ret i32 %5, !dbg !31 +} + +; CHECK: r{{[0-9]+}} = 1 +; CHECK: r{{[0-9]+}} = 1 +; CHECK: r{{[0-9]+}} = 1 +; CHECK: exit + +; CHECK: .long 16 # BTF_KIND_TYPEDEF(id = 4) +; CHECK: .long 40 # BTF_KIND_STRUCT(id = 7) +; CHECK: .long 65 # BTF_KIND_ENUM(id = 10) + +; CHECK: .ascii ".text" # string offset=10 +; CHECK: .ascii "func_t" # string offset=16 +; CHECK: .byte 48 # string offset=23 +; CHECK: .ascii "s2" # string offset=40 +; CHECK: .ascii "AA" # string offset=65 + +; CHECK: .long 16 # FieldReloc +; CHECK-NEXT: .long 10 # Field reloc section string offset=10 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 23 +; CHECK-NEXT: .long 12 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 23 +; CHECK-NEXT: .long 12 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long 10 +; CHECK-NEXT: .long 23 +; CHECK-NEXT: .long 12 + +; Function Attrs: nounwind readnone +declare i32 @llvm.bpf.preserve.type.info(i32, i64) #1 + +attributes #0 = { nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { nounwind readnone } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!13, !14, !15, !16} +!llvm.ident = !{!17} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 15.0.0 (https://github.com/llvm/llvm-project.git 3d974661fd15612259d37f603ddf21df7ee0e428)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !7, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "t1.c", directory: "/tmp/tmp1", checksumkind: CSK_MD5, checksum: "53350e4a8003565f949c897f1fce8567") +!2 = !{!3} +!3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "AA", file: !1, line: 1, baseType: !4, size: 32, elements: !5) +!4 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned) +!5 = !{!6} +!6 = !DIEnumerator(name: "VAL", value: 100) +!7 = !{!8} +!8 = !DIDerivedType(tag: DW_TAG_typedef, name: "func_t", file: !1, line: 2, baseType: !9) +!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) +!10 = !DISubroutineType(types: !11) +!11 = !{!12} +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !{i32 7, !"Dwarf Version", i32 5} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{i32 1, !"wchar_size", i32 4} +!16 = !{i32 7, !"frame-pointer", i32 2} +!17 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project.git 3d974661fd15612259d37f603ddf21df7ee0e428)"} +!18 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 4, type: !10, scopeLine: 4, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !19) +!19 = !{} +!20 = !DILocation(line: 5, column: 10, scope: !18) +!21 = !DILocation(line: 6, column: 10, scope: !18) +!22 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s2", file: !1, line: 3, size: 320, elements: !23) +!23 = !{!24} +!24 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !22, file: !1, line: 3, baseType: !25, size: 320) +!25 = !DICompositeType(tag: DW_TAG_array_type, baseType: !12, size: 320, elements: !26) +!26 = !{!27} +!27 = !DISubrange(count: 10) +!28 = !DILocation(line: 5, column: 56, scope: !18) +!29 = !DILocation(line: 7, column: 10, scope: !18) +!30 = !DILocation(line: 6, column: 59, scope: !18) +!31 = !DILocation(line: 5, column: 3, scope: !18) -- 2.7.4