summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/BPF/BTFDebug.cpp
AgeCommit message (Collapse)Author
2025-10-22[BPF] Do not emit names for PTR, CONST, VOLATILE and RESTRICT BTF types ↵Michal R
(#163174) We currently raise a warning in `print_btf.py` when any of these types have a name. Linux kernel doesn't allow names in these types either.[0] However, there is nothing stopping frontends from giving names to these types. To make sure that they are always anonymous, explicitly skip the name emission. [0] https://elixir.bootlin.com/linux/v6.17.1/source/kernel/bpf/btf.c#L2586
2025-10-20[BPF] Support for `DW_TAG_variant_part` in BTF generation (#155783)Michal R
Variant part, represented by `DW_TAG_variant_part` is a structure with a discriminant and different variants, from which only one can be active and valid at the same time. The discriminant is the main difference between variant parts and unions represented by `DW_TAG_union` type. Variant parts are used by Rust enums, which look like: ```rust pub enum MyEnum { First { a: u32, b: i32 }, Second(u32), } ``` This type's debug info is the following `DICompositeType` with `DW_TAG_structure_type` tag: ```llvm !4 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyEnum", scope: !2, file: !5, size: 96, align: 32, flags: DIFlagPublic, elements: !6, templateParams: !16, identifier: "faba668fd9f71e9b7cf3b9ac5e8b93cb") ``` With one element being also a `DICompositeType`, but with `DW_TAG_variant_part` tag: ```llvm !6 = !{!7} !7 = !DICompositeType(tag: DW_TAG_variant_part, scope: !4, file: !5, size: 96, align: 32, elements: !8, templateParams: !16, identifier: "e4aee046fc86d111657622fdcb8c42f7", discriminator: !21) ``` Which has a discriminator: ```llvm !21 = !DIDerivedType(tag: DW_TAG_member, scope: !4, file: !5, baseType: !13, size: 32, align: 32, flags: DIFlagArtificial) ``` Which then holds different variants as `DIDerivedType` elements with `DW_TAG_member` tag: ```llvm !8 = !{!9, !17} !9 = !DIDerivedType(tag: DW_TAG_member, name: "First", scope: !7, file: !5, baseType: !10, size: 96, align: 32, extraData: i32 0) !10 = !DICompositeType(tag: DW_TAG_structure_type, name: "First", scope: !4, file: !5, size: 96, align: 32, flags: DIFlagPublic, elements: !11, templateParams: !16, identifier: "cc7748c842e275452db4205b190c8ff7") !11 = !{!12, !14} !12 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !10, file: !5, baseType: !13, size: 32, align: 32, offset: 32, flags: DIFlagPublic) !13 = !DIBasicType(name: "u32", size: 32, encoding: DW_ATE_unsigned) !14 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !10, file: !5, baseType: !15, size: 32, align: 32, offset: 64, flags: DIFlagPublic) !15 = !DIBasicType(name: "i32", size: 32, encoding: DW_ATE_signed) !16 = !{} !17 = !DIDerivedType(tag: DW_TAG_member, name: "Second", scope: !7, file: !5, baseType: !18, size: 96, align: 32, extraData: i32 1) !18 = !DICompositeType(tag: DW_TAG_structure_type, name: "Second", scope: !4, file: !5, size: 96, align: 32, flags: DIFlagPublic, elements: !19, templateParams: !16, identifier: "a2094b1381f3082d504fbd0903aa7c06") !19 = !{!20} !20 = !DIDerivedType(tag: DW_TAG_member, name: "__0", scope: !18, file: !5, baseType: !13, size: 32, align: 32, offset: 32, flags: DIFlagPublic) ``` BPF backend was assuming that all the elements of any `DICompositeType` have tag `DW_TAG_member` and are instances of `DIDerivedType`. However, the single element of the outer composite type `!4` has tag `DW_TAG_variant_part` and is an instance of `DICompositeType`. The unconditional call of `cast<DIDerivedType>` on all elements was causing an assertion failure when any Rust code with enums was compiled to the BPF target. Fix that by: * Handling `DW_TAG_variant_part` in `visitStructType`. * Replacing unconditional call of `cast<DIDerivedType>` over `DICompositeType` elements with a `switch` statement, handling both `DW_TAG_member` and `DW_TAG_variant_part` and casting the element to an appropriate type (`DIDerivedType` or `DICompositeType`). Fixes: https://github.com/llvm/llvm-project/issues/155778
2025-09-06[BPF] Remove an unnecessary cast (NFC) (#157230)Kazu Hirata
getZExtValue() already returns uint64_t.
2025-07-28[BPF] Visit nested map array during BTF generation (#150608)Mahé
Fixes missing inner map struct type definitions [^1]. We should visit the type of nested array of maps like we do for global maps. This patch adds a boolean to convey the information to visitTypeEntry and visitDerivedType that the pointee is a map definition and should be treated as such. It ressembles and works with commit 0d21c956a5c1 ("[BPF] Handle nested wrapper structs in BPF map definition traversal (#144097)") which focused on directly nested wrapper structs. Before that patch, this ARRAY_OF_MAPS definition would lead to the BTF information include the 'missing_type' as "FWD 'missing_type' fwd_kind=struct": struct missing_type { uint64_t foo; }; struct { __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); [...] __array( values, struct { [...] __type(value, struct missing_type); }); } map SEC(".maps"); Which lead to errors while trying to load the map: libbpf: map 'outer_map.inner': can't determine value size for type [N]: -22. To solve this issue, users had to use the struct in a dummy variable or in a dummy function for the BTF to be generated correctly [^2]. [^1]: https://lore.kernel.org/netdev/aH_cGvgC20iD8qs9@gmail.com/T/#u [^2]: https://github.com/cilium/ebpf/discussions/1658#discussioncomment-12491339 --------- Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com> Co-authored-by: Eduard Zingerman <eddyz87@gmail.com>
2025-07-25MCSectionELF: Remove classofFangrui Song
The object file format specific derived classes are used in context like MCStreamer and MCObjectTargetWriter where the type is statically known. We don't use isa/dyn_cast and we want to eliminate MCSection::SectionVariant in the base class.
2025-06-20[BPF] Handle nested wrapper structs in BPF map definition traversal (#144097)Michal Rostecki
In Aya/Rust, BPF map definitions are nested in two nested types: * A struct representing the map type (e.g., `HashMap`, `RingBuf`) that provides methods for interacting with the map type (e.g. `HashMap::get`, `RingBuf::reserve`). * An `UnsafeCell`, which informs the Rust compiler that the type is thread-safe and can be safely mutated even as a global variable. The kernel guarantees map operation safety. This leads to a type hierarchy like: ```rust pub struct HashMap<K, V, const M: usize, const F: usize = 0>( core::cell::UnsafeCell<HashMapDef<K, V, M, F>>, ); const BPF_MAP_TYPE_HASH: usize = 1; pub struct HashMapDef<K, V, const M: usize, const F: usize = 0> { r#type: *const [i32; BPF_MAP_TYPE_HASH], key: *const K, value: *const V, max_entries: *const [i32; M], map_flags: *const [i32; F], } ``` Then used in the BPF program code as a global variable: ```rust #[link_section = ".maps"] static HASH_MAP: HashMap<u32, u32, 1337> = HashMap::new(); ``` Which is an equivalent of the following BPF map definition in C: ```c #define BPF_MAP_TYPE_HASH 1 struct { int (*type)[BPF_MAP_TYPE_HASH]; typeof(int) *key; typeof(int) *value; int (*max_entries)[1337]; } map_1 __attribute__((section(".maps"))); ``` Accessing the actual map definition requires traversing: ``` HASH_MAP -> __0 -> value ``` Previously, the BPF backend only visited the pointee types of the outermost struct, and didn’t descend into inner wrappers. This caused issues when the key/value types were custom structs: ```rust // Define custom structs for key and values. pub struct MyKey(u32); pub struct MyValue(u32); #[link_section = ".maps"] #[export_name = "HASH_MAP"] pub static HASH_MAP: HashMap<MyKey, MyValue, 10> = HashMap::new(); ``` These types weren’t fully visited and appeared in BTF as forward declarations: ``` #30: <FWD> 'MyKey' kind:struct #31: <FWD> 'MyValue' kind:struct ``` The fix is to enhance `visitMapDefType` to recursively visit inner composite members. If a member is a composite type (likely a wrapper), it is now also visited using `visitMapDefType`, ensuring that the pointee types of the innermost stuct members, like `MyKey` and `MyValue`, are fully resolved in BTF. With this fix, the correct BTF entries are emitted: ``` #6: <STRUCT> 'MyKey' sz:4 n:1 #00 '__0' off:0 --> [7] #7: <INT> 'u32' bits:32 off:0 #8: <PTR> --> [9] #9: <STRUCT> 'MyValue' sz:4 n:1 #00 '__0' off:0 --> [7] ``` Fixes: #143361
2025-06-10[BPF] Use heterogeneous lookup with std::map (NFC) (#143395)Kazu Hirata
2025-05-28[BPF] Allow struct pointee member btf generation with annotations (#141719)yonghong-song
Currently, to avoid generating too much BTF types, for a struct type like ``` struct foo { int val; struct bar *ptr; }; ``` if the BTF generation reaches 'struct foo', it will not generate actual type for 'struct bar' and instead a forward decl is generated. The 'struct bar' is actual generated in BTF unless it is reached through a non-struct pointer member. Such a limitation forces bpf developer to hack and workaround this problem. See [1] and [2]. For example in [1], we have ``` struct map_value { struct prog_test_ref_kfunc *not_kptr; struct prog_test_ref_kfunc __kptr *val; struct node_data __kptr *node; }; ``` The BTF type for 'struct node_data' is not generated. Note that we have a '__kptr' annotation. Similar problem for [2] with a '__uptr' annotation. Note that the issue in [1] has been resolved later but the hack in [2] is still needed. This patch relaxed the struct type (with struct pointer member) BTF generation if the struct pointer has a btf_type_tag annotation. [1] https://lore.kernel.org/r/20230310230743.2320707-4-davemarchevsky@fb.com [2] https://lore.kernel.org/r/20241023234759.860539-9-martin.lau@linux.dev
2025-05-27[BPF] Handle traps with kfunc call __bpf_trap (#131731)yonghong-song
Currently, middle-end generates 'unreachable' insn if the compiler feels the code is indeed unreachable or the code becomes invalid due to some optimizaiton (e.g. code optimization with uninitialized variables). Right now BPF backend ignores 'unreachable' insn during selectiondag lowering. For cases where 'unreachable' is due to invalid code transformation, such a signal will be missed. Later on, users needs some effort to debug it which impacts developer productivity. This patch enabled selectiondag lowering for 'unreachable' insn. Previous attempt ([1]) tries to have a backend IR pass to filter out 'unreachable' insns in a number of cases. But such pattern matching may misalign with future middle-end optimization with 'unreachable' insns. This patch takes a different approach. The 'unreachable' insn is lowered with special encoding in bpf object file and verifier will do proper verification for the bpf prog. More specifically, the 'unreachable' insn is replaced by a __bpf_trap() function. This function will be a kfunc (in ".ksyms" section) with a weak attribute, but does not have definition. The actual kfunc definition is expected to be in kernel. The __bpf_trap() extern function is also encoded in BTF. The name __bpf_trap() is chosen to satisfy reserved identifier requirement. Besides the uninitialized variable case, the builtin function '__builtin_trap' can also generate kfunc __bpf_trap(). For example in [3], we have ``` # define __bpf_unreachable() __builtin_trap() ``` If the compiler didn't remove __builtin_trap() during middle-end optimization, compilation will fail. With this patch, compilation will not fail and __builtin_trap() is converted to __bpf_trap() kfunc. The eventual failure will be in verifier instead of llvm compilation. To keep compilation time failure, user can add an option like `-ftrap-function=<something>`. I tested this patch on bpf selftests and all tests are passed. I also tried original example in [2] and the code looks like below: ``` ; { 0: bf 16 00 00 00 00 00 00 r6 = r1 ; bpf_printk("Start"); 1: 18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0x0 ll 0000000000000008: R_BPF_64_64 .rodata 3: b4 02 00 00 06 00 00 00 w2 = 0x6 4: 85 00 00 00 06 00 00 00 call 0x6 ; DEFINE_FUNC_CTX_POINTER(data) 5: 61 61 4c 00 00 00 00 00 w1 = *(u32 *)(r6 + 0x4c) ; bpf_printk("pre ipv6_hdrlen_offset"); 6: 18 01 00 00 06 00 00 00 00 00 00 00 00 00 00 00 r1 = 0x6 ll 0000000000000030: R_BPF_64_64 .rodata 8: b4 02 00 00 17 00 00 00 w2 = 0x17 9: 85 00 00 00 06 00 00 00 call 0x6 10: 85 10 00 00 ff ff ff ff call -0x1 0000000000000050: R_BPF_64_32 __bpf_trap 11: 95 00 00 00 00 00 00 00 exit <END> ``` Eventually kernel verifier will emit the following logs: ``` 10: (85) call __bpf_trap#74479 unexpected __bpf_trap() due to uninitialized variable? ``` In another internal sched-ext bpf prog, with the patch we have bpf code: ``` Disassembly of section .text: 0000000000000000 <scx_storage_init_single>: ; { 0: bc 13 00 00 00 00 00 00 w3 = w1 1: b4 01 00 00 00 00 00 00 w1 = 0x0 ; const u32 zero = 0; ... 0000000000003a80 <create_dom>: ; { 1872: bc 16 00 00 00 00 00 00 w6 = w1 ; bpf_printk("dom_id %d", dom_id); 1873: 18 01 00 00 3f 00 00 00 00 00 00 00 00 00 00 00 r1 = 0x3f ll 0000000000003a88: R_BPF_64_64 .rodata 1875: b4 02 00 00 0a 00 00 00 w2 = 0xa 1876: bc 63 00 00 00 00 00 00 w3 = w6 1877: 85 00 00 00 06 00 00 00 call 0x6 ; ret = scx_bpf_create_dsq(dom_id, 0); 1878: bc 61 00 00 00 00 00 00 w1 = w6 1879: b4 02 00 00 00 00 00 00 w2 = 0x0 1880: 85 10 00 00 ff ff ff ff call -0x1 0000000000003ac0: R_BPF_64_32 scx_bpf_create_dsq ; domc->node_cpumask = node_data[node_id]; 1881: 85 10 00 00 ff ff ff ff call -0x1 0000000000003ac8: R_BPF_64_32 __bpf_trap 1882: 95 00 00 00 00 00 00 00 exit <END> ``` The verifier can easily report the error too. A bpf flag `-bpf-disable-trap-unreachable` is introduced to disable trapping for 'unreachable' or __builtin_trap. [1] https://github.com/llvm/llvm-project/pull/126858 [2] https://github.com/msune/clang_bpf/blob/main/Makefile#L3 [3] https://github.com/libbpf/libbpf/blob/master/src/bpf_helpers.h
2025-03-14[BPF] Avoid repeated hash lookups (NFC) (#131265)Kazu Hirata
Co-authored-by: Nikita Popov <github@npopov.com>
2025-03-05[BPF] Avoid repeated map lookups (NFC) (#129820)Kazu Hirata
2024-11-09[Target] Migrate away from PointerUnion::{is,get,dyn_cast} (NFC) (#115623)Kazu Hirata
Note that PointerUnion::{is,get,dyn_cast} have been soft deprecated in PointerUnion.h: // FIXME: Replace the uses of is(), get() and dyn_cast() with // isa<T>, cast<T> and the llvm::dyn_cast<T>
2024-10-22[BPF] Avoid repeated map lookups (NFC) (#113247)Kazu Hirata
2024-09-24[BPF] Do atomic_fetch_*() pattern matching with memory ordering (#107343)yonghong-song
Three commits in this pull request: commit 1: implement pattern matching for memory ordering seq_cst, acq_rel, release, acquire and monotonic. Specially, for monotonic memory ordering (relaxed memory model), if no return value is used, locked insn is used. commit 2: add support to handle dwarf atomic modifier in BTF generation. Actually atomic modifier is ignored in BTF. commit 3: add tests for new atomic ordering support and BTF support with _Atomic type. I removed RFC tag as now patch sets are in reasonable states. For atomic fetch_and_*() operations, do pattern matching with memory ordering seq_cst, acq_rel, release, acquire and monotonic (relaxed). For fetch_and_*() operations with seq_cst/acq_rel/release/acquire ordering, atomic_fetch_*() instructions are generated. For monotonic ordering, locked insns are generated if return value is not used. Otherwise, atomic_fetch_*() insns are used. The main motivation is to resolve the kernel issue [1]. The following are memory ordering are supported: seq_cst, acq_rel, release, acquire, relaxed Current gcc style __sync_fetch_and_*() operations are all seq_cst. To use explicit memory ordering, the _Atomic type is needed. The following is an example: ``` $ cat test.c \#include <stdatomic.h> void f1(_Atomic int *i) { (void)__c11_atomic_fetch_and(i, 10, memory_order_relaxed); } void f2(_Atomic int *i) { (void)__c11_atomic_fetch_and(i, 10, memory_order_acquire); } void f3(_Atomic int *i) { (void)__c11_atomic_fetch_and(i, 10, memory_order_seq_cst); } $ cat run.sh clang -I/home/yhs/work/bpf-next/tools/testing/selftests/bpf -O2 --target=bpf -c test.c -o test.o && llvm-objdum p -d test.o $ ./run.sh test.o: file format elf64-bpf Disassembly of section .text: 0000000000000000 <f1>: 0: b4 02 00 00 0a 00 00 00 w2 = 0xa 1: c3 21 00 00 50 00 00 00 lock *(u32 *)(r1 + 0x0) &= w2 2: 95 00 00 00 00 00 00 00 exit 0000000000000018 <f2>: 3: b4 02 00 00 0a 00 00 00 w2 = 0xa 4: c3 21 00 00 51 00 00 00 w2 = atomic_fetch_and((u32 *)(r1 + 0x0), w2) 5: 95 00 00 00 00 00 00 00 exit 0000000000000030 <f3>: 6: b4 02 00 00 0a 00 00 00 w2 = 0xa 7: c3 21 00 00 51 00 00 00 w2 = atomic_fetch_and((u32 *)(r1 + 0x0), w2) 8: 95 00 00 00 00 00 00 00 exit ``` The following is another example where return value is used: ``` $ cat test1.c \#include <stdatomic.h> int f1(_Atomic int *i) { return __c11_atomic_fetch_and(i, 10, memory_order_relaxed); } int f2(_Atomic int *i) { return __c11_atomic_fetch_and(i, 10, memory_order_acquire); } int f3(_Atomic int *i) { return __c11_atomic_fetch_and(i, 10, memory_order_seq_cst); } $ cat run.sh clang -I/home/yhs/work/bpf-next/tools/testing/selftests/bpf -O2 --target=bpf -c test1.c -o test1.o && llvm-objdump -d test1.o $ ./run.sh test.o: file format elf64-bpf Disassembly of section .text: 0000000000000000 <f1>: 0: b4 00 00 00 0a 00 00 00 w0 = 0xa 1: c3 01 00 00 51 00 00 00 w0 = atomic_fetch_and((u32 *)(r1 + 0x0), w0) 2: 95 00 00 00 00 00 00 00 exit 0000000000000018 <f2>: 3: b4 00 00 00 0a 00 00 00 w0 = 0xa 4: c3 01 00 00 51 00 00 00 w0 = atomic_fetch_and((u32 *)(r1 + 0x0), w0) 5: 95 00 00 00 00 00 00 00 exit 0000000000000030 <f3>: 6: b4 00 00 00 0a 00 00 00 w0 = 0xa 7: c3 01 00 00 51 00 00 00 w0 = atomic_fetch_and((u32 *)(r1 + 0x0), w0) 8: 95 00 00 00 00 00 00 00 exit ``` You can see that for relaxed memory ordering, if return value is used, atomic_fetch_and() insn is used. Otherwise, if return value is not used, locked insn is used. Here is another example with global _Atomic variable: ``` $ cat test3.c \#include <stdatomic.h> _Atomic int i; void f1(void) { (void)__c11_atomic_fetch_and(&i, 10, memory_order_relaxed); } void f2(void) { (void)__c11_atomic_fetch_and(&i, 10, memory_order_seq_cst); } $ cat run.sh clang -I/home/yhs/work/bpf-next/tools/testing/selftests/bpf -O2 --target=bpf -c test3.c -o test3.o && llvm-objdump -d test3.o $ ./run.sh test3.o: file format elf64-bpf Disassembly of section .text: 0000000000000000 <f1>: 0: b4 01 00 00 0a 00 00 00 w1 = 0xa 1: 18 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r2 = 0x0 ll 3: c3 12 00 00 50 00 00 00 lock *(u32 *)(r2 + 0x0) &= w1 4: 95 00 00 00 00 00 00 00 exit 0000000000000028 <f2>: 5: b4 01 00 00 0a 00 00 00 w1 = 0xa 6: 18 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r2 = 0x0 ll 8: c3 12 00 00 51 00 00 00 w1 = atomic_fetch_and((u32 *)(r2 + 0x0), w1) 9: 95 00 00 00 00 00 00 00 exit ``` Note that in the above compilations, '-g' is not used. The reason is due to the following IR related to _Atomic type: ``` $clang -I/home/yhs/work/bpf-next/tools/testing/selftests/bpf -O2 --target=bpf -g -S -emit-llvm test3.c ``` The related debug info for test3.c: ``` !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "i", scope: !2, file: !3, line: 3, type: !16, isLocal: false, isDefinition: true) ... !16 = !DIDerivedType(tag: DW_TAG_atomic_type, baseType: !17) !17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) ``` If compiling test.c, the related debug info: ``` ... !19 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 3, type: !20, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !25) !20 = !DISubroutineType(types: !21) !21 = !{null, !22} !22 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !23, size: 64) !23 = !DIDerivedType(tag: DW_TAG_atomic_type, baseType: !24) !24 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !25 = !{!26} !26 = !DILocalVariable(name: "i", arg: 1, scope: !19, file: !1, line: 3, type: !22) ``` All the above suggests _Atomic behaves like a modifier (e.g. const, restrict, volatile). This seems true based on doc [1]. Without proper handling DW_TAG_atomic_type, llvm BTF generation will be incorrect since the current implementation assumes no existence of DW_TAG_atomic_type. So we have two choices here: (1). llvm bpf backend processes DW_TAG_atomic_type but ignores it in BTF encoding. (2). Add another type, e.g., BTF_KIND_ATOMIC to BTF. BTF_KIND_ATOMIC behaves as a modifier like const/volatile/restrict. For choice (1), llvm bpf backend should skip dwarf::DW_TAG_atomic_type during BTF generation whenever necessary. For choice (2), BTF_KIND_ATOMIC will be added to BTF so llvm backend and kernel needs to handle that properly. The main advantage of it probably is to maintain this atomic type so it is also available to skeleton. But I think for skeleton a raw type might be good enough unless user space intends to do some atomic operation with that, which is a unlikely case. So I choose choice (1) in this RFC implementation. See the commit message of the second commit for details. [1] https://lore.kernel.org/bpf/7b941f53-2a05-48ec-9032-8f106face3a3@linux.dev/ [2] https://dwarfstd.org/issues/131112.1.html ---------
2024-07-05[BPF] Fix linking issues in static map initializers (#91310)Nick Zavaritsky
When BPF object files are linked with bpftool, every symbol must be accompanied by BTF info. Ensure that extern functions referenced by global variable initializers are included in BTF. The primary motivation is "static" initialization of PROG maps: ```c extern int elsewhere(struct xdp_md *); struct { __uint(type, BPF_MAP_TYPE_PROG_ARRAY); __uint(max_entries, 1); __type(key, int); __type(value, int); __array(values, int (struct xdp_md *)); } prog_map SEC(".maps") = { .values = { elsewhere } }; ``` BPF backend needs debug info to produce BTF. Debug info is not normally generated for external variables and functions. Previously, it was solved differently for variables (collecting variable declarations in ExternalDeclarations vector) and functions (logic invoked during codegen in CGExpr.cpp). This patch generalises ExternalDefclarations to include both function and variable declarations. This change ensures that function references are not missed no matter the context. Previously external functions referenced in constant expressions lacked debug info.
2024-06-28[IR] Don't include Module.h in Analysis.h (NFC) (#97023)Nikita Popov
Replace it with a forward declaration instead. Analysis.h is pulled in by all passes, but not all passes need to access the module.
2024-06-28[IR] Add getDataLayout() helpers to Function and GlobalValue (#96919)Nikita Popov
Similar to https://github.com/llvm/llvm-project/pull/96902, this adds `getDataLayout()` helpers to Function and GlobalValue, replacing the current `getParent()->getDataLayout()` pattern.
2024-05-05[Target] Use StringRef::operator== instead of StringRef::equals (NFC) ↵Kazu Hirata
(#91072) (#91138) I'm planning to remove StringRef::equals in favor of StringRef::operator==. - StringRef::operator==/!= outnumber StringRef::equals by a factor of 38 under llvm/ in terms of their usage. - The elimination of StringRef::equals brings StringRef closer to std::string_view, which has operator== but not equals. - S == "foo" is more readable than S.equals("foo"), especially for !Long.Expression.equals("str") vs Long.Expression != "str".
2024-04-29BPF: Use DebugLoc to find Filename for BTF line info (#90302)yonghong-song
Andrii found an issue where the BTF line info may have empty source which seems wrong. The program is a Meta internal bpf program. I can reproduce with latest upstream compiler as well. Let the bpf program built without this patch and then with the following veristat check where veristat is a bpf verifier tool to do kernel verification for bpf programs: $ veristat -vl2 yhs.bpf.o --log-size=150000000 >& log $ rg '^;' log | sort | uniq -c | sort -nr | head -n10 4206 ; } else if (action->dry_run) { @ src_mitigations.h:57 3907 ; if (now < start_allow_time) { @ ban.h:17 3674 ; @ src_mitigations.h:0 3223 ; if (action->vip_id != ALL_VIPS_ID && action->vip_id != vip_id) { @ src_mitigations.h:85 1737 ; pkt_info->is_dry_run_drop = action->dry_run; @ src_mitigations.h:26 1737 ; if (mitigation == ALLOW) { @ src_mitigations.h:28 1737 ; enum match_action mitigation = action->action; @ src_mitigations.h:25 1727 ; void* res = bpf_map_lookup_elem(bpf_map, key); @ filter_helpers.h:498 1691 ; bpf_map_lookup_elem(&rate_limit_config_map, rule_id); @ rate_limit.h:76 1688 ; if (throttle_cfg) { @ rate_limit.h:85 You can see 3674 ; @ src_mitigations.h:0 where we do not have proper line information and line number. In LLVM Machine IR, some instructions may carry DebugLoc information to specify where the corresponding source is for this instruction. The information includes file_name, line_num and col_num. Each instruction may also attribute to a function in debuginfo. So there are two ways to find file_name for a particular insn: (1) find the corresponding function in debuginfo (MI->getMF()->getFunction().getSubprogram()) and then find the file_name from DISubprogram. (2) find the corresponding file_name from DebugLoc. The option (1) is used in current implementation. This mostly works. But if one instruction is somehow generated from multiple functions, the compiler has to pick just one. This may cause a mismatch between file_name and line_num/col_num. Besides potential incorrect mismatch of file_name vs. line_num/col_num, There is another issue where some DebugLoc has line number 0. For example, I dumped the dwarf line table for the above bpf program: Address Line Column File ISA Discriminator OpIndex Flags ------------------ ------ ------ ------ --- ------------- ------- ------------- 0x0000000000000000 96 0 17 0 0 0 is_stmt 0x0000000000000010 100 12 17 0 0 0 is_stmt prologue_end 0x0000000000000020 0 12 17 0 0 0 0x0000000000000058 37 7 17 0 0 0 is_stmt 0x0000000000000060 0 0 17 0 0 0 0x0000000000000088 37 7 17 0 0 0 0x0000000000000090 42 75 17 0 0 0 is_stmt 0x00000000000000a8 42 52 17 0 0 0 0x00000000000000c0 120 9 17 0 0 0 is_stmt 0x00000000000000c8 0 9 17 0 0 0 0x00000000000000d0 106 21 17 0 0 0 is_stmt 0x00000000000000d8 106 3 17 0 0 0 0x00000000000000e0 110 25 17 0 0 0 is_stmt 0x00000000000000f8 110 36 17 0 0 0 0x0000000000000100 0 36 17 0 0 0 ... These DebugLoc with line number 0 needs to be skipped since we cannot map them to the correct source code. Note that selftest offset-reloc-basic.ll has this issue as well which is adjusted by this patch. With the above two fixes, empty lines for source annotation are removed. $ veristat -vl2 yhs.bpf.o --log-size=150000000 >& log $ rg '^;' log.latest | sort | uniq -c | sort -nr | head -n10 4206 ; } else if (action->dry_run) { @ src_mitigations.h:57 3907 ; if (now < start_allow_time) { @ ban.h:17 3223 ; if (action->vip_id != ALL_VIPS_ID && action->vip_id != vip_id) { @ src_mitigations.h:85 1737 ; pkt_info->is_dry_run_drop = action->dry_run; @ src_mitigations.h:26 1737 ; if (mitigation == ALLOW) { @ src_mitigations.h:28 1737 ; enum match_action mitigation = action->action; @ src_mitigations.h:25 1727 ; void* res = bpf_map_lookup_elem(bpf_map, key); @ filter_helpers.h:498 1691 ; bpf_map_lookup_elem(&rate_limit_config_map, rule_id); @ rate_limit.h:76 1688 ; if (throttle_cfg) { @ rate_limit.h:85 1670 ; if (rl_cfg) { @ rate_limit.h:77 You can see that we do not have empty line any more. 3223 ; if (action->vip_id != ALL_VIPS_ID && action->vip_id != vip_id) { @ src_mitigations.h:85 Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
2023-12-11[llvm] Use StringRef::{starts,ends}_with (NFC) (#74956)Kazu Hirata
This patch replaces uses of StringRef::{starts,ends}with with StringRef::{starts,ends}_with for consistency with std::{string,string_view}::{starts,ends}_with in C++20. I'm planning to deprecate and eventually remove StringRef::{starts,ends}with.
2023-09-21[BPF][DebugInfo] Show CO-RE relocations in llvm-objdumpEduard Zingerman
Extend llvm-objdump to show CO-RE relocations when `-r` option is passed and object file has .BTF and .BTF.ext sections. For example, the following C program: #define __pai __attribute__((preserve_access_index)) struct foo { int i; int j;} __pai; struct bar { struct foo f[7]; } __pai; extern void sink(void *); void root(struct bar *bar) { sink(&bar[2].f[3].j); } Should lead to the following objdump output: $ clang --target=bpf -O2 -g t.c -c -o - | \ llvm-objdump --no-addresses --no-show-raw-insn -dr - ... r2 = 0x94 CO-RE <byte_off> [2] struct bar::[2].f[3].j (2:0:3:1) r1 += r2 call -0x1 R_BPF_64_32 sink exit ... More examples could be found in unit tests, see BTFParserTest.cpp. To achieve this: - Move CO-RE relocation kinds definitions from BPFCORE.h to BTF.h. - Extend BTF.h with types derived from BTF::CommonType, e.g. BTF::IntType and BTF::StrutType, to allow dyn_cast() and access to type additional data. - Extend BTFParser to load BTF type and relocation data. - Modify llvm-objdump.cpp to create instance of BTFParser when disassembly of object file with BTF sections is processed and `-r` flag is supplied. Additional information about CO-RE is available at [1]. [1] https://docs.kernel.org/bpf/llvm_reloc.html Depends on D149058 Differential Revision: https://reviews.llvm.org/D150079
2023-08-15[BPF] Fix in/out argument constraints for CORE_MEM instructionsEduard Zingerman
When LLVM is build with `LLVM_ENABLE_EXPENSIVE_CHECKS=ON` option the following C code snippet: struct t { int a; } __attribute__((preserve_access_index)); void test(struct t *t) { t->a = 42; } Causes an assertion: $ clang -g -O2 -c --target=bpf -mcpu=v2 t.c -o /dev/null Function Live Ins: $r1 in %0 bb.0.entry: liveins: $r1 DBG_VALUE $r1, $noreg, !"t", ... %0:gpr = COPY $r1 DBG_VALUE %0:gpr, $noreg, !"t", ... %1:gpr = LD_imm64 @"llvm.t:0:0$0:0" %3:gpr = ADD_rr %0:gpr(tied-def 0), killed %1:gpr %4:gpr = MOV_ri 42 CORE_MEM killed %4:gpr, 411, %0:gpr, @"llvm.t:0:0$0:0", ... RET debug-location !25; t.c:7:1 *** Bad machine code: Explicit definition marked as use *** - function: test - basic block: %bb.0 entry (0x6210000d8a90) - instruction: CORE_MEM killed %4:gpr, 411, %0:gpr, @"llvm.t:0:0$0:0", ... - operand 0: killed %4:gpr This happens because `CORE_MEM` instruction is defined to have output operands: def CORE_MEM : TYPE_LD_ST<BPF_MEM.Value, BPF_W.Value, (outs GPR:$dst), (ins u64imm:$opcode, GPR:$src, u64imm:$offset), "$dst = core_mem($opcode, $src, $offset)", []>; As documented in [1]: > By convention, the LLVM code generator orders instruction operands > so that all register definitions come before the register uses, even > on architectures that are normally printed in other orders. In other words, the first argument for `CORE_MEM` is considered to be a "def", while in reality it is "use": %1:gpr = LD_imm64 @"llvm.t:0:0$0:0" %3:gpr = ADD_rr %0:gpr(tied-def 0), killed %1:gpr %4:gpr = MOV_ri 42 '---------------. v CORE_MEM killed %4:gpr, 411, %0:gpr, @"llvm.t:0:0$0:0", ... Here is how `CORE_MEM` is constructed in `BPFMISimplifyPatchable::checkADDrr()`: BuildMI(*DefInst->getParent(), *DefInst, DefInst->getDebugLoc(), TII->get(COREOp)) .add(DefInst->getOperand(0)).addImm(Opcode).add(*BaseOp) .addGlobalAddress(GVal); Note that first operand is constructed as `.add(DefInst->getOperand(0))`. For `LD{D,W,H,B}` instructions the `DefInst->getOperand(0)` is a destination register of a load, so instruction is constructed in accordance with `outs` declaration. For `ST{D,W,H,B}` instructions the `DefInst->getOperand(0)` is a source register of a store (value to be stored), so instruction violates the `outs` declaration. This commit fixes the issue by splitting `CORE_MEM` in three instructions: `CORE_ST`, `CORE_LD64`, `CORE_LD32` with correct `outs` specifications. [1] https://llvm.org/docs/CodeGenerator.html#the-machineinstr-class Differential Revision: https://reviews.llvm.org/D157806
2023-08-03[BPF] Don't crash on missing line infoTamir Duberstein
When compiling Rust code we may end up with calls to functions provided by other code units. Presently this code crashes on a null pointer dereference - this patch avoids that crash and adds a test. Reviewed By: ast Differential Revision: https://reviews.llvm.org/D156446
2023-08-02Revert "[BPF] Narrow some interfaces"Tamir Duberstein
Review requested by @ast and @yonghong-song. This reverts commit 82bc1839bc53db296be36947ec0c482c8ca3a3d8.
2023-08-02[BPF] Narrow some interfacesTamir Duberstein
When compiling Rust code we sometimes see incomplete debug info leading to crashes. Narrow the interfaces so we can see where it happens. Reviewed By: ajwerner Differential Revision: https://reviews.llvm.org/D156443
2023-08-02[BPF] Avoid repeating MI->getOperand(NumDefs) x3Tamir Duberstein
Differential Revision: https://reviews.llvm.org/D156445
2023-07-10[BPF][DebugInfo][NFC] Move BTF.h definitions from BPF target to DebugInfoEduard Zingerman
There are plans to add some BTF processing to tools like objdump and readelf. This commit moves BTF.{h,def} files from BPF target specific location to include/llvm/DebugInfo/* to avoid tools including headers from lib/Target/*. Reviewed By: yonghong-song, MaskRay Differential Revision: https://reviews.llvm.org/D149501
2023-03-14[Target] Use *{Set,Map}::contains (NFC)Kazu Hirata
2023-03-13[BPF] Improve pruning to avoid generate more types in BTFYonghong Song
Commit 3671bdbcd214("[BPF] Fix a BTF type pruning bug") fixed a pruning bug to allow generate more types. But the commit has a bug which permits to generate more types than necessary. The following is an example to illustrate the problem. struct t1 { int a; }; struct t2 { struct t1 *p1; struct t1 *p2; int b; }; int foo(struct t2 *arg) { return arg->b; } The following is the part of BTF generation sequence: (1). 'struct t2 *arg' -> 'struct t1 *p1' In this step, the type 'struct t1' will be generated as a forward decl and the ptr type (to 'struct t1') will be stored in the internal type table. (2). now the second field 'struct t1 *p2' will be processed. Since the ptr type (to 'struct t1') already in the type table, the existing logic strips out ptr modifier and is able to generate BTF type for 'struct t1'. In the above step (2), if CheckPointer is true (the type traversal chain including a struct member), 'ptr' modifier should be checked and the subsequent type generation should be skipped since the same case has been processed in visitDerivedType(). The issue is exposed when I am trying to use llvm15 to compile some internal bpf programs. The bpf skeleton put the whole ELF section (after striping some sections like dwarf) as a string. The large BTF section triggered the following error: bpf_object_with_struct_ops_test_prog_bpf/BpfObjectWithStructOpsTestProg.skel.h:222:23: error: string literal of length 140144 exceeds maximum length 65536 that C++ compilers are required to support [-Werror,-Woverlength-strings] return (const void *)"\ ^~ 1 error generated. Although adding -Wno-overlength-strings could workaround the issue, improving llvm BTF generation sounds better esp. for users using vmlinux.h. Differential Revision: https://reviews.llvm.org/D145816
2023-01-07[BPF] generate btf_decl_tag records for params of extern functionsEduard Zingerman
After frontend changes in the following commit: "BPF: preserve btf_decl_tag for parameters of extern functions" same mechanics could be used to get the list of function parameters and associated btf_decl_tag entries for both extern and non-extern functions. This commit extracts this mechanics as a separate auxiliary function BTFDebug::processDISubprogram(). The function is called for both extern and non-extern functions in order to generated corresponding BTF_DECL_TAG records. Differential Revision: https://reviews.llvm.org/D140971
2023-01-02[llvm] Use std::optional instead of llvm::Optional (NFC)Kazu Hirata
This is part of an effort to migrate from llvm::Optional to std::optional: https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-29[BPF] Use SectionForGlobal() for section names computation in BTFEduard Zingerman
Use function TargetLoweringObjectFile::SectionForGlobal() to compute section names for globals described in BTF_KIND_DATASEC records. This fixes a discrepancy in section name computation between BTFDebug::processGlobals and the rest of the LLVM pipeline. Specifically, the following example illustrates the discrepancy before this commit: struct Foo { int i; } __attribute__((aligned(16))); struct Foo foo = { 0 }; The initializer for 'foo' looks as follows: %struct.Foo { i32 0, [12 x i8] undef } TargetLoweringObjectFile::SectionForGlobal() classifies 'foo' as a part of '.bss' section, while BTFDebug::processGlobals classified it as a part of '.data' section because of the following expression: SecName = Global.getInitializer()->isZeroValue() ? ".bss" : ".data" The isZeroValue() returns false because of the undef tail of the initializer, while SectionForGlobal() allows such patterns in '.bss'. Differential Revision: https://reviews.llvm.org/D140505
2022-12-18Remove redundant .c_str() and .get() callsGregory Alfonso
Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D139485
2022-06-18[llvm] Call *set::insert without checking membership first (NFC)Kazu Hirata
2022-06-10[MC] De-capitalize SwitchSection. NFCFangrui Song
Add SwitchSection to return switchSection. The API will be removed soon.
2022-06-06[BPF] Add BTF 64bit enum value supportYonghong Song
Current BTF only supports 32-bit value. For example, enum T { VAL = 0xffffFFFF00000008 }; the generated BTF looks like .long 16 # BTF_KIND_ENUM(id = 4) .long 100663297 # 0x6000001 .long 8 .long 18 .long 8 The encoded value is 8 which equals to (uint32_t)0xffffFFFF00000008 and this is incorrect. This patch introduced BTF_KIND_ENUM64 which permits to encode 64-bit value. The format for each enumerator looks like: .long name_offset .long (uint32_t)value # lower-32 bit value .long value >> 32 # high-32 bit value We use two 32-bit values to represent a 64-bit value as current BTF type subsection has 4-byte alignment and gaps are not permitted in the subsection. This patch also added support for kflag (the bit 31 of CommonType.Info) such that kflag = 1 implies the value is signed and kflag = 0 implies the value is unsigned. The kernel UAPI enumerator definition is struct btf_enum { __u32 name_off; __s32 val; }; so kflag = 0 with unsigned value provides backward compatability. With this patch, for enum T { VAL = 0xffffFFFF00000008 }; the generated BTF looks like .long 16 # BTF_KIND_ENUM64(id = 4) .long 3187671053 # 0x13000001 .long 8 .long 18 .long 8 # 0x8 .long 4294967295 # 0xffffffff and the enumerator value and signedness are encoded correctly. Differential Revision: https://reviews.llvm.org/D124641
2022-03-12Cleanup includes: DebugInfo & CodeGenserge-sans-paille
Discourse thread: https://discourse.llvm.org/t/include-what-you-use-include-cleanup Differential Revision: https://reviews.llvm.org/D121332
2022-02-16[BPF] Fix a BTF type pruning bugYonghong Song
In BPF backend, BTF type generation may skip some debuginfo types if they are the pointee type of a struct member. For example, struct task_struct { ... struct mm_struct *mm; ... }; BPF backend may generate a forward decl for 'struct mm_struct' instead of full type if there are no other usage of 'struct mm_struct'. The reason is to avoid bringing too much unneeded types in BTF. Alexei found a pruning bug where we may miss some full type generation. The following is an illustrating example: struct t1 { ... } struct t2 { struct t1 *p; }; struct t2 g; void foo(struct t1 *arg) { ... } In the above case, we will have partial debuginfo chain like below: struct t2 -> member p \ -> ptr -> struct t1 / foo -> argument arg During traversing struct t2 -> member p -> ptr -> struct t1 The corresponding BTF types are generated except 'struct t1' which will be in FixUp stage. Later, when traversing foo -> argument arg -> ptr -> struct t1 The 'ptr' BTF type has been generated and currently implementation ignores 'pointer' type hence 'struct t1' is not generated. This patch fixed the issue not just for the above case, but for general case with multiple derived types, e.g., struct t2 -> member p \ -> const -> ptr -> volatile -> struct t1 / foo -> argument arg Differential Revision: https://reviews.llvm.org/D119986
2022-02-14[BPF] Fix a bug in BTF_KIND_TYPE_TAG generationYonghong Song
Kumar Kartikeya Dwivedi reported a bug ([1]) where BTF_KIND_TYPE_TAG types are not generated. Currently, BPF backend only generates BTF types which are used by the program, e.g., global variables, functions and some builtin functions. For example, suppose we have struct task_struct { ... struct task_group *sched_task_group; struct mm_struct *mm; ... pid_t pid; pid_t tgid; ... } If BPF program intends to access task_struct->pid and task_struct->tgid, there really no need to generate BTF types for struct task_group and mm_struct. In BPF backend, during BTF generation, when generating BTF for struct task_struct, if types for task_group and mm_struct have not been generated yet, a Fixup structure will be created, which will be reexamined later to instantiate into either a full type or a forward type. In current implementation, if we have something like struct foo { struct bar __tag1 *f; }; and when generating types for struct foo, struct bar type has not been generated, the __tag1 will be lost during later Fixup instantiation. This patch fixed this issue by properly handling btf_type_tag's during Fixup instantiation stage. [1] https://lore.kernel.org/bpf/20220210232411.pmhzj7v5uptqby7r@apollo.legion/ Differential Revision: https://reviews.llvm.org/D119799
2022-01-27[BTFDebug] Avoid pointer element type accessNikita Popov
Use the global value type instead.
2022-01-25[NFC] Remove uses of PointerType::getElementType()Nikita Popov
Instead use either Type::getPointerElementType() or Type::getNonOpaquePointerElementType(). This is part of D117885, in preparation for deprecating the API.
2021-11-09BPF: change btf_type_tag BTF output formatYonghong Song
For the declaration like below: int __tag1 * __tag1 __tag2 *g Commit 41860e602aaa ("BPF: Support btf_type_tag attribute") implemented the following encoding: VAR(g) -> __tag1 --> __tag2 -> pointer -> __tag1 -> pointer -> int Some further experiments with linux btf_type_tag support, esp. with generating attributes in vmlinux.h, and also some internal discussion showed the following format is more desirable: VAR(g) -> pointer -> __tag2 -> __tag1 -> pointer -> __tag1 -> int The format makes it similar to other modifier like 'const', e.g., const int *g which has encoding VAR(g) -> PTR -> CONST -> int Differential Revision: https://reviews.llvm.org/D113496
2021-11-04BPF: Support btf_type_tag attributeYonghong Song
A new kind BTF_KIND_TYPE_TAG is defined. The tags associated with a pointer type are emitted in their IR order as modifiers. For example, for the following declaration: int __tag1 * __tag1 __tag2 *g; The BTF type chain will look like VAR(g) -> __tag1 --> __tag2 -> pointer -> __tag1 -> pointer -> int In the above "->" means BTF CommonType.Type which indicates the point-to type. Differential Revision: https://reviews.llvm.org/D113222
2021-10-21BPF: emit BTF_KIND_DECL_TAG for typedef typesYonghong Song
If a typedef type has __attribute__((btf_decl_tag("str"))) with bpf target, emit BTF_KIND_DECL_TAG for that type in the BTF. Differential Revision: https://reviews.llvm.org/D112259
2021-10-19BPF: set .BTF and .BTF.ext section alignment to 4Yonghong Song
Currently, .BTF and .BTF.ext has default alignment of 1. For example, $ cat t.c int foo() { return 0; } $ clang -target bpf -O2 -c -g t.c $ llvm-readelf -S t.o ... Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al ... [ 7] .BTF PROGBITS 0000000000000000 000167 00008b 00 0 0 1 [ 8] .BTF.ext PROGBITS 0000000000000000 0001f2 000050 00 0 0 1 But to have no misaligned data access, .BTF and .BTF.ext actually requires alignment of 4. Misalignment is not an issue for architecture like x64/arm64 as it can handle it well. But some architectures like mips may incur a trap if .BTF/.BTF.ext is not properly aligned. This patch explicitly forced .BTF and .BTF.ext alignment to be 4. For the above example, we will have [ 7] .BTF PROGBITS 0000000000000000 000168 00008b 00 0 0 4 [ 8] .BTF.ext PROGBITS 0000000000000000 0001f4 000050 00 0 0 4 Differential Revision: https://reviews.llvm.org/D112106
2021-10-18[NFC][BPF] fix comments and rename functions related to BTF_KIND_DECL_TAGYonghong Song
There are no functionality change. Fix some comments and rename processAnnotations() to processDeclAnnotations() to avoid confusion when later BTF_KIND_TYPE_TAG is introduced (https://reviews.llvm.org/D111199).
2021-10-11BPF: rename BTF_KIND_TAG to BTF_KIND_DECL_TAGYonghong Song
Per discussion in https://reviews.llvm.org/D111199, the existing btf_tag attribute will be renamed to btf_decl_tag. This patch updated BTF backend to use btf_decl_tag attribute name and also renamed BTF_KIND_TAG to BTF_KIND_DECL_TAG. Differential Revision: https://reviews.llvm.org/D111592
2021-09-09BPF: change BTF_KIND_TAG formatYonghong Song
Previously we have the following binary representation: struct bpf_type { name, info, type } struct btf_tag { __u32 component_idx; } If the tag points to a struct/union/var/func type, we will have kflag = 1, component_idx = 0 if the tag points to struct/union member or func argument, we will have kflag = 0, component_idx = 0, ..., vlen - 1 The above rather makes interface complex to have both kflag and component needed to determine its legality and index. This patch simplifies the interface by removing kflag involvement. component_idx = (u32)-1 : tag pointing to a type component_idx = 0 ... vlen - 1 : tag pointing to a member or argument and kflag is always 0 and there is no need to check. Differential Revision: https://reviews.llvm.org/D109560
2021-08-28[BPF] support btf_tag attribute in .BTF sectionYonghong Song
A new kind BTF_KIND_TAG is added to .BTF to encode btf_tag attributes. The format looks like CommonType.name : attribute string CommonType.type : attached to a struct/union/func/var. CommonType.info : encoding BTF_KIND_TAG kflag == 1 to indicate the attribute is for CommonType.type, or kflag == 0 for struct/union member or func argument. one uint32_t : to encode which member/argument starting from 0. If one particular type or member/argument has more than one attribute, multiple BTF_KIND_TAG will be generated. Differential Revision: https://reviews.llvm.org/D106622
2021-04-26BPF: generate BTF info for LD_imm64 loaded function pointerYonghong Song
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