-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce builtin to get percpu kernel data
There exist "percpu" global variables in the kernel which contain a distinct value for each CPU. In BPF, access to these variables is done via the bpf_per_cpu_ptr and bpf_this_cpu_ptr helpers. Both accept a pointer to a percpu ksym and the former also accepts a CPU number. The ksym is an extern variable with a BTF entry matching the BTF of the corresponding kernel variable. Since we now use libbpf to do the loading, it is sufficient to emit a global variable declaration with a proper BTF and libbpf will take care of the rest. Introduce new bpftrace builtin percpu_kaddr to access the percpu data. The helper has two forms: percpu_kaddr("symbol_name") <- uses bpf_this_cpu_ptr percpu_kaddr("symbol_name", N) <- uses bpf_per_cpu_ptr where N is the CPU number. The former variant retrieves the value for the current CPU. A tricky part is that bpf_per_cpu_ptr may return NULL if the supplied CPU number is higher than the number of the CPUs. The BPF program should perform a NULL-check on the returned value, otherwise it is rejected by the verifier. In practice, this only happens if pointer arithmetics is used (i.e. a struct field is accessed). Since it is quite complex to detect a missing NULL-check in bpftrace, we instead let verifier do it and just display the potential verifier error in a nicer manner. The check if the global variable exists is done in semantic analyser to get better error highlighting. Therefore, for testing the new builtin in semantic analyser tests, we need to add a symbol (process_counts) into tests/data/data_source.c to get it into our mock BTF. The problem here is that pahole places only percpu variables into BTF (and none other) so the symbol must be in the ".data..percpu" section. To do that, we need to make data_source.o a relocatable file (using compiler's -c option), otherwise the linker would put the symbol back to ".data". This in turn breaks DWARF generation which seems to need a linked binary so we link data_source.o into data_source during the DWARF generation step.
- Loading branch information
1 parent
14f1e5c
commit efb61f6
Showing
19 changed files
with
373 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#include "common.h" | ||
|
||
namespace bpftrace { | ||
namespace test { | ||
namespace codegen { | ||
|
||
TEST(codegen, call_percpu_kaddr) | ||
{ | ||
test("BEGIN { percpu_kaddr(\"process_counts\", 0); }", NAME); | ||
} | ||
|
||
TEST(codegen, call_percpu_kaddr_this_cpu) | ||
{ | ||
test("BEGIN { percpu_kaddr(\"process_counts\"); }", NAME); | ||
} | ||
|
||
} // namespace codegen | ||
} // namespace test | ||
} // namespace bpftrace |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
; ModuleID = 'bpftrace' | ||
source_filename = "bpftrace" | ||
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128" | ||
target triple = "bpf-pc-linux" | ||
|
||
%"struct map_t" = type { ptr, ptr } | ||
%"struct map_t.0" = type { ptr, ptr, ptr, ptr } | ||
|
||
@LICENSE = global [4 x i8] c"GPL\00", section "license" | ||
@ringbuf = dso_local global %"struct map_t" zeroinitializer, section ".maps", !dbg !0 | ||
@event_loss_counter = dso_local global %"struct map_t.0" zeroinitializer, section ".maps", !dbg !16 | ||
@process_counts = external global i64, section ".ksyms", !dbg !36 | ||
|
||
; Function Attrs: nounwind | ||
declare i64 @llvm.bpf.pseudo(i64 %0, i64 %1) #0 | ||
|
||
define i64 @BEGIN_1(ptr %0) section "s_BEGIN_1" !dbg !41 { | ||
entry: | ||
%per_cpu_ptr = call ptr inttoptr (i64 153 to ptr)(ptr @process_counts, i64 0) | ||
%1 = ptrtoint ptr %per_cpu_ptr to i64 | ||
ret i64 0 | ||
} | ||
|
||
attributes #0 = { nounwind } | ||
|
||
!llvm.dbg.cu = !{!38} | ||
!llvm.module.flags = !{!40} | ||
|
||
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) | ||
!1 = distinct !DIGlobalVariable(name: "ringbuf", linkageName: "global", scope: !2, file: !2, type: !3, isLocal: false, isDefinition: true) | ||
!2 = !DIFile(filename: "bpftrace.bpf.o", directory: ".") | ||
!3 = !DICompositeType(tag: DW_TAG_structure_type, scope: !2, file: !2, size: 128, elements: !4) | ||
!4 = !{!5, !11} | ||
!5 = !DIDerivedType(tag: DW_TAG_member, name: "type", scope: !2, file: !2, baseType: !6, size: 64) | ||
!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64) | ||
!7 = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 864, elements: !9) | ||
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | ||
!9 = !{!10} | ||
!10 = !DISubrange(count: 27, lowerBound: 0) | ||
!11 = !DIDerivedType(tag: DW_TAG_member, name: "max_entries", scope: !2, file: !2, baseType: !12, size: 64, offset: 64) | ||
!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) | ||
!13 = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 8388608, elements: !14) | ||
!14 = !{!15} | ||
!15 = !DISubrange(count: 262144, lowerBound: 0) | ||
!16 = !DIGlobalVariableExpression(var: !17, expr: !DIExpression()) | ||
!17 = distinct !DIGlobalVariable(name: "event_loss_counter", linkageName: "global", scope: !2, file: !2, type: !18, isLocal: false, isDefinition: true) | ||
!18 = !DICompositeType(tag: DW_TAG_structure_type, scope: !2, file: !2, size: 256, elements: !19) | ||
!19 = !{!20, !25, !30, !33} | ||
!20 = !DIDerivedType(tag: DW_TAG_member, name: "type", scope: !2, file: !2, baseType: !21, size: 64) | ||
!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64) | ||
!22 = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 64, elements: !23) | ||
!23 = !{!24} | ||
!24 = !DISubrange(count: 2, lowerBound: 0) | ||
!25 = !DIDerivedType(tag: DW_TAG_member, name: "max_entries", scope: !2, file: !2, baseType: !26, size: 64, offset: 64) | ||
!26 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !27, size: 64) | ||
!27 = !DICompositeType(tag: DW_TAG_array_type, baseType: !8, size: 32, elements: !28) | ||
!28 = !{!29} | ||
!29 = !DISubrange(count: 1, lowerBound: 0) | ||
!30 = !DIDerivedType(tag: DW_TAG_member, name: "key", scope: !2, file: !2, baseType: !31, size: 64, offset: 128) | ||
!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !32, size: 64) | ||
!32 = !DIBasicType(name: "int32", size: 32, encoding: DW_ATE_signed) | ||
!33 = !DIDerivedType(tag: DW_TAG_member, name: "value", scope: !2, file: !2, baseType: !34, size: 64, offset: 192) | ||
!34 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !35, size: 64) | ||
!35 = !DIBasicType(name: "int64", size: 64, encoding: DW_ATE_signed) | ||
!36 = !DIGlobalVariableExpression(var: !37, expr: !DIExpression()) | ||
!37 = distinct !DIGlobalVariable(name: "process_counts", linkageName: "global", scope: !2, file: !2, type: !35, isLocal: false, isDefinition: true) | ||
!38 = distinct !DICompileUnit(language: DW_LANG_C, file: !2, producer: "bpftrace", isOptimized: false, runtimeVersion: 0, emissionKind: LineTablesOnly, globals: !39) | ||
!39 = !{!0, !16, !36} | ||
!40 = !{i32 2, !"Debug Info Version", i32 3} | ||
!41 = distinct !DISubprogram(name: "BEGIN_1", linkageName: "BEGIN_1", scope: !2, file: !2, type: !42, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !38, retainedNodes: !46) | ||
!42 = !DISubroutineType(types: !43) | ||
!43 = !{!35, !44} | ||
!44 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !45, size: 64) | ||
!45 = !DIBasicType(name: "int8", size: 8, encoding: DW_ATE_signed) | ||
!46 = !{!47} | ||
!47 = !DILocalVariable(name: "ctx", arg: 1, scope: !41, file: !2, type: !44) |
Oops, something went wrong.