1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

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
This commit is contained in:
Yonghong Song 2021-05-06 16:31:30 -07:00
parent 9a8d215400
commit b2cd040e05
2 changed files with 111 additions and 0 deletions

View File

@ -872,6 +872,8 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call,
if (CInfo.Kind == BPFPreserveFieldInfoAI) {
InfoKind = CInfo.AccessIndex;
if (InfoKind == BPFCoreSharedInfo::FIELD_EXISTENCE)
PatchImm = 1;
break;
}

View File

@ -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)