Skip to content

Commit bba7338

Browse files
committed
BPF: generate BTF info for LD_imm64 loaded function pointer
For an example like below, extern int do_work(int); long bpf_helper(void *callback_fn); long prog() { return bpf_helper(&do_work); } The final generated codes look like: r1 = do_work ll call bpf_helper exit where we have debuginfo for do_work() extern function: !17 = !DISubprogram(name: "do_work", ...) This patch implemented to add additional checking in processing LD_imm64 operands for possible function pointers so BTF for bpf function do_work() can be properly generated. The original llvm function name processReloc() is renamed to processGlobalValue() to better reflect what the function is doing. Differential Revision: https://reviews.llvm.org/D100568
1 parent fd1ff5e commit bba7338

File tree

3 files changed

+86
-6
lines changed

3 files changed

+86
-6
lines changed

llvm/lib/Target/BPF/BTFDebug.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,13 +1030,16 @@ void BTFDebug::generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId,
10301030
FieldRelocTable[SecNameOff].push_back(FieldReloc);
10311031
}
10321032

1033-
void BTFDebug::processReloc(const MachineOperand &MO) {
1033+
void BTFDebug::processGlobalValue(const MachineOperand &MO) {
10341034
// check whether this is a candidate or not
10351035
if (MO.isGlobal()) {
10361036
const GlobalValue *GVal = MO.getGlobal();
10371037
auto *GVar = dyn_cast<GlobalVariable>(GVal);
1038-
if (!GVar)
1038+
if (!GVar) {
1039+
// Not a global variable. Maybe an extern function reference.
1040+
processFuncPrototypes(dyn_cast<Function>(GVal));
10391041
return;
1042+
}
10401043

10411044
if (!GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr) &&
10421045
!GVar->hasAttribute(BPFCoreSharedInfo::TypeIdAttr))
@@ -1087,12 +1090,12 @@ void BTFDebug::beginInstruction(const MachineInstr *MI) {
10871090
//
10881091
// If the insn is "r2 = LD_imm64 @<an TypeIdAttr global>",
10891092
// The LD_imm64 result will be replaced with a btf type id.
1090-
processReloc(MI->getOperand(1));
1093+
processGlobalValue(MI->getOperand(1));
10911094
} else if (MI->getOpcode() == BPF::CORE_MEM ||
10921095
MI->getOpcode() == BPF::CORE_ALU32_MEM ||
10931096
MI->getOpcode() == BPF::CORE_SHIFT) {
10941097
// relocation insn is a load, store or shift insn.
1095-
processReloc(MI->getOperand(3));
1098+
processGlobalValue(MI->getOperand(3));
10961099
} else if (MI->getOpcode() == BPF::JAL) {
10971100
// check extern function references
10981101
const MachineOperand &MO = MI->getOperand(0);

llvm/lib/Target/BPF/BTFDebug.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,9 @@ class BTFDebug : public DebugHandlerBase {
320320
/// Populating unprocessed type on demand.
321321
unsigned populateType(const DIType *Ty);
322322

323-
/// Process relocation instructions.
324-
void processReloc(const MachineOperand &MO);
323+
/// Process global variables referenced by relocation instructions
324+
/// and extern function references.
325+
void processGlobalValue(const MachineOperand &MO);
325326

326327
/// Emit common header of .BTF and .BTF.ext sections.
327328
void emitCommonHeader();
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
2+
; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
3+
;
4+
; Source code:
5+
; extern int do_work(int) __attribute__((section(".callback_fn")));
6+
; long bpf_helper(void *callback_fn);
7+
; long prog() {
8+
; return bpf_helper(&do_work);
9+
; }
10+
; Compilation flag:
11+
; clang -target bpf -O2 -g -S -emit-llvm test.c
12+
13+
; Function Attrs: nounwind
14+
define dso_local i64 @prog() local_unnamed_addr #0 !dbg !7 {
15+
entry:
16+
%call = tail call i64 @bpf_helper(i8* bitcast (i32 (i32)* @do_work to i8*)) #2, !dbg !11
17+
ret i64 %call, !dbg !12
18+
}
19+
20+
; CHECK: .long 0 # BTF_KIND_FUNC_PROTO(id = 4)
21+
; CHECK-NEXT: .long 218103809 # 0xd000001
22+
; CHECK-NEXT: .long 5
23+
; CHECK-NEXT: .long 0
24+
; CHECK-NEXT: .long 5
25+
; CHECK-NEXT: .long 51 # BTF_KIND_INT(id = 5)
26+
; CHECK-NEXT: .long 16777216 # 0x1000000
27+
; CHECK-NEXT: .long 4
28+
; CHECK-NEXT: .long 16777248 # 0x1000020
29+
; CHECK-NEXT: .long 55 # BTF_KIND_FUNC(id = 6)
30+
; CHECK-NEXT: .long 201326594 # 0xc000002
31+
; CHECK-NEXT: .long 4
32+
33+
; CHECK: .long 74 # BTF_KIND_DATASEC(id = 10)
34+
; CHECK-NEXT: .long 251658241 # 0xf000001
35+
; CHECK-NEXT: .long 0
36+
; CHECK-NEXT: .long 6
37+
; CHECK-NEXT: .long do_work
38+
; CHECK-NEXT: .long 0
39+
40+
; CHECK: .ascii "int" # string offset=51
41+
; CHECK: .ascii "do_work" # string offset=55
42+
; CHECK: .ascii ".callback_fn" # string offset=74
43+
44+
declare !dbg !13 dso_local i64 @bpf_helper(i8*) local_unnamed_addr #1
45+
46+
declare !dbg !17 dso_local i32 @do_work(i32) #1 section ".callback_fn"
47+
48+
attributes #0 = { nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
49+
attributes #1 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
50+
attributes #2 = { nounwind }
51+
52+
!llvm.dbg.cu = !{!0}
53+
!llvm.module.flags = !{!3, !4, !5}
54+
!llvm.ident = !{!6}
55+
56+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git aa382ed8a38d5efa118e1b2617544f5c253658a9)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
57+
!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/btf/core")
58+
!2 = !{}
59+
!3 = !{i32 7, !"Dwarf Version", i32 4}
60+
!4 = !{i32 2, !"Debug Info Version", i32 3}
61+
!5 = !{i32 1, !"wchar_size", i32 4}
62+
!6 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git aa382ed8a38d5efa118e1b2617544f5c253658a9)"}
63+
!7 = distinct !DISubprogram(name: "prog", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
64+
!8 = !DISubroutineType(types: !9)
65+
!9 = !{!10}
66+
!10 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
67+
!11 = !DILocation(line: 4, column: 12, scope: !7)
68+
!12 = !DILocation(line: 4, column: 5, scope: !7)
69+
!13 = !DISubprogram(name: "bpf_helper", scope: !1, file: !1, line: 2, type: !14, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
70+
!14 = !DISubroutineType(types: !15)
71+
!15 = !{!10, !16}
72+
!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
73+
!17 = !DISubprogram(name: "do_work", scope: !1, file: !1, line: 1, type: !18, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2)
74+
!18 = !DISubroutineType(types: !19)
75+
!19 = !{!20, !20}
76+
!20 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)

0 commit comments

Comments
 (0)