[llvm] 605c811 - BPF: fix FIELD_EXISTS relocation with array subscripts
Yonghong Song via llvm-commits
llvm-commits at lists.llvm.org
Thu May 6 22:42:36 PDT 2021
Author: Yonghong Song
Date: 2021-05-06T22:37:02-07:00
New Revision: 605c811d2b0f71c576740c9a54629804353bf67a
URL: https://github.com/llvm/llvm-project/commit/605c811d2b0f71c576740c9a54629804353bf67a
DIFF: https://github.com/llvm/llvm-project/commit/605c811d2b0f71c576740c9a54629804353bf67a.diff
LOG: BPF: fix FIELD_EXISTS relocation with array subscripts
Lorenz Bauer reported an issue in bpf mailing list ([1]) where
for FIELD_EXISTS relocation, if the object is an array subscript,
the patched immediate is the object offset from the base address,
instead of 1.
Currently in BPF AbstractMemberAccess pass, the final offset
from the base address is the patched offset except FIELD_EXISTS
which is 1 unconditionally. In this particular case, the last
data structure access is not a field (struct/union offset)
so it didn't hit the place to set patched immediate to be 1.
This patch fixed the issue by checking the relocation type.
If the type is FIELD_EXISTS, just set to 1.
Tested by modifying some bpf selftests, libbpf is okay with
such types with FIELD_EXISTS relocation.
[1] https://lore.kernel.org/bpf/CACAyw99n-cMEtVst7aK-3BfHb99GMEChmRLCvhrjsRpHhPrtvA@mail.gmail.com/
Differential Revision: https://reviews.llvm.org/D102036
Added:
llvm/test/CodeGen/BPF/CORE/intrinsic-fieldinfo-existence-4.ll
Modified:
llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
index cd994a9c83658..a12ef395b00b2 100644
--- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
+++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
@@ -872,6 +872,8 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
if (CInfo.Kind == BPFPreserveFieldInfoAI) {
InfoKind = CInfo.AccessIndex;
+ if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE)
+ PatchImm = 1;
break;
}
diff --git a/llvm/test/CodeGen/BPF/CORE/intrinsic-fieldinfo-existence-4.ll b/llvm/test/CodeGen/BPF/CORE/intrinsic-fieldinfo-existence-4.ll
new file mode 100644
index 0000000000000..eb2b649895d7c
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/intrinsic-fieldinfo-existence-4.ll
@@ -0,0 +1,109 @@
+; RUN: opt -O2 -mtriple=bpf-pc-linux %s | llvm-dis > %t1
+; RUN: llc -filetype=asm -o - %t1 | FileCheck %s
+; RUN: llc -mattr=+alu32 -filetype=asm -o - %t1 | FileCheck %s
+; Source code:
+; #define BPF_FIELD_EXISTS 2
+; unsigned test1() {
+; struct t {
+; int val;
+; } bar;
+; return __builtin_preserve_field_info((&bar)[1], BPF_FIELD_EXISTS);
+; }
+; Compilation flag:
+; clang -target bpf -O2 -g -S -emit-llvm -Xclang -disable-llvm-passes test.c
+
+%struct.t = type { i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @test1() #0 !dbg !6 {
+entry:
+ %bar = alloca %struct.t, align 4
+ %0 = bitcast %struct.t* %bar to i8*, !dbg !20
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #5, !dbg !20
+ call void @llvm.dbg.declare(metadata %struct.t* %bar, metadata !11, metadata !DIExpression()), !dbg !21
+ %1 = call %struct.t* @llvm.preserve.array.access.index.p0s_struct.ts.p0s_struct.ts(%struct.t* %bar, i32 0, i32 1), !dbg !22, !llvm.preserve.access.index !4
+ %2 = call i32 @llvm.bpf.preserve.field.info.p0s_struct.ts(%struct.t* %1, i64 2), !dbg !23
+ %3 = bitcast %struct.t* %bar to i8*, !dbg !24
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %3) #5, !dbg !24
+ ret i32 %2, !dbg !25
+}
+
+; CHECK: r0 = 1
+; CHECK-NEXT: exit
+
+; CHECK: .long 26 # BTF_KIND_STRUCT(id = 4)
+; CHECK-NEXT: .long 67108865 # 0x4000001
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long 28
+; CHECK-NEXT: .long 5
+; CHECK-NEXT: .long 0 # 0x0
+; CHECK-NEXT: .long 32 # BTF_KIND_INT(id = 5)
+; CHECK-NEXT: .long 16777216 # 0x1000000
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long 16777248 # 0x1000020
+
+; CHECK: .byte 116 # string offset=26
+; CHECK: .ascii "val" # string offset=28
+; CHECK: .ascii "int" # string offset=32
+; CHECK: .byte 49 # string offset=36
+
+; CHECK: .long 16 # FieldReloc
+; CHECK-NEXT: .long {{[0-9]+}} # Field reloc section string
+; CHECK-NEXT: .long 1
+; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
+; CHECK-NEXT: .long 4
+; CHECK-NEXT: .long 36
+; CHECK-NEXT: .long 2
+
+; Function Attrs: argmemonly nofree nosync nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #2
+
+; Function Attrs: nofree nosync nounwind readnone willreturn
+declare %struct.t* @llvm.preserve.array.access.index.p0s_struct.ts.p0s_struct.ts(%struct.t*, i32 immarg, i32 immarg) #3
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.bpf.preserve.field.info.p0s_struct.ts(%struct.t*, i64 immarg) #4
+
+; Function Attrs: argmemonly nofree nosync nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+attributes #0 = { nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { argmemonly nofree nosync nounwind willreturn }
+attributes #2 = { nofree nosync nounwind readnone speculatable willreturn }
+attributes #3 = { nofree nosync nounwind readnone willreturn }
+attributes #4 = { nounwind readnone }
+attributes #5 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!15, !16, !17, !18}
+!llvm.ident = !{!19}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 2e0ee68dc85c0a2b7e65e489a60ab363393b06a8)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64)
+!5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", scope: !6, file: !1, line: 3, size: 32, elements: !12)
+!6 = distinct !DISubprogram(name: "test1", scope: !1, file: !1, line: 2, type: !7, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9}
+!9 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!10 = !{!11}
+!11 = !DILocalVariable(name: "bar", scope: !6, file: !1, line: 5, type: !5)
+!12 = !{!13}
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "val", scope: !5, file: !1, line: 4, baseType: !14, size: 32)
+!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!15 = !{i32 7, !"Dwarf Version", i32 4}
+!16 = !{i32 2, !"Debug Info Version", i32 3}
+!17 = !{i32 1, !"wchar_size", i32 4}
+!18 = !{i32 7, !"frame-pointer", i32 2}
+!19 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 2e0ee68dc85c0a2b7e65e489a60ab363393b06a8)"}
+!20 = !DILocation(line: 3, column: 3, scope: !6)
+!21 = !DILocation(line: 5, column: 5, scope: !6)
+!22 = !DILocation(line: 6, column: 40, scope: !6)
+!23 = !DILocation(line: 6, column: 10, scope: !6)
+!24 = !DILocation(line: 7, column: 1, scope: !6)
+!25 = !DILocation(line: 6, column: 3, scope: !6)
More information about the llvm-commits
mailing list