Back to home page

OSCL-LXR

 
 

    


0001 .. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
0002 
0003 ====================
0004 BPF LLVM Relocations
0005 ====================
0006 
0007 This document describes LLVM BPF backend relocation types.
0008 
0009 Relocation Record
0010 =================
0011 
0012 LLVM BPF backend records each relocation with the following 16-byte
0013 ELF structure::
0014 
0015   typedef struct
0016   {
0017     Elf64_Addr    r_offset;  // Offset from the beginning of section.
0018     Elf64_Xword   r_info;    // Relocation type and symbol index.
0019   } Elf64_Rel;
0020 
0021 For example, for the following code::
0022 
0023   int g1 __attribute__((section("sec")));
0024   int g2 __attribute__((section("sec")));
0025   static volatile int l1 __attribute__((section("sec")));
0026   static volatile int l2 __attribute__((section("sec")));
0027   int test() {
0028     return g1 + g2 + l1 + l2;
0029   }
0030 
0031 Compiled with ``clang -target bpf -O2 -c test.c``, the following is
0032 the code with ``llvm-objdump -dr test.o``::
0033 
0034        0:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
0035                 0000000000000000:  R_BPF_64_64  g1
0036        2:       61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0)
0037        3:       18 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r2 = 0 ll
0038                 0000000000000018:  R_BPF_64_64  g2
0039        5:       61 20 00 00 00 00 00 00 r0 = *(u32 *)(r2 + 0)
0040        6:       0f 10 00 00 00 00 00 00 r0 += r1
0041        7:       18 01 00 00 08 00 00 00 00 00 00 00 00 00 00 00 r1 = 8 ll
0042                 0000000000000038:  R_BPF_64_64  sec
0043        9:       61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0)
0044       10:       0f 10 00 00 00 00 00 00 r0 += r1
0045       11:       18 01 00 00 0c 00 00 00 00 00 00 00 00 00 00 00 r1 = 12 ll
0046                 0000000000000058:  R_BPF_64_64  sec
0047       13:       61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0)
0048       14:       0f 10 00 00 00 00 00 00 r0 += r1
0049       15:       95 00 00 00 00 00 00 00 exit
0050 
0051 There are four relations in the above for four ``LD_imm64`` instructions.
0052 The following ``llvm-readelf -r test.o`` shows the binary values of the four
0053 relocations::
0054 
0055   Relocation section '.rel.text' at offset 0x190 contains 4 entries:
0056       Offset             Info             Type               Symbol's Value  Symbol's Name
0057   0000000000000000  0000000600000001 R_BPF_64_64            0000000000000000 g1
0058   0000000000000018  0000000700000001 R_BPF_64_64            0000000000000004 g2
0059   0000000000000038  0000000400000001 R_BPF_64_64            0000000000000000 sec
0060   0000000000000058  0000000400000001 R_BPF_64_64            0000000000000000 sec
0061 
0062 Each relocation is represented by ``Offset`` (8 bytes) and ``Info`` (8 bytes).
0063 For example, the first relocation corresponds to the first instruction
0064 (Offset 0x0) and the corresponding ``Info`` indicates the relocation type
0065 of ``R_BPF_64_64`` (type 1) and the entry in the symbol table (entry 6).
0066 The following is the symbol table with ``llvm-readelf -s test.o``::
0067 
0068   Symbol table '.symtab' contains 8 entries:
0069      Num:    Value          Size Type    Bind   Vis       Ndx Name
0070        0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT   UND
0071        1: 0000000000000000     0 FILE    LOCAL  DEFAULT   ABS test.c
0072        2: 0000000000000008     4 OBJECT  LOCAL  DEFAULT     4 l1
0073        3: 000000000000000c     4 OBJECT  LOCAL  DEFAULT     4 l2
0074        4: 0000000000000000     0 SECTION LOCAL  DEFAULT     4 sec
0075        5: 0000000000000000   128 FUNC    GLOBAL DEFAULT     2 test
0076        6: 0000000000000000     4 OBJECT  GLOBAL DEFAULT     4 g1
0077        7: 0000000000000004     4 OBJECT  GLOBAL DEFAULT     4 g2
0078 
0079 The 6th entry is global variable ``g1`` with value 0.
0080 
0081 Similarly, the second relocation is at ``.text`` offset ``0x18``, instruction 3,
0082 for global variable ``g2`` which has a symbol value 4, the offset
0083 from the start of ``.data`` section.
0084 
0085 The third and fourth relocations refers to static variables ``l1``
0086 and ``l2``. From ``.rel.text`` section above, it is not clear
0087 which symbols they really refers to as they both refers to
0088 symbol table entry 4, symbol ``sec``, which has ``STT_SECTION`` type
0089 and represents a section. So for static variable or function,
0090 the section offset is written to the original insn
0091 buffer, which is called ``A`` (addend). Looking at
0092 above insn ``7`` and ``11``, they have section offset ``8`` and ``12``.
0093 From symbol table, we can find that they correspond to entries ``2``
0094 and ``3`` for ``l1`` and ``l2``.
0095 
0096 In general, the ``A`` is 0 for global variables and functions,
0097 and is the section offset or some computation result based on
0098 section offset for static variables/functions. The non-section-offset
0099 case refers to function calls. See below for more details.
0100 
0101 Different Relocation Types
0102 ==========================
0103 
0104 Six relocation types are supported. The following is an overview and
0105 ``S`` represents the value of the symbol in the symbol table::
0106 
0107   Enum  ELF Reloc Type     Description      BitSize  Offset        Calculation
0108   0     R_BPF_NONE         None
0109   1     R_BPF_64_64        ld_imm64 insn    32       r_offset + 4  S + A
0110   2     R_BPF_64_ABS64     normal data      64       r_offset      S + A
0111   3     R_BPF_64_ABS32     normal data      32       r_offset      S + A
0112   4     R_BPF_64_NODYLD32  .BTF[.ext] data  32       r_offset      S + A
0113   10    R_BPF_64_32        call insn        32       r_offset + 4  (S + A) / 8 - 1
0114 
0115 For example, ``R_BPF_64_64`` relocation type is used for ``ld_imm64`` instruction.
0116 The actual to-be-relocated data (0 or section offset)
0117 is stored at ``r_offset + 4`` and the read/write
0118 data bitsize is 32 (4 bytes). The relocation can be resolved with
0119 the symbol value plus implicit addend. Note that the ``BitSize`` is 32 which
0120 means the section offset must be less than or equal to ``UINT32_MAX`` and this
0121 is enforced by LLVM BPF backend.
0122 
0123 In another case, ``R_BPF_64_ABS64`` relocation type is used for normal 64-bit data.
0124 The actual to-be-relocated data is stored at ``r_offset`` and the read/write data
0125 bitsize is 64 (8 bytes). The relocation can be resolved with
0126 the symbol value plus implicit addend.
0127 
0128 Both ``R_BPF_64_ABS32`` and ``R_BPF_64_NODYLD32`` types are for 32-bit data.
0129 But ``R_BPF_64_NODYLD32`` specifically refers to relocations in ``.BTF`` and
0130 ``.BTF.ext`` sections. For cases like bcc where llvm ``ExecutionEngine RuntimeDyld``
0131 is involved, ``R_BPF_64_NODYLD32`` types of relocations should not be resolved
0132 to actual function/variable address. Otherwise, ``.BTF`` and ``.BTF.ext``
0133 become unusable by bcc and kernel.
0134 
0135 Type ``R_BPF_64_32`` is used for call instruction. The call target section
0136 offset is stored at ``r_offset + 4`` (32bit) and calculated as
0137 ``(S + A) / 8 - 1``.
0138 
0139 Examples
0140 ========
0141 
0142 Types ``R_BPF_64_64`` and ``R_BPF_64_32`` are used to resolve ``ld_imm64``
0143 and ``call`` instructions. For example::
0144 
0145   __attribute__((noinline)) __attribute__((section("sec1")))
0146   int gfunc(int a, int b) {
0147     return a * b;
0148   }
0149   static __attribute__((noinline)) __attribute__((section("sec1")))
0150   int lfunc(int a, int b) {
0151     return a + b;
0152   }
0153   int global __attribute__((section("sec2")));
0154   int test(int a, int b) {
0155     return gfunc(a, b) +  lfunc(a, b) + global;
0156   }
0157 
0158 Compiled with ``clang -target bpf -O2 -c test.c``, we will have
0159 following code with `llvm-objdump -dr test.o``::
0160 
0161   Disassembly of section .text:
0162 
0163   0000000000000000 <test>:
0164          0:       bf 26 00 00 00 00 00 00 r6 = r2
0165          1:       bf 17 00 00 00 00 00 00 r7 = r1
0166          2:       85 10 00 00 ff ff ff ff call -1
0167                   0000000000000010:  R_BPF_64_32  gfunc
0168          3:       bf 08 00 00 00 00 00 00 r8 = r0
0169          4:       bf 71 00 00 00 00 00 00 r1 = r7
0170          5:       bf 62 00 00 00 00 00 00 r2 = r6
0171          6:       85 10 00 00 02 00 00 00 call 2
0172                   0000000000000030:  R_BPF_64_32  sec1
0173          7:       0f 80 00 00 00 00 00 00 r0 += r8
0174          8:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
0175                   0000000000000040:  R_BPF_64_64  global
0176         10:       61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0)
0177         11:       0f 10 00 00 00 00 00 00 r0 += r1
0178         12:       95 00 00 00 00 00 00 00 exit
0179 
0180   Disassembly of section sec1:
0181 
0182   0000000000000000 <gfunc>:
0183          0:       bf 20 00 00 00 00 00 00 r0 = r2
0184          1:       2f 10 00 00 00 00 00 00 r0 *= r1
0185          2:       95 00 00 00 00 00 00 00 exit
0186 
0187   0000000000000018 <lfunc>:
0188          3:       bf 20 00 00 00 00 00 00 r0 = r2
0189          4:       0f 10 00 00 00 00 00 00 r0 += r1
0190          5:       95 00 00 00 00 00 00 00 exit
0191 
0192 The first relocation corresponds to ``gfunc(a, b)`` where ``gfunc`` has a value of 0,
0193 so the ``call`` instruction offset is ``(0 + 0)/8 - 1 = -1``.
0194 The second relocation corresponds to ``lfunc(a, b)`` where ``lfunc`` has a section
0195 offset ``0x18``, so the ``call`` instruction offset is ``(0 + 0x18)/8 - 1 = 2``.
0196 The third relocation corresponds to ld_imm64 of ``global``, which has a section
0197 offset ``0``.
0198 
0199 The following is an example to show how R_BPF_64_ABS64 could be generated::
0200 
0201   int global() { return 0; }
0202   struct t { void *g; } gbl = { global };
0203 
0204 Compiled with ``clang -target bpf -O2 -g -c test.c``, we will see a
0205 relocation below in ``.data`` section with command
0206 ``llvm-readelf -r test.o``::
0207 
0208   Relocation section '.rel.data' at offset 0x458 contains 1 entries:
0209       Offset             Info             Type               Symbol's Value  Symbol's Name
0210   0000000000000000  0000000700000002 R_BPF_64_ABS64         0000000000000000 global
0211 
0212 The relocation says the first 8-byte of ``.data`` section should be
0213 filled with address of ``global`` variable.
0214 
0215 With ``llvm-readelf`` output, we can see that dwarf sections have a bunch of
0216 ``R_BPF_64_ABS32`` and ``R_BPF_64_ABS64`` relocations::
0217 
0218   Relocation section '.rel.debug_info' at offset 0x468 contains 13 entries:
0219       Offset             Info             Type               Symbol's Value  Symbol's Name
0220   0000000000000006  0000000300000003 R_BPF_64_ABS32         0000000000000000 .debug_abbrev
0221   000000000000000c  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
0222   0000000000000012  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
0223   0000000000000016  0000000600000003 R_BPF_64_ABS32         0000000000000000 .debug_line
0224   000000000000001a  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
0225   000000000000001e  0000000200000002 R_BPF_64_ABS64         0000000000000000 .text
0226   000000000000002b  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
0227   0000000000000037  0000000800000002 R_BPF_64_ABS64         0000000000000000 gbl
0228   0000000000000040  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
0229   ......
0230 
0231 The .BTF/.BTF.ext sections has R_BPF_64_NODYLD32 relocations::
0232 
0233   Relocation section '.rel.BTF' at offset 0x538 contains 1 entries:
0234       Offset             Info             Type               Symbol's Value  Symbol's Name
0235   0000000000000084  0000000800000004 R_BPF_64_NODYLD32      0000000000000000 gbl
0236 
0237   Relocation section '.rel.BTF.ext' at offset 0x548 contains 2 entries:
0238       Offset             Info             Type               Symbol's Value  Symbol's Name
0239   000000000000002c  0000000200000004 R_BPF_64_NODYLD32      0000000000000000 .text
0240   0000000000000040  0000000200000004 R_BPF_64_NODYLD32      0000000000000000 .text