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]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:spacepreserveuh1hhhhhhhhhhubh)}(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}hjsbah}(h]h ]h"]h$]h&]hhuh1hhhhKDhhhhubh)}(h5The 6th entry is global variable ``g1`` with value 0.h](h!The 6th entry is global variable }(hjhhhNhNubj-)}(h``g1``h]hg1}(hj$hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh with value 0.}(hjhhhNhNubeh}(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 }(hj<hhhNhNubj-)}(h ``.text``h]h.text}(hjDhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj<ubh offset }(hj<hhhNhNubj-)}(h``0x18``h]h0x18}(hjVhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj<ubh, instruction 3, has a type of }(hj<hhhNhNubj-)}(h``R_BPF_64_64``h]h R_BPF_64_64}(hjhhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj<ubh^ and refers to entry 7 in the symbol table. The second relocation resolves to global variable }(hj<hhhNhNubj-)}(h``g2``h]hg2}(hjzhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj<ubhV which has a symbol value 4. The symbol value represents the offset from the start of }(hj<hhhNhNubj-)}(h ``.data``h]h.data}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj<ubh8 section where the initial value of the global variable }(hj<hhhNhNubj-)}(h``g2``h]hg2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj<ubh is stored.}(hj<hhhNhNubeh}(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 }(hjhhhNhNubj-)}(h``l1``h]hl1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }(hjhhhNhNubj-)}(h``l2``h]hl2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh . From the }(hjhhhNhNubj-)}(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 }(hjhhhNhNubj-)}(h``sec``h]hsec}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh , which has }(hjhhhNhNubj-)}(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 }(hjhhhNhNubj-)}(h``A``h]hA}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh! (addend). Looking at above insn }(hjhhhNhNubj-)}(h``7``h]h7}(hj*hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }(hjhhhNhNubj-)}(h``11``h]h11}(hj<hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh, they have section offset }(hjhhhNhNubj-)}(h``8``h]h8}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }hjsbj-)}(h``12``h]h12}(hj`hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubhA. From symbol table, we can find that they correspond to entries }(hjhhhNhNubj-)}(h``2``h]h2}(hjrhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }hjsbj-)}(h``3``h]h3}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh for }(hjhhhNhNubj-)}(h``l1``h]hl1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }hjsbj-)}(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 }(hjhhhNhNubj-)}(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 }(hjhhhNhNubj-)}(h``S``h]hS}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh8 represents the value of the symbol in the symbol table:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKjhjhhubh)}(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}hjsbah}(h]h ]h"]h$]h&]hhuh1hhhhKmhjhhubh)}(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'hhhNhNubj-)}(h``R_BPF_64_64``h]h R_BPF_64_64}(hj/hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj'ubh relocation type is used for }(hj'hhhNhNubj-)}(h ``ld_imm64``h]hld_imm64}(hjAhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj'ubhQ instruction. The actual to-be-relocated data (0 or section offset) is stored at }(hj'hhhNhNubj-)}(h``r_offset + 4``h]h r_offset + 4}(hjShhhNhNubah}(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'hhhNhNubj-)}(h ``BitSize``h]hBitSize}(hjehhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj'ubhD is 32 which means the section offset must be less than or equal to }(hj'hhhNhNubj-)}(h``UINT32_MAX``h]h UINT32_MAX}(hjwhhhNhNubah}(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, }(hjhhhNhNubj-)}(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 }(hjhhhNhNubj-)}(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 }(hjhhhNhNubj-)}(h``R_BPF_64_ABS32``h]hR_BPF_64_ABS32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }(hjhhhNhNubj-)}(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 }(hjhhhNhNubj-)}(h``R_BPF_64_NODYLD32``h]hR_BPF_64_NODYLD32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh' specifically refers to relocations in }(hjhhhNhNubj-)}(h``.BTF``h]h.BTF}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }(hjhhhNhNubj-)}(h ``.BTF.ext``h]h.BTF.ext}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh) sections. For cases like bcc where llvm }(hjhhhNhNubj-)}(h``ExecutionEngine RuntimeDyld``h]hExecutionEngine RuntimeDyld}(hj#hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh is involved, }(hjhhhNhNubj-)}(h``R_BPF_64_NODYLD32``h]hR_BPF_64_NODYLD32}(hj5hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh] types of relocations should not be resolved to actual function/variable address. Otherwise, }(hjhhhNhNubj-)}(h``.BTF``h]h.BTF}(hjGhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }hjsbj-)}(h ``.BTF.ext``h]h.BTF.ext}(hjYhhhNhNubah}(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 }(hjqhhhNhNubj-)}(h``R_BPF_64_32``h]h R_BPF_64_32}(hjyhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjqubhK is used for call instruction. The call target section offset is stored at }(hjqhhhNhNubj-)}(h``r_offset + 4``h]h r_offset + 4}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjqubh (32bit) and calculated as }(hjqhhhNhNubj-)}(h``(S + A) / 8 - 1``h]h(S + A) / 8 - 1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjqubh.}(hjqhhhNhNubeh}(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 }(hjhhhNhNubj-)}(h``R_BPF_64_64``h]h R_BPF_64_64}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }(hjhhhNhNubj-)}(h``R_BPF_64_32``h]h R_BPF_64_32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh are used to resolve }(hjhhhNhNubj-)}(h ``ld_imm64``h]hld_imm64}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }(hjhhhNhNubj-)}(h``call``h]hcall}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh instructions. For example:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(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; }}hj$sbah}(h]h ]h"]h$]h&]hhuh1hhhhKhjhhubh)}(hqCompiled with ``clang --target=bpf -O2 -c test.c``, we will have following code with `llvm-objdump -dr test.o``::h](hCompiled with }(hj2hhhNhNubj-)}(h$``clang --target=bpf -O2 -c test.c``h]h clang --target=bpf -O2 -c test.c}(hj:hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj2ubh#, we will have following code with }(hj2hhhNhNubhtitle_reference)}(h`llvm-objdump -dr test.o``h]hllvm-objdump -dr test.o`}(hjNhhhNhNubah}(h]h ]h"]h$]h&]uh1jLhj2ubh:}(hj2hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(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}hjfsbah}(h]h ]h"]h$]h&]hhuh1hhhhKhjhhubh)}(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 }(hjthhhNhNubj-)}(h``gfunc(a, b)``h]h gfunc(a, b)}(hj|hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh where }(hjthhhNhNubj-)}(h ``gfunc``h]hgfunc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh has a value of 0, so the }(hjthhhNhNubj-)}(h``call``h]hcall}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh instruction offset is }(hjthhhNhNubj-)}(h``(0 + 0)/8 - 1 = -1``h]h(0 + 0)/8 - 1 = -1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh'. The second relocation corresponds to }(hjthhhNhNubj-)}(h``lfunc(a, b)``h]h lfunc(a, b)}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh where }hjtsbj-)}(h ``lfunc``h]hlfunc}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh has a section offset }(hjthhhNhNubj-)}(h``0x18``h]h0x18}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh , so the }(hjthhhNhNubj-)}(h``call``h]hcall}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh instruction offset is }hjtsbj-)}(h``(0 + 0x18)/8 - 1 = 2``h]h(0 + 0x18)/8 - 1 = 2}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh2. The third relocation corresponds to ld_imm64 of }(hjthhhNhNubj-)}(h ``global``h]hglobal}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh, which has a section offset }(hjthhhNhNubj-)}(h``0``h]h0}(hj0hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjtubh.}(hjthhhNhNubeh}(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:}(hjHhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hBint global() { return 0; } struct t { void *g; } gbl = { global };h]hBint global() { return 0; } struct t { void *g; } gbl = { global };}hjVsbah}(h]h ]h"]h$]h&]hhuh1hhhhKhjhhubh)}(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 }(hjdhhhNhNubj-)}(h'``clang --target=bpf -O2 -g -c test.c``h]h#clang --target=bpf -O2 -g -c test.c}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjdubh$, we will see a relocation below in }(hjdhhhNhNubj-)}(h ``.data``h]h.data}(hj~hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjdubh section with command }(hjdhhhNhNubj-)}(h``llvm-readelf -r test.o``h]hllvm-readelf -r test.o}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjdubh:}(hjdhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(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&]hhuh1hhhhKhjhhubh)}(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 }(hjhhhNhNubj-)}(h ``.data``h]h.data}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh* section should be filled with address of }(hjhhhNhNubj-)}(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 }(hjhhhNhNubj-)}(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 }(hjhhhNhNubj-)}(h``R_BPF_64_ABS32``h]hR_BPF_64_ABS32}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh and }(hjhhhNhNubj-)}(h``R_BPF_64_ABS64``h]hR_BPF_64_ABS64}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh relocations:}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(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&]hhuh1hhhhKhjhhubh)}(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:}(hj:hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(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}hjHsbah}(h]h ]h"]h$]h&]hhuh1hhhhKhjhhubhtarget)}(h.. _btf-co-re-relocations:h]h}(h]h ]h"]h$]h&]refidbtf-co-re-relocationsuh1jVhKhjhhhhubeh}(h]examplesah ]h"]examplesah$]h&]uh1hhhhhhhhKubeh}(h]bpf-llvm-relocationsah ]h"]bpf llvm relocationsah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hCO-RE Relocationsh]hCO-RE Relocations}(hjwhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjthhhhhKubh)}(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&]uh1hhhhKhjthhubh)}(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&]uh1hhhhMhjthhubh)}(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&]uh1hhhhMhjthhubh 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](j-)}(h``BPF_CORE_FIELD_LSHIFT_U64``h]hBPF_CORE_FIELD_LSHIFT_U64}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh and }(hj hhhNhNubj-)}(h``BPF_CORE_FIELD_RSHIFT_U64``h]hBPF_CORE_FIELD_RSHIFT_U64}(hj! 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 ubh)}(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}hj9 sbah}(h]h ]h"]h$]h&]hhj j j j }uh1hhhhM6hj 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 }(hjR hhhNhNubj-)}(h``BPF_CORE_TYPE_MATCHES``h]hBPF_CORE_TYPE_MATCHES}(hjZ hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjR ubh/ queries matching relation, defined as follows:}(hjR hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMChjN ubj)}(hhh](j)}(h7for integers: types match if size and signedness match;h]h)}(hjw h]h7for integers: types match if size and signedness match;}(hjy hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMFhju ubah}(h]h ]h"]h$]h&]uh1jhjr 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);}(hj% hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMThj! ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]jc jd uh1jhhhMQhj ubeh}(h]h ]h"]h$]h&]uh1jhjr 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:}(hjI hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMVhjE ubj)}(hhh](j)}(hCnumber and position of arguments in local type has to match target;h]h)}(hj\ h]hCnumber and position of arguments in local type has to match target;}(hj^ hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMXhjZ ubah}(h]h ]h"]h$]h&]uh1jhjW 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.}(hju hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMYhjq ubah}(h]h ]h"]h$]h&]uh1jhjW ubeh}(h]h ]h"]h$]h&]jc jd uh1jhhhMXhjE ubeh}(h]h ]h"]h$]h&]uh1jhjr ubeh}(h]h ]h"]h$]h&]jc jd uh1jhhhMFhjN ubeh}(h]h ]h"]h$]h&]uh1jhj hhhNhNubeh}(h]h ]h"]h$]h&]jc jd uh1jhhhM2hje hhubeh}(h]relocation-kindsah ]h"]relocation kindsah$]h&]uh1hhjthhhhhM 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 hhubh)}(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 }uh1hhhhM`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](j-)}(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](j-)}(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](j-)}(h``access_str_off``h]haccess_str_off}(hj4 hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj0 ubhl - offset into corresponding .BTF string section. String interpretation depends on specific relocation kind:}(hj0 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 }(hjS hhhNhNubh reference)}(h`getelementptr `_h]h getelementptr}(hj] hhhNhNubah}(h]h ]h"]h$]h&]name getelementptrrefurih]h}(h]h ]h"] getelementptrah$]h&]jm jn uh1jVindirect_reference_nameGEPhjS jo Kubhi instruction’s arguments for identifying offset to a field. For example, consider the following C code:}(hjS hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMrhjO ubh)}(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 }uh1hhhhMxhjO 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 hhhNhNubj-)}(h ``s[0].a``h]hs[0].a}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh would be encoded as }(hj hhhNhNubj-)}(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](j-)}(h``0``h]h0}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh: first element of }(hj hhhNhNubj-)}(h``s``h]hs}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh (as if }(hj hhhNhNubj-)}(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](j-)}(h``0``h]h0}(hj# hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh: index of field }(hj hhhNhNubj-)}(h``a``h]ha}(hj5 hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh in }(hj hhhNhNubj-)}(h``struct sample``h]h struct sample}(hjG hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhj ubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]jc jd uh1jhhhMhj ubeh}(h]h ]h"]h$]h&]uh1jhj ubj)}(h7Access to ``s->a`` would be encoded as ``0:0`` as well.h]h)}(hjs h](h Access to }(hju hhhNhNubj-)}(h``s->a``h]hs->a}(hj| hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hju ubh would be encoded as }(hju hhhNhNubj-)}(h``0:0``h]h0:0}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hju ubh as well.}(hju hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjq 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 hhhNhNubj-)}(h``s->b``h]hs->b}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh would be encoded as }(hj hhhNhNubj-)}(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](j-)}(h``0``h]h0}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh: first element of }(hj hhhNhNubj-)}(h``s``h]hs}(hj hhhNhNubah}(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](j-)}(h``1``h]h1}(hj$hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh: index of field }(hj hhhNhNubj-)}(h``b``h]hb}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh in }(hj hhhNhNubj-)}(h``struct sample``h]h struct sample}(hjHhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hj ubh.}(hj hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]jc jd uh1jhhhMhj ubeh}(h]h ]h"]h$]h&]uh1jEhj 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 }(hjvhhhNhNubj-)}(h ``s[1].c[5]``h]h s[1].c[5]}(hj~hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjvubh would be encoded as }(hjvhhhNhNubj-)}(h ``1:2:0:5``h]h1:2:0:5}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjvubh:}(hjvhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjrubj)}(hhh](j)}(h``1``: second element of ``s``;h]h)}(hjh](j-)}(h``1``h]h1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh: second element of }(hjhhhNhNubj-)}(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](j-)}(h``2``h]h2}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh(: index of anonymous structure field in }(hjhhhNhNubj-)}(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)}(hjh](j-)}(h``0``h]h0}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh: index of field }(hjhhhNhNubj-)}(h``c``h]hc}(hj2hhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh in anonymous structure;}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjubah}(h]h ]h"]h$]h&]uh1jhjubj)}(h#``5``: access to array element #5. h]h)}(h"``5``: access to array element #5.h](j-)}(h``5``h]h5}(hjXhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjTubh: access to array element #5.}(hjThhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhMhjPubah}(h]h ]h"]h$]h&]uh1jhjubeh}(h]h ]h"]h$]h&]jc jd uh1jhhhMhjrubeh}(h]h ]h"]h$]h&]uh1jhj ubeh}(h]h ]h"]h$]h&]jc jd uh1jhhhMhjO ubeh}(h]h ]h"]h$]h&]uh1jhjL 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&]uh1jhjL 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&]uh1jhjL ubeh}(h]h ]h"]h$]h&]jc jd 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](j-)}(h``kind``h]hkind}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1j,hjubh - one of }(hjhhhNhNubj-)}(h``enum bpf_core_relo_kind``h]henum bpf_core_relo_kind}(hjhhhNhNubah}(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&]jc jd uh1jhhhMihj hhubjW)}(hE.. _GEP: https://llvm.org/docs/LangRef.html#getelementptr-instructionh]h}(h]gepah ]h"]gepah$]h&]jm jn uh1jVhMhj hhhh referencedKubjW)}(h".. _btf_co_re_relocation_examples:h]h}(h]h ]h"]h$]h&]jbbtf-co-re-relocation-examplesuh1jVhMhj hhhhubeh}(h]co-re-relocation-recordah ]h"]co-re relocation recordah$]h&]uh1hhjthhhhhM\ubh)}(hhh](h)}(hCO-RE Relocation Examplesh]hCO-RE Relocation Examples}(hj]hhhNhNubah}(h]h ]h"]h$]h&]uh1hhjZhhhhhMubh)}(hFor the following C code:h]hFor the following C code:}(hjkhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjZhhubh)}(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 };}hjysbah}(h]h ]h"]h$]h&]hhj j j j }uh1hhhhMhjZhhubh)}(h#With the following BTF definitions:h]h#With the following BTF definitions:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjZhhubh)}(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 }uh1hhhhMhjZhhubh)}(hzField offset relocations are generated automatically when ``__attribute__((preserve_access_index))`` is used, for example:h](h:Field offset relocations are generated automatically when }(hjhhhNhNubj-)}(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&]uh1hhhhMhjZhhubh)}(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 }uh1hhhhMhjZhhubh)}(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&]uh1hhhhMhjZhhubh)}(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 }uh1hhhhMhjZhhubh)}(hType-based relocations:h]hType-based relocations:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjZhhubh)}(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 }uh1hhhhMhjZhhubh)}(hEnum-based relocations:h]hEnum-based relocations:}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhMhjZhhubh)}(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}hjsbah}(h]h ]h"]h$]h&]hhj j j j }uh1hhhhMhjZhhubeh}(h](co-re-relocation-examplesjQeh ]h"](co-re relocation examplesbtf_co_re_relocation_exampleseh$]h&]uh1hhjthhhhhMexpect_referenced_by_name}j2jGsexpect_referenced_by_id}jQjGsubeh}(h](co-re-relocationsjceh ]h"](co-re relocationsbtf-co-re-relocationseh$]h&]uh1hhhhhhhhKj5}j?jXsj7}jcjXsubeh}(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_handlerjgerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _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]jp asubstitution_defs}substitution_names}refnames}gep](jp j] esrefids}(jc]jXajQ]jGaunameids}(jqjnjjjjjijfj?jcj>j;j j jWjTjCj@j2jQj1j.u nametypes}(jqjjjij?j>j jWjCj2j1uh}(jnhjhjjjfjjcjtj;jtj je jTj j@j:jQjZj.jZu 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&]levelKtypeINFOsourcehlineKuh1jubj)}(hhh]h)}(hhh]h3Hyperlink target "getelementptr" is not referenced.}hjsbah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypejsourcehlineMruh1jubj)}(hhh]h)}(hhh]hCHyperlink target "btf-co-re-relocation-examples" is not referenced.}hj sbah}(h]h ]h"]h$]h&]uh1hhjubah}(h]h ]h"]h$]h&]levelKtypejsourcehlineMuh1jube transformerN include_log] decorationNhhub.