sphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget"/translations/zh_CN/bpf/llvm_relocmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/zh_TW/bpf/llvm_relocmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/it_IT/bpf/llvm_relocmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/ja_JP/bpf/llvm_relocmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/ko_KR/bpf/llvm_relocmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hPortuguese (Brazilian)}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/pt_BR/bpf/llvm_relocmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget"/translations/sp_SP/bpf/llvm_relocmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhcomment)}(h3SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)h]h3SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhhhhhhubj )}(hXgSymbol table '.symtab' contains 8 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c 2: 0000000000000008 4 OBJECT LOCAL DEFAULT 4 l1 3: 000000000000000c 4 OBJECT LOCAL DEFAULT 4 l2 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 sec 5: 0000000000000000 128 FUNC GLOBAL DEFAULT 2 test 6: 0000000000000000 4 OBJECT GLOBAL DEFAULT 4 g1 7: 0000000000000004 4 OBJECT GLOBAL DEFAULT 4 g2h]hXgSymbol table '.symtab' contains 8 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c 2: 0000000000000008 4 OBJECT LOCAL DEFAULT 4 l1 3: 000000000000000c 4 OBJECT LOCAL DEFAULT 4 l2 4: 0000000000000000 0 SECTION LOCAL DEFAULT 4 sec 5: 0000000000000000 128 FUNC GLOBAL DEFAULT 2 test 6: 0000000000000000 4 OBJECT GLOBAL DEFAULT 4 g1 7: 0000000000000004 4 OBJECT GLOBAL DEFAULT 4 g2}hj"sbah}(h]h ]h"]h$]h&]hhuh1j hhhKDhhhhubh)}(h5The 6th entry is global variable ``g1`` with value 0.h](h!The 6th entry is global variable }(hj0hhhNhNubjA)}(h``g1``h]hg1}(hj8hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj0ubh with value 0.}(hj0hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKOhhhhubh)}(hXzSimilarly, the second relocation is at ``.text`` offset ``0x18``, instruction 3, has a type of ``R_BPF_64_64`` and refers to entry 7 in the symbol table. The second relocation resolves to global variable ``g2`` which has a symbol value 4. The symbol value represents the offset from the start of ``.data`` section where the initial value of the global variable ``g2`` is stored.h](h'Similarly, the second relocation is at }(hjPhhhNhNubjA)}(h ``.text``h]h.text}(hjXhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjPubh offset }(hjPhhhNhNubjA)}(h``0x18``h]h0x18}(hjjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjPubh, instruction 3, has a type of }(hjPhhhNhNubjA)}(h``R_BPF_64_64``h]h R_BPF_64_64}(hj|hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjPubh^ and refers to entry 7 in the symbol table. The second relocation resolves to global variable }(hjPhhhNhNubjA)}(h``g2``h]hg2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjPubhV which has a symbol value 4. The symbol value represents the offset from the start of }(hjPhhhNhNubjA)}(h ``.data``h]h.data}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjPubh8 section where the initial value of the global variable }(hjPhhhNhNubjA)}(h``g2``h]hg2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjPubh is stored.}(hjPhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKQhhhhubh)}(hXUThe third and fourth relocations refer to static variables ``l1`` and ``l2``. From the ``.rel.text`` section above, it is not clear to which symbols they really refer as they both refer to symbol table entry 4, symbol ``sec``, which has ``STT_SECTION`` type and represents a section. So for a static variable or function, the section offset is written to the original insn buffer, which is called ``A`` (addend). Looking at above insn ``7`` and ``11``, they have section offset ``8`` and ``12``. From symbol table, we can find that they correspond to entries ``2`` and ``3`` for ``l1`` and ``l2``.h](h;The third and fourth relocations refer to static variables }(hjhhhNhNubjA)}(h``l1``h]hl1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }(hjhhhNhNubjA)}(h``l2``h]hl2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh . From the }(hjhhhNhNubjA)}(h ``.rel.text``h]h .rel.text}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubhv section above, it is not clear to which symbols they really refer as they both refer to symbol table entry 4, symbol }(hjhhhNhNubjA)}(h``sec``h]hsec}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh , which has }(hjhhhNhNubjA)}(h``STT_SECTION``h]h STT_SECTION}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh type and represents a section. So for a static variable or function, the section offset is written to the original insn buffer, which is called }(hjhhhNhNubjA)}(h``A``h]hA}(hj,hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh! (addend). Looking at above insn }(hjhhhNhNubjA)}(h``7``h]h7}(hj>hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }(hjhhhNhNubjA)}(h``11``h]h11}(hjPhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh, they have section offset }(hjhhhNhNubjA)}(h``8``h]h8}(hjbhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }hjsbjA)}(h``12``h]h12}(hjthhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubhA. From symbol table, we can find that they correspond to entries }(hjhhhNhNubjA)}(h``2``h]h2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }hjsbjA)}(h``3``h]h3}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh for }(hjhhhNhNubjA)}(h``l1``h]hl1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }hjsbjA)}(h``l2``h]hl2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKWhhhhubh)}(hIn general, the ``A`` is 0 for global variables and functions, and is the section offset or some computation result based on section offset for static variables/functions. The non-section-offset case refers to function calls. See below for more details.h](hIn general, the }(hjhhhNhNubjA)}(h``A``h]hA}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh is 0 for global variables and functions, and is the section offset or some computation result based on section offset for static variables/functions. The non-section-offset case refers to function calls. See below for more details.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKbhhhhubeh}(h]relocation-recordah ]h"]relocation recordah$]h&]uh1hhhhhhhhK ubh)}(hhh](h)}(hDifferent Relocation Typesh]hDifferent Relocation Types}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKhubh)}(hSix relocation types are supported. The following is an overview and ``S`` represents the value of the symbol in the symbol table::h](hESix relocation types are supported. The following is an overview and }(hj hhhNhNubjA)}(h``S``h]hS}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh8 represents the value of the symbol in the symbol table:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKjhjhhubj )}(hXEnum ELF Reloc Type Description BitSize Offset Calculation 0 R_BPF_NONE None 1 R_BPF_64_64 ld_imm64 insn 32 r_offset + 4 S + A 2 R_BPF_64_ABS64 normal data 64 r_offset S + A 3 R_BPF_64_ABS32 normal data 32 r_offset S + A 4 R_BPF_64_NODYLD32 .BTF[.ext] data 32 r_offset S + A 10 R_BPF_64_32 call insn 32 r_offset + 4 (S + A) / 8 - 1h]hXEnum ELF Reloc Type Description BitSize Offset Calculation 0 R_BPF_NONE None 1 R_BPF_64_64 ld_imm64 insn 32 r_offset + 4 S + A 2 R_BPF_64_ABS64 normal data 64 r_offset S + A 3 R_BPF_64_ABS32 normal data 32 r_offset S + A 4 R_BPF_64_NODYLD32 .BTF[.ext] data 32 r_offset S + A 10 R_BPF_64_32 call insn 32 r_offset + 4 (S + A) / 8 - 1}hj-sbah}(h]h ]h"]h$]h&]hhuh1j hhhKmhjhhubh)}(hXFor example, ``R_BPF_64_64`` relocation type is used for ``ld_imm64`` instruction. The actual to-be-relocated data (0 or section offset) is stored at ``r_offset + 4`` and the read/write data bitsize is 32 (4 bytes). The relocation can be resolved with the symbol value plus implicit addend. Note that the ``BitSize`` is 32 which means the section offset must be less than or equal to ``UINT32_MAX`` and this is enforced by LLVM BPF backend.h](h For example, }(hj;hhhNhNubjA)}(h``R_BPF_64_64``h]h R_BPF_64_64}(hjChhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj;ubh relocation type is used for }(hj;hhhNhNubjA)}(h ``ld_imm64``h]hld_imm64}(hjUhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj;ubhQ instruction. The actual to-be-relocated data (0 or section offset) is stored at }(hj;hhhNhNubjA)}(h``r_offset + 4``h]h r_offset + 4}(hjghhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj;ubh and the read/write data bitsize is 32 (4 bytes). The relocation can be resolved with the symbol value plus implicit addend. Note that the }(hj;hhhNhNubjA)}(h ``BitSize``h]hBitSize}(hjyhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj;ubhD is 32 which means the section offset must be less than or equal to }(hj;hhhNhNubjA)}(h``UINT32_MAX``h]h UINT32_MAX}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj;ubh* and this is enforced by LLVM BPF backend.}(hj;hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKuhjhhubh)}(hX In another case, ``R_BPF_64_ABS64`` relocation type is used for normal 64-bit data. The actual to-be-relocated data is stored at ``r_offset`` and the read/write data bitsize is 64 (8 bytes). The relocation can be resolved with the symbol value plus implicit addend.h](hIn another case, }(hjhhhNhNubjA)}(h``R_BPF_64_ABS64``h]hR_BPF_64_ABS64}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh^ relocation type is used for normal 64-bit data. The actual to-be-relocated data is stored at }(hjhhhNhNubjA)}(h ``r_offset``h]hr_offset}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh| and the read/write data bitsize is 64 (8 bytes). The relocation can be resolved with the symbol value plus implicit addend.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK}hjhhubh)}(hXBoth ``R_BPF_64_ABS32`` and ``R_BPF_64_NODYLD32`` types are for 32-bit data. But ``R_BPF_64_NODYLD32`` specifically refers to relocations in ``.BTF`` and ``.BTF.ext`` sections. For cases like bcc where llvm ``ExecutionEngine RuntimeDyld`` is involved, ``R_BPF_64_NODYLD32`` types of relocations should not be resolved to actual function/variable address. Otherwise, ``.BTF`` and ``.BTF.ext`` become unusable by bcc and kernel.h](hBoth }(hjhhhNhNubjA)}(h``R_BPF_64_ABS32``h]hR_BPF_64_ABS32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }(hjhhhNhNubjA)}(h``R_BPF_64_NODYLD32``h]hR_BPF_64_NODYLD32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh types are for 32-bit data. But }(hjhhhNhNubjA)}(h``R_BPF_64_NODYLD32``h]hR_BPF_64_NODYLD32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh' specifically refers to relocations in }(hjhhhNhNubjA)}(h``.BTF``h]h.BTF}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }(hjhhhNhNubjA)}(h ``.BTF.ext``h]h.BTF.ext}(hj%hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh) sections. For cases like bcc where llvm }(hjhhhNhNubjA)}(h``ExecutionEngine RuntimeDyld``h]hExecutionEngine RuntimeDyld}(hj7hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh is involved, }(hjhhhNhNubjA)}(h``R_BPF_64_NODYLD32``h]hR_BPF_64_NODYLD32}(hjIhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh] types of relocations should not be resolved to actual function/variable address. Otherwise, }(hjhhhNhNubjA)}(h``.BTF``h]h.BTF}(hj[hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }hjsbjA)}(h ``.BTF.ext``h]h.BTF.ext}(hjmhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh# become unusable by bcc and kernel.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hType ``R_BPF_64_32`` is used for call instruction. The call target section offset is stored at ``r_offset + 4`` (32bit) and calculated as ``(S + A) / 8 - 1``.h](hType }(hjhhhNhNubjA)}(h``R_BPF_64_32``h]h R_BPF_64_32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubhK is used for call instruction. The call target section offset is stored at }(hjhhhNhNubjA)}(h``r_offset + 4``h]h r_offset + 4}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh (32bit) and calculated as }(hjhhhNhNubjA)}(h``(S + A) / 8 - 1``h]h(S + A) / 8 - 1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubeh}(h]different-relocation-typesah ]h"]different relocation typesah$]h&]uh1hhhhhhhhKhubh)}(hhh](h)}(hExamplesh]hExamples}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hsTypes ``R_BPF_64_64`` and ``R_BPF_64_32`` are used to resolve ``ld_imm64`` and ``call`` instructions. For example::h](hTypes }(hjhhhNhNubjA)}(h``R_BPF_64_64``h]h R_BPF_64_64}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }(hjhhhNhNubjA)}(h``R_BPF_64_32``h]h R_BPF_64_32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh are used to resolve }(hjhhhNhNubjA)}(h ``ld_imm64``h]hld_imm64}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }(hjhhhNhNubjA)}(h``call``h]hcall}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh instructions. For example:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj )}(hXJ__attribute__((noinline)) __attribute__((section("sec1"))) int gfunc(int a, int b) { return a * b; } static __attribute__((noinline)) __attribute__((section("sec1"))) int lfunc(int a, int b) { return a + b; } int global __attribute__((section("sec2"))); int test(int a, int b) { return gfunc(a, b) + lfunc(a, b) + global; }h]hXJ__attribute__((noinline)) __attribute__((section("sec1"))) int gfunc(int a, int b) { return a * b; } static __attribute__((noinline)) __attribute__((section("sec1"))) int lfunc(int a, int b) { return a + b; } int global __attribute__((section("sec2"))); int test(int a, int b) { return gfunc(a, b) + lfunc(a, b) + global; }}hj8sbah}(h]h ]h"]h$]h&]hhuh1j hhhKhjhhubh)}(hqCompiled with ``clang --target=bpf -O2 -c test.c``, we will have following code with `llvm-objdump -dr test.o``::h](hCompiled with }(hjFhhhNhNubjA)}(h$``clang --target=bpf -O2 -c test.c``h]h clang --target=bpf -O2 -c test.c}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjFubh#, we will have following code with }(hjFhhhNhNubhtitle_reference)}(h`llvm-objdump -dr test.o``h]hllvm-objdump -dr test.o`}(hjbhhhNhNubah}(h]h ]h"]h$]h&]uh1j`hjFubh:}(hjFhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj )}(hXDisassembly of section .text: 0000000000000000 : 0: bf 26 00 00 00 00 00 00 r6 = r2 1: bf 17 00 00 00 00 00 00 r7 = r1 2: 85 10 00 00 ff ff ff ff call -1 0000000000000010: R_BPF_64_32 gfunc 3: bf 08 00 00 00 00 00 00 r8 = r0 4: bf 71 00 00 00 00 00 00 r1 = r7 5: bf 62 00 00 00 00 00 00 r2 = r6 6: 85 10 00 00 02 00 00 00 call 2 0000000000000030: R_BPF_64_32 sec1 7: 0f 80 00 00 00 00 00 00 r0 += r8 8: 18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll 0000000000000040: R_BPF_64_64 global 10: 61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0) 11: 0f 10 00 00 00 00 00 00 r0 += r1 12: 95 00 00 00 00 00 00 00 exit Disassembly of section sec1: 0000000000000000 : 0: bf 20 00 00 00 00 00 00 r0 = r2 1: 2f 10 00 00 00 00 00 00 r0 *= r1 2: 95 00 00 00 00 00 00 00 exit 0000000000000018 : 3: bf 20 00 00 00 00 00 00 r0 = r2 4: 0f 10 00 00 00 00 00 00 r0 += r1 5: 95 00 00 00 00 00 00 00 exith]hXDisassembly of section .text: 0000000000000000 : 0: bf 26 00 00 00 00 00 00 r6 = r2 1: bf 17 00 00 00 00 00 00 r7 = r1 2: 85 10 00 00 ff ff ff ff call -1 0000000000000010: R_BPF_64_32 gfunc 3: bf 08 00 00 00 00 00 00 r8 = r0 4: bf 71 00 00 00 00 00 00 r1 = r7 5: bf 62 00 00 00 00 00 00 r2 = r6 6: 85 10 00 00 02 00 00 00 call 2 0000000000000030: R_BPF_64_32 sec1 7: 0f 80 00 00 00 00 00 00 r0 += r8 8: 18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll 0000000000000040: R_BPF_64_64 global 10: 61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0) 11: 0f 10 00 00 00 00 00 00 r0 += r1 12: 95 00 00 00 00 00 00 00 exit Disassembly of section sec1: 0000000000000000 : 0: bf 20 00 00 00 00 00 00 r0 = r2 1: 2f 10 00 00 00 00 00 00 r0 *= r1 2: 95 00 00 00 00 00 00 00 exit 0000000000000018 : 3: bf 20 00 00 00 00 00 00 r0 = r2 4: 0f 10 00 00 00 00 00 00 r0 += r1 5: 95 00 00 00 00 00 00 00 exit}hjzsbah}(h]h ]h"]h$]h&]hhuh1j hhhKhjhhubh)}(hXThe first relocation corresponds to ``gfunc(a, b)`` where ``gfunc`` has a value of 0, so the ``call`` instruction offset is ``(0 + 0)/8 - 1 = -1``. The second relocation corresponds to ``lfunc(a, b)`` where ``lfunc`` has a section offset ``0x18``, so the ``call`` instruction offset is ``(0 + 0x18)/8 - 1 = 2``. The third relocation corresponds to ld_imm64 of ``global``, which has a section offset ``0``.h](h$The first relocation corresponds to }(hjhhhNhNubjA)}(h``gfunc(a, b)``h]h gfunc(a, b)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh where }(hjhhhNhNubjA)}(h ``gfunc``h]hgfunc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh has a value of 0, so the }(hjhhhNhNubjA)}(h``call``h]hcall}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh instruction offset is }(hjhhhNhNubjA)}(h``(0 + 0)/8 - 1 = -1``h]h(0 + 0)/8 - 1 = -1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh'. The second relocation corresponds to }(hjhhhNhNubjA)}(h``lfunc(a, b)``h]h lfunc(a, b)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh where }hjsbjA)}(h ``lfunc``h]hlfunc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh has a section offset }(hjhhhNhNubjA)}(h``0x18``h]h0x18}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh , so the }(hjhhhNhNubjA)}(h``call``h]hcall}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh instruction offset is }hjsbjA)}(h``(0 + 0x18)/8 - 1 = 2``h]h(0 + 0x18)/8 - 1 = 2}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh2. The third relocation corresponds to ld_imm64 of }(hjhhhNhNubjA)}(h ``global``h]hglobal}(hj2hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh, which has a section offset }(hjhhhNhNubjA)}(h``0``h]h0}(hjDhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hKThe following is an example to show how R_BPF_64_ABS64 could be generated::h]hJThe following is an example to show how R_BPF_64_ABS64 could be generated:}(hj\hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj )}(hBint global() { return 0; } struct t { void *g; } gbl = { global };h]hBint global() { return 0; } struct t { void *g; } gbl = { global };}hjjsbah}(h]h ]h"]h$]h&]hhuh1j hhhKhjhhubh)}(hCompiled with ``clang --target=bpf -O2 -g -c test.c``, we will see a relocation below in ``.data`` section with command ``llvm-readelf -r test.o``::h](hCompiled with }(hjxhhhNhNubjA)}(h'``clang --target=bpf -O2 -g -c test.c``h]h#clang --target=bpf -O2 -g -c test.c}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjxubh$, we will see a relocation below in }(hjxhhhNhNubjA)}(h ``.data``h]h.data}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjxubh section with command }(hjxhhhNhNubjA)}(h``llvm-readelf -r test.o``h]hllvm-readelf -r test.o}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjxubh:}(hjxhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj )}(hRelocation section '.rel.data' at offset 0x458 contains 1 entries: Offset Info Type Symbol's Value Symbol's Name 0000000000000000 0000000700000002 R_BPF_64_ABS64 0000000000000000 globalh]hRelocation section '.rel.data' at offset 0x458 contains 1 entries: Offset Info Type Symbol's Value Symbol's Name 0000000000000000 0000000700000002 R_BPF_64_ABS64 0000000000000000 global}hjsbah}(h]h ]h"]h$]h&]hhuh1j hhhKhjhhubh)}(hoThe relocation says the first 8-byte of ``.data`` section should be filled with address of ``global`` variable.h](h(The relocation says the first 8-byte of }(hjhhhNhNubjA)}(h ``.data``h]h.data}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh* section should be filled with address of }(hjhhhNhNubjA)}(h ``global``h]hglobal}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh variable.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hWith ``llvm-readelf`` output, we can see that dwarf sections have a bunch of ``R_BPF_64_ABS32`` and ``R_BPF_64_ABS64`` relocations::h](hWith }(hjhhhNhNubjA)}(h``llvm-readelf``h]h llvm-readelf}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh8 output, we can see that dwarf sections have a bunch of }(hjhhhNhNubjA)}(h``R_BPF_64_ABS32``h]hR_BPF_64_ABS32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh and }(hjhhhNhNubjA)}(h``R_BPF_64_ABS64``h]hR_BPF_64_ABS64}(hj(hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh relocations:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj )}(hXRelocation section '.rel.debug_info' at offset 0x468 contains 13 entries: Offset Info Type Symbol's Value Symbol's Name 0000000000000006 0000000300000003 R_BPF_64_ABS32 0000000000000000 .debug_abbrev 000000000000000c 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str 0000000000000012 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str 0000000000000016 0000000600000003 R_BPF_64_ABS32 0000000000000000 .debug_line 000000000000001a 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str 000000000000001e 0000000200000002 R_BPF_64_ABS64 0000000000000000 .text 000000000000002b 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str 0000000000000037 0000000800000002 R_BPF_64_ABS64 0000000000000000 gbl 0000000000000040 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str ......h]hXRelocation section '.rel.debug_info' at offset 0x468 contains 13 entries: Offset Info Type Symbol's Value Symbol's Name 0000000000000006 0000000300000003 R_BPF_64_ABS32 0000000000000000 .debug_abbrev 000000000000000c 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str 0000000000000012 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str 0000000000000016 0000000600000003 R_BPF_64_ABS32 0000000000000000 .debug_line 000000000000001a 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str 000000000000001e 0000000200000002 R_BPF_64_ABS64 0000000000000000 .text 000000000000002b 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str 0000000000000037 0000000800000002 R_BPF_64_ABS64 0000000000000000 gbl 0000000000000040 0000000400000003 R_BPF_64_ABS32 0000000000000000 .debug_str ......}hj@sbah}(h]h ]h"]h$]h&]hhuh1j hhhKhjhhubh)}(h>The .BTF/.BTF.ext sections has R_BPF_64_NODYLD32 relocations::h]h=The .BTF/.BTF.ext sections has R_BPF_64_NODYLD32 relocations:}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubj )}(hX+Relocation section '.rel.BTF' at offset 0x538 contains 1 entries: Offset Info Type Symbol's Value Symbol's Name 0000000000000084 0000000800000004 R_BPF_64_NODYLD32 0000000000000000 gbl Relocation section '.rel.BTF.ext' at offset 0x548 contains 2 entries: Offset Info Type Symbol's Value Symbol's Name 000000000000002c 0000000200000004 R_BPF_64_NODYLD32 0000000000000000 .text 0000000000000040 0000000200000004 R_BPF_64_NODYLD32 0000000000000000 .texth]hX+Relocation section '.rel.BTF' at offset 0x538 contains 1 entries: Offset Info Type Symbol's Value Symbol's Name 0000000000000084 0000000800000004 R_BPF_64_NODYLD32 0000000000000000 gbl Relocation section '.rel.BTF.ext' at offset 0x548 contains 2 entries: Offset Info Type Symbol's Value Symbol's Name 000000000000002c 0000000200000004 R_BPF_64_NODYLD32 0000000000000000 .text 0000000000000040 0000000200000004 R_BPF_64_NODYLD32 0000000000000000 .text}hj\sbah}(h]h ]h"]h$]h&]hhuh1j hhhKhjhhubhtarget)}(h.. _btf-co-re-relocations:h]h}(h]h ]h"]h$]h&]refidbtf-co-re-relocationsuh1jjhKhjhhhhubeh}(h]examplesah ]h"]examplesah$]h&]uh1hhhhhhhhKubeh}(h]bpf-llvm-relocationsah ]h"]bpf llvm relocationsah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hCO-RE Relocationsh]hCO-RE Relocations}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(hX0From object file point of view CO-RE mechanism is implemented as a set of CO-RE specific relocation records. These relocation records are not related to ELF relocations and are encoded in .BTF.ext section. See :ref:`Documentation/bpf/btf.rst ` for more information on .BTF.ext structure.h](hFrom object file point of view CO-RE mechanism is implemented as a set of CO-RE specific relocation records. These relocation records are not related to ELF relocations and are encoded in .BTF.ext section. See }(hjhhhNhNubh)}(h2:ref:`Documentation/bpf/btf.rst `h]hinline)}(hjh]hDocumentation/bpf/btf.rst}(hjhhhNhNubah}(h]h ](xrefstdstd-refeh"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]refdocbpf/llvm_reloc refdomainjreftyperef refexplicitrefwarn reftargetbtf_ext_sectionuh1hhhhKhjubh, for more information on .BTF.ext structure.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hCO-RE relocations are applied to BPF instructions to update immediate or offset fields of the instruction at load time with information relevant for target kernel.h]hCO-RE relocations are applied to BPF instructions to update immediate or offset fields of the instruction at load time with information relevant for target kernel.}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh)}(h;Field to patch is selected basing on the instruction class:h]h;Field to patch is selected basing on the instruction class:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjhhubh bullet_list)}(hhh](h list_item)}(hf, BPF_CORE_FIELD_SIGNED) off = relo(s->f, BPF_CORE_FIELD_BYTE_OFFSET) sz = relo(s->f, BPF_CORE_FIELD_BYTE_SIZE) l = relo(s->f, BPF_CORE_FIELD_LSHIFT_U64) r = relo(s->f, BPF_CORE_FIELD_RSHIFT_U64) // define ``v`` as signed or unsigned integer of size ``sz`` v = *({s|u} *)((void *)s + off) v <<= l v >>= r h](h)}(h``BPF_CORE_FIELD_LSHIFT_U64`` and ``BPF_CORE_FIELD_RSHIFT_U64`` are supposed to be used to read bitfield values using the following algorithm:h](jA)}(h``BPF_CORE_FIELD_LSHIFT_U64``h]hBPF_CORE_FIELD_LSHIFT_U64}(hj# hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh and }(hj hhhNhNubjA)}(h``BPF_CORE_FIELD_RSHIFT_U64``h]hBPF_CORE_FIELD_RSHIFT_U64}(hj5 hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubhO are supposed to be used to read bitfield values using the following algorithm:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhM2hj ubj )}(hXz// To read bitfield ``f`` from ``struct s`` is_signed = relo(s->f, BPF_CORE_FIELD_SIGNED) off = relo(s->f, BPF_CORE_FIELD_BYTE_OFFSET) sz = relo(s->f, BPF_CORE_FIELD_BYTE_SIZE) l = relo(s->f, BPF_CORE_FIELD_LSHIFT_U64) r = relo(s->f, BPF_CORE_FIELD_RSHIFT_U64) // define ``v`` as signed or unsigned integer of size ``sz`` v = *({s|u} *)((void *)s + off) v <<= l v >>= rh]hXz// To read bitfield ``f`` from ``struct s`` is_signed = relo(s->f, BPF_CORE_FIELD_SIGNED) off = relo(s->f, BPF_CORE_FIELD_BYTE_OFFSET) sz = relo(s->f, BPF_CORE_FIELD_BYTE_SIZE) l = relo(s->f, BPF_CORE_FIELD_LSHIFT_U64) r = relo(s->f, BPF_CORE_FIELD_RSHIFT_U64) // define ``v`` as signed or unsigned integer of size ``sz`` v = *({s|u} *)((void *)s + off) v <<= l v >>= r}hjM sbah}(h]h ]h"]h$]h&]hhj j j j }uh1j hhhM6hj ubeh}(h]h ]h"]h$]h&]uh1jhj hhhNhNubj)}(hXThe ``BPF_CORE_TYPE_MATCHES`` queries matching relation, defined as follows: * for integers: types match if size and signedness match; * for arrays & pointers: target types are recursively matched; * for structs & unions: * local members need to exist in target with the same name; * for each member we recursively check match unless it is already behind a pointer, in which case we only check matching names and compatible kind; * for enums: * local variants have to have a match in target by symbolic name (but not numeric value); * size has to match (but enum may match enum64 and vice versa); * for function pointers: * number and position of arguments in local type has to match target; * for each argument and the return value we recursively check match. h](h)}(hLThe ``BPF_CORE_TYPE_MATCHES`` queries matching relation, defined as follows:h](hThe }(hjf hhhNhNubjA)}(h``BPF_CORE_TYPE_MATCHES``h]hBPF_CORE_TYPE_MATCHES}(hjn hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjf ubh/ queries matching relation, defined as follows:}(hjf hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMChjb ubj)}(hhh](j)}(h7for integers: types match if size and signedness match;h]h)}(hj h]h7for integers: types match if size and signedness match;}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMFhj ubah}(h]h ]h"]h$]h&]uh1jhj ubj)}(hsize has to match (but enum may match enum64 and vice versa); h]h)}(h=size has to match (but enum may match enum64 and vice versa);h]h=size has to match (but enum may match enum64 and vice versa);}(hj9 hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMThj5 ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhMQhj ubeh}(h]h ]h"]h$]h&]uh1jhj ubj)}(hfor function pointers: * number and position of arguments in local type has to match target; * for each argument and the return value we recursively check match. h](h)}(hfor function pointers:h]hfor function pointers:}(hj] hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMVhjY ubj)}(hhh](j)}(hCnumber and position of arguments in local type has to match target;h]h)}(hjp h]hCnumber and position of arguments in local type has to match target;}(hjr hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMXhjn ubah}(h]h ]h"]h$]h&]uh1jhjk ubj)}(hCfor each argument and the return value we recursively check match. h]h)}(hBfor each argument and the return value we recursively check match.h]hBfor each argument and the return value we recursively check match.}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMYhj ubah}(h]h ]h"]h$]h&]uh1jhjk ubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhMXhjY ubeh}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhMFhjb ubeh}(h]h ]h"]h$]h&]uh1jhj hhhNhNubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhM2hjy hhubeh}(h]relocation-kindsah ]h"]relocation kindsah$]h&]uh1hhjhhhhhM ubh)}(hhh](h)}(hCO-RE Relocation Recordh]hCO-RE Relocation Record}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj hhhhhM\ubh)}(h8Relocation record is encoded as the following structure:h]h8Relocation record is encoded as the following structure:}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhM^hj hhubj )}(hstruct bpf_core_relo { __u32 insn_off; __u32 type_id; __u32 access_str_off; enum bpf_core_relo_kind kind; };h]hstruct bpf_core_relo { __u32 insn_off; __u32 type_id; __u32 access_str_off; enum bpf_core_relo_kind kind; };}hj sbah}(h]h ]h"]h$]h&]hhj j j j }uh1j hhhM`hj hhubj)}(hhh](j)}(hd``insn_off`` - instruction offset (in bytes) within a code section associated with this relocation; h]h)}(hc``insn_off`` - instruction offset (in bytes) within a code section associated with this relocation;h](jA)}(h ``insn_off``h]hinsn_off}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubhW - instruction offset (in bytes) within a code section associated with this relocation;}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMihj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(h\``type_id`` - BTF type ID of the "root" (containing) entity of a relocatable type or field; h]h)}(h[``type_id`` - BTF type ID of the "root" (containing) entity of a relocatable type or field;h](jA)}(h ``type_id``h]htype_id}(hj" hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubhT - BTF type ID of the “root” (containing) entity of a relocatable type or field;}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMlhj ubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubj)}(hX``access_str_off`` - offset into corresponding .BTF string section. String interpretation depends on specific relocation kind: * for field-based relocations, string encodes an accessed field using a sequence of field and array indices, separated by colon (:). It's conceptually very close to LLVM's `getelementptr `_ instruction's arguments for identifying offset to a field. For example, consider the following C code: .. code-block:: c struct sample { int a; int b; struct { int c[10]; }; } __attribute__((preserve_access_index)); struct sample *s; * Access to ``s[0].a`` would be encoded as ``0:0``: * ``0``: first element of ``s`` (as if ``s`` is an array); * ``0``: index of field ``a`` in ``struct sample``. * Access to ``s->a`` would be encoded as ``0:0`` as well. * Access to ``s->b`` would be encoded as ``0:1``: * ``0``: first element of ``s``; * ``1``: index of field ``b`` in ``struct sample``. * Access to ``s[1].c[5]`` would be encoded as ``1:2:0:5``: * ``1``: second element of ``s``; * ``2``: index of anonymous structure field in ``struct sample``; * ``0``: index of field ``c`` in anonymous structure; * ``5``: access to array element #5. * for type-based relocations, string is expected to be just "0"; * for enum value-based relocations, string contains an index of enum value within its enum type; h](h)}(h~``access_str_off`` - offset into corresponding .BTF string section. String interpretation depends on specific relocation kind:h](jA)}(h``access_str_off``h]haccess_str_off}(hjH hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjD ubhl - offset into corresponding .BTF string section. String interpretation depends on specific relocation kind:}(hjD hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMohj@ ubj)}(hhh](j)}(hX@for field-based relocations, string encodes an accessed field using a sequence of field and array indices, separated by colon (:). It's conceptually very close to LLVM's `getelementptr `_ instruction's arguments for identifying offset to a field. For example, consider the following C code: .. code-block:: c struct sample { int a; int b; struct { int c[10]; }; } __attribute__((preserve_access_index)); struct sample *s; * Access to ``s[0].a`` would be encoded as ``0:0``: * ``0``: first element of ``s`` (as if ``s`` is an array); * ``0``: index of field ``a`` in ``struct sample``. * Access to ``s->a`` would be encoded as ``0:0`` as well. * Access to ``s->b`` would be encoded as ``0:1``: * ``0``: first element of ``s``; * ``1``: index of field ``b`` in ``struct sample``. * Access to ``s[1].c[5]`` would be encoded as ``1:2:0:5``: * ``1``: second element of ``s``; * ``2``: index of anonymous structure field in ``struct sample``; * ``0``: index of field ``c`` in anonymous structure; * ``5``: access to array element #5. h](h)}(hX(for field-based relocations, string encodes an accessed field using a sequence of field and array indices, separated by colon (:). It's conceptually very close to LLVM's `getelementptr `_ instruction's arguments for identifying offset to a field. For example, consider the following C code:h](hfor field-based relocations, string encodes an accessed field using a sequence of field and array indices, separated by colon (:). It’s conceptually very close to LLVM’s }(hjg hhhNhNubh reference)}(h`getelementptr `_h]h getelementptr}(hjq hhhNhNubah}(h]h ]h"]h$]h&]name getelementptrrefurih]h}(h]h ]h"] getelementptrah$]h&]j j uh1jjindirect_reference_nameGEPhjg j Kubhi instruction’s arguments for identifying offset to a field. For example, consider the following C code:}(hjg hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMrhjc ubj )}(h|struct sample { int a; int b; struct { int c[10]; }; } __attribute__((preserve_access_index)); struct sample *s;h]h|struct sample { int a; int b; struct { int c[10]; }; } __attribute__((preserve_access_index)); struct sample *s;}hj sbah}(h]h ]h"]h$]h&]hhj j j j }uh1j hhhMxhjc ubj)}(hhh](j)}(hAccess to ``s[0].a`` would be encoded as ``0:0``: * ``0``: first element of ``s`` (as if ``s`` is an array); * ``0``: index of field ``a`` in ``struct sample``. h](h)}(h1Access to ``s[0].a`` would be encoded as ``0:0``:h](h Access to }(hj hhhNhNubjA)}(h ``s[0].a``h]hs[0].a}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh would be encoded as }(hj hhhNhNubjA)}(h``0:0``h]h0:0}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubj)}(hhh](j)}(h8``0``: first element of ``s`` (as if ``s`` is an array);h]h)}(hj h](jA)}(h``0``h]h0}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh: first element of }(hj hhhNhNubjA)}(h``s``h]hs}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh (as if }(hj hhhNhNubjA)}(h``s``h]hs}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh is an array);}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhj ubj)}(h2``0``: index of field ``a`` in ``struct sample``. h]h)}(h1``0``: index of field ``a`` in ``struct sample``.h](jA)}(h``0``h]h0}(hj7 hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj3 ubh: index of field }(hj3 hhhNhNubjA)}(h``a``h]ha}(hjI hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj3 ubh in }(hj3 hhhNhNubjA)}(h``struct sample``h]h struct sample}(hj[ hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj3 ubh.}(hj3 hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj/ ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhMhj ubeh}(h]h ]h"]h$]h&]uh1jhj ubj)}(h7Access to ``s->a`` would be encoded as ``0:0`` as well.h]h)}(hj h](h Access to }(hj hhhNhNubjA)}(h``s->a``h]hs->a}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh would be encoded as }(hj hhhNhNubjA)}(h``0:0``h]h0:0}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh as well.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhj ubj)}(hAccess to ``s->b`` would be encoded as ``0:1``: * ``0``: first element of ``s``; * ``1``: index of field ``b`` in ``struct sample``. h](h)}(h/Access to ``s->b`` would be encoded as ``0:1``:h](h Access to }(hj hhhNhNubjA)}(h``s->b``h]hs->b}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh would be encoded as }(hj hhhNhNubjA)}(h``0:1``h]h0:1}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh:}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubj)}(hhh](j)}(h``0``: first element of ``s``;h]h)}(hj h](jA)}(h``0``h]h0}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh: first element of }(hj hhhNhNubjA)}(h``s``h]hs}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj ubh;}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhj ubj)}(h2``1``: index of field ``b`` in ``struct sample``. h]h)}(h1``1``: index of field ``b`` in ``struct sample``.h](jA)}(h``1``h]h1}(hj8hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj4ubh: index of field }(hj4hhhNhNubjA)}(h``b``h]hb}(hjJhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj4ubh in }(hj4hhhNhNubjA)}(h``struct sample``h]h struct sample^F}(hj\hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj4ubh.}(hj4hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj0ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhMhj ubeh}(h]h ]h"]h$]h&]uh1jhj ubj)}(hAccess to ``s[1].c[5]`` would be encoded as ``1:2:0:5``: * ``1``: second element of ``s``; * ``2``: index of anonymous structure field in ``struct sample``; * ``0``: index of field ``c`` in anonymous structure; * ``5``: access to array element #5. h](h)}(h8Access to ``s[1].c[5]`` would be encoded as ``1:2:0:5``:h](h Access to }(hjhhhNhNubjA)}(h ``s[1].c[5]``h]h s[1].c[5]}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh would be encoded as }(hjhhhNhNubjA)}(h ``1:2:0:5``h]h1:2:0:5}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjubj)}(hhh](j)}(h``1``: second element of ``s``;h]h)}(hjh](jA)}(h``1``h]h1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh: second element of }(hjhhhNhNubjA)}(h``s``h]hs}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh;}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h?``2``: index of anonymous structure field in ``struct sample``;h]h)}(hjh](jA)}(h``2``h]h2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh(: index of anonymous structure field in }(hjhhhNhNubjA)}(h``struct sample``h]h struct sample}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh;}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h3``0``: index of field ``c`` in anonymous structure;h]h)}(hj/h](jA)}(h``0``h]h0}(hj4hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj1ubh: index of field }(hj1hhhNhNubjA)}(h``c``h]hc}(hjFhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hj1ubh in anonymous structure;}(hj1hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj-ubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h#``5``: access to array element #5. h]h)}(h"``5``: access to array element #5.h](jA)}(h``5``h]h5}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjhubh: access to array element #5.}(hjhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjdubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhMhjubeh}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhMhjc ubeh}(h]h ]h"]h$]h&]uh1jhj` ubj)}(h?for type-based relocations, string is expected to be just "0"; h]h)}(h>for type-based relocations, string is expected to be just "0";h]hBfor type-based relocations, string is expected to be just “0”;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jhj` ubj)}(h`for enum value-based relocations, string contains an index of enum value within its enum type; h]hdefinition_list)}(hhh]hdefinition_list_item)}(h_for enum value-based relocations, string contains an index of enum value within its enum type; h](hterm)}(hBfor enum value-based relocations, string contains an index of enumh]hBfor enum value-based relocations, string contains an index of enum}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1jhhhMhjubh definition)}(hhh]h)}(hvalue within its enum type;h]hvalue within its enum type;}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]uh1jhhhMhjubah}(h]h ]h"]h$]h&]uh1jhjubah}(h]h ]h"]h$]h&]uh1jhj` ubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhMrhj@ ubeh}(h]h ]h"]h$]h&]uh1jhj hhhNhNubj)}(h/``kind`` - one of ``enum bpf_core_relo_kind``. h]h)}(h.``kind`` - one of ``enum bpf_core_relo_kind``.h](jA)}(h``kind``h]hkind}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh - one of }(hjhhhNhNubjA)}(h``enum bpf_core_relo_kind``h]henum bpf_core_relo_kind}(hj*hhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jhj hhhhhNubeh}(h]h ]h"]h$]h&]jw jx uh1jhhhMihj hhubjk)}(hE.. _GEP: https://llvm.org/docs/LangRef.html#getelementptr-instructionh]h}(h]gepah ]h"]gepah$]h&]j j uh1jjhMhj hhhhnj referencedKubjk)}(h".. _btf_co_re_relocation_examples:h]h}(h]h ]h"]h$]h&]jvbtf-co-re-relocation-examplesuh1jjhMhj hhhhubeh}(h]co-re-relocation-recordah ]h"]co-re relocation recordah$]h&]uh1hhjhhhhhM\ubh)}(hhh](h)}(hCO-RE Relocation Examplesh]hCO-RE Relocation Examples}(hjqhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjnhhhhhMubh)}(hFor the following C code:h]hFor the following C code:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjnhhubj )}(hmstruct foo { int a; int b; unsigned c:15; } __attribute__((preserve_access_index)); enum bar { U, V };h]hmstruct foo { int a; int b; unsigned c:15; } __attribute__((preserve_access_index)); enum bar { U, V };}hjsbah}(h]h ]h"]h$]h&]hhj j j j }uh1j hhhMhjnhhubh)}(h#With the following BTF definitions:h]h#With the following BTF definitions:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjnhhubj )}(hXy... [2] STRUCT 'foo' size=8 vlen=2 'a' type_id=3 bits_offset=0 'b' type_id=3 bits_offset=32 'c' type_id=4 bits_offset=64 bitfield_size=15 [3] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED [4] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none) ... [16] ENUM 'bar' encoding=UNSIGNED size=4 vlen=2 'U' val=0 'V' val=1h]hXy... [2] STRUCT 'foo' size=8 vlen=2 'a' type_id=3 bits_offset=0 'b' type_id=3 bits_offset=32 'c' type_id=4 bits_offset=64 bitfield_size=15 [3] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED [4] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none) ... [16] ENUM 'bar' encoding=UNSIGNED size=4 vlen=2 'U' val=0 'V' val=1}hjsbah}(h]h ]h"]h$]h&]hhj j nonej }uh1j hhhMhjnhhubh)}(hzField offset relocations are generated automatically when ``__attribute__((preserve_access_index))`` is used, for example:h](h:Field offset relocations are generated automatically when }(hjhhhNhNubjA)}(h*``__attribute__((preserve_access_index))``h]h&__attribute__((preserve_access_index))}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j@hjubh is used, for example:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjnhhubj )}(hX2void alpha(struct foo *s, volatile unsigned long *g) { *g = s->a; s->a = 1; } 00 : 0: r3 = *(s32 *)(r1 + 0x0) 00: CO-RE [2] struct foo::a (0:0) 1: *(u64 *)(r2 + 0x0) = r3 2: *(u32 *)(r1 + 0x0) = 0x1 10: CO-RE [2] struct foo::a (0:0) 3: exith]hX2void alpha(struct foo *s, volatile unsigned long *g) { *g = s->a; s->a = 1; } 00 : 0: r3 = *(s32 *)(r1 + 0x0) 00: CO-RE [2] struct foo::a (0:0) 1: *(u64 *)(r2 + 0x0) = r3 2: *(u32 *)(r1 + 0x0) = 0x1 10: CO-RE [2] struct foo::a (0:0) 3: exit}hjsbah}(h]h ]h"]h$]h&]hhj j j j }uh1j hhhMhjnhhubh)}(h]All relocation kinds could be requested via built-in functions. E.g. field-based relocations:h]h]All relocation kinds could be requested via built-in functions. E.g. field-based relocations:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjnhhubj )}(hXvoid bravo(struct foo *s, volatile unsigned long *g) { *g = __builtin_preserve_field_info(s->b, 0 /* field byte offset */); *g = __builtin_preserve_field_info(s->b, 1 /* field byte size */); *g = __builtin_preserve_field_info(s->b, 2 /* field existence */); *g = __builtin_preserve_field_info(s->b, 3 /* field signedness */); *g = __builtin_preserve_field_info(s->c, 4 /* bitfield left shift */); *g = __builtin_preserve_field_info(s->c, 5 /* bitfield right shift */); } 20 : 4: r1 = 0x4 20: CO-RE [2] struct foo::b (0:1) 5: *(u64 *)(r2 + 0x0) = r1 6: r1 = 0x4 30: CO-RE [2] struct foo::b (0:1) 7: *(u64 *)(r2 + 0x0) = r1 8: r1 = 0x1 40: CO-RE [2] struct foo::b (0:1) 9: *(u64 *)(r2 + 0x0) = r1 10: r1 = 0x1 50: CO-RE [2] struct foo::b (0:1) 11: *(u64 *)(r2 + 0x0) = r1 12: r1 = 0x31 60: CO-RE [2] struct foo::c (0:2) 13: *(u64 *)(r2 + 0x0) = r1 14: r1 = 0x31 70: CO-RE [2] struct foo::c (0:2) 15: *(u64 *)(r2 + 0x0) = r1 16: exith]hXvoid bravo(struct foo *s, volatile unsigned long *g) { *g = __builtin_preserve_field_info(s->b, 0 /* field byte offset */); *g = __builtin_preserve_field_info(s->b, 1 /* field byte size */); *g = __builtin_preserve_field_info(s->b, 2 /* field existence */); *g = __builtin_preserve_field_info(s->b, 3 /* field signedness */); *g = __builtin_preserve_field_info(s->c, 4 /* bitfield left shift */); *g = __builtin_preserve_field_info(s->c, 5 /* bitfield right shift */); } 20 : 4: r1 = 0x4 20: CO-RE [2] struct foo::b (0:1) 5: *(u64 *)(r2 + 0x0) = r1 6: r1 = 0x4 30: CO-RE [2] struct foo::b (0:1) 7: *(u64 *)(r2 + 0x0) = r1 8: r1 = 0x1 40: CO-RE [2] struct foo::b (0:1) 9: *(u64 *)(r2 + 0x0) = r1 10: r1 = 0x1 50: CO-RE [2] struct foo::b (0:1) 11: *(u64 *)(r2 + 0x0) = r1 12: r1 = 0x31 60: CO-RE [2] struct foo::c (0:2) 13: *(u64 *)(r2 + 0x0) = r1 14: r1 = 0x31 70: CO-RE [2] struct foo::c (0:2) 15: *(u64 *)(r2 + 0x0) = r1 16: exit}hjsbah}(h]h ]h"]h$]h&]hhj j j j }uh1j hhhMhjnhhubh)}(hType-based relocations:h]hType-based relocations:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjnhhubj )}(hXvoid charlie(struct foo *s, volatile unsigned long *g) { *g = __builtin_preserve_type_info(*s, 0 /* type existence */); *g = __builtin_preserve_type_info(*s, 1 /* type size */); *g = __builtin_preserve_type_info(*s, 2 /* type matches */); *g = __builtin_btf_type_id(*s, 0 /* type id in this object file */); *g = __builtin_btf_type_id(*s, 1 /* type id in target kernel */); } 88 : 17: r1 = 0x1 88: CO-RE [2] struct foo 18: *(u64 *)(r2 + 0x0) = r1 19: r1 = 0xc 98: CO-RE [2] struct foo 20: *(u64 *)(r2 + 0x0) = r1 21: r1 = 0x1 a8: CO-RE [2] struct foo 22: *(u64 *)(r2 + 0x0) = r1 23: r1 = 0x2 ll b8: CO-RE [2] struct foo 25: *(u64 *)(r2 + 0x0) = r1 26: r1 = 0x2 ll d0: CO-RE [2] struct foo 28: *(u64 *)(r2 + 0x0) = r1 29: exith]hXvoid charlie(struct foo *s, volatile unsigned long *g) { *g = __builtin_preserve_type_info(*s, 0 /* type existence */); *g = __builtin_preserve_type_info(*s, 1 /* type size */); *g = __builtin_preserve_type_info(*s, 2 /* type matches */); *g = __builtin_btf_type_id(*s, 0 /* type id in this object file */); *g = __builtin_btf_type_id(*s, 1 /* type id in target kernel */); } 88 : 17: r1 = 0x1 88: CO-RE [2] struct foo 18: *(u64 *)(r2 + 0x0) = r1 19: r1 = 0xc 98: CO-RE [2] struct foo 20: *(u64 *)(r2 + 0x0) = r1 21: r1 = 0x1 a8: CO-RE [2] struct foo 22: *(u64 *)(r2 + 0x0) = r1 23: r1 = 0x2 ll b8: CO-RE [2] struct foo 25: *(u64 *)(r2 + 0x0) = r1 26: r1 = 0x2 ll d0: CO-RE [2] struct foo 28: *(u64 *)(r2 + 0x0) = r1 29: exit}hjsbah}(h]h ]h"]h$]h&]hhj j j j }uh1j hhhMhjnhhubh)}(hEnum-based relocations:h]hEnum-based relocations:}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjnhhubj )}(hXvoid delta(struct foo *s, volatile unsigned long *g) { *g = __builtin_preserve_enum_value(*(enum bar *)U, 0 /* enum literal existence */); *g = __builtin_preserve_enum_value(*(enum bar *)V, 1 /* enum literal value */); } f0 : 30: r1 = 0x1 ll f0: CO-RE [16] enum bar::U = 0 32: *(u64 *)(r2 + 0x0) = r1 33: r1 = 0x1 ll 108: CO-RE [16] enum bar::V = 1 35: *(u64 *)(r2 + 0x0) = r1 36: exith]hXvoid delta(struct foo *s, volatile unsigned long *g) { *g = __builtin_preserve_enum_value(*(enum bar *)U, 0 /* enum literal existence */); *g = __builtin_preserve_enum_value(*(enum bar *)V, 1 /* enum literal value */); } f0 : 30: r1 = 0x1 ll f0: CO-RE [16] enum bar::U = 0 32: *(u64 *)(r2 + 0x0) = r1 33: r1 = 0x1 ll 108: CO-RE [16] enum bar::V = 1 35: *(u64 *)(r2 + 0x0) = r1 36: exit}hj1sbah}(h]h ]h"]h$]h&]hhj j j j }uh1j hhhMhjnhhubeh}(h](co-re-relocation-examplesjeeh ]h"](co-re relocation examplesbtf_co_re_relocation_exampleseh$]h&]uh1hhjhhhhhMexpect_referenced_by_name}jFj[sexpect_referenced_by_id}jej[subeh}(h](co-re-relocationsjweh ]h"](co-re relocationsbtf-co-re-relocationseh$]h&]uh1hhhhhhhhKjI}jSjlsjK}jwjlsubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerj{error_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourcehnj _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]j asubstitution_defs}substitution_names}refnames}gep](j jq esrefids}(jw]jlaje]j[aunameids}(jjjjjjj}jzjSjwjRjOj j jkjhjWjTjFjejEjBu nametypes}(jjjj}jSjRj jkjWjFjEuh}(jhjhjjjzjjwjjOjj jy jhj jTjNjejnjBjnu footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}Rparse_messages]transform_messages](hsystem_message)}(hhh]h)}(hhh]h;Hyperlink target "btf-co-re-relocations" is not referenced.}hjsbah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypeINFOsourcehnjlineKuh1jubj)}(hhh]h)}(hhh]h3Hyperlink target "getelementptr" is not referenced.}hjsbah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypejsourcehnjlineMruh1jubj)}(hhh]h)}(hhh]hCHyperlink target "btf-co-re-relocation-examples" is not referenced.}hjsbah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypejsourcehnjlineMuh1jube transformerN include_log] decorationNhhub.