cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

llvm_reloc.rst (11187B)


      1.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
      2
      3====================
      4BPF LLVM Relocations
      5====================
      6
      7This document describes LLVM BPF backend relocation types.
      8
      9Relocation Record
     10=================
     11
     12LLVM BPF backend records each relocation with the following 16-byte
     13ELF structure::
     14
     15  typedef struct
     16  {
     17    Elf64_Addr    r_offset;  // Offset from the beginning of section.
     18    Elf64_Xword   r_info;    // Relocation type and symbol index.
     19  } Elf64_Rel;
     20
     21For example, for the following code::
     22
     23  int g1 __attribute__((section("sec")));
     24  int g2 __attribute__((section("sec")));
     25  static volatile int l1 __attribute__((section("sec")));
     26  static volatile int l2 __attribute__((section("sec")));
     27  int test() {
     28    return g1 + g2 + l1 + l2;
     29  }
     30
     31Compiled with ``clang -target bpf -O2 -c test.c``, the following is
     32the code with ``llvm-objdump -dr test.o``::
     33
     34       0:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
     35                0000000000000000:  R_BPF_64_64  g1
     36       2:       61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0)
     37       3:       18 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r2 = 0 ll
     38                0000000000000018:  R_BPF_64_64  g2
     39       5:       61 20 00 00 00 00 00 00 r0 = *(u32 *)(r2 + 0)
     40       6:       0f 10 00 00 00 00 00 00 r0 += r1
     41       7:       18 01 00 00 08 00 00 00 00 00 00 00 00 00 00 00 r1 = 8 ll
     42                0000000000000038:  R_BPF_64_64  sec
     43       9:       61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0)
     44      10:       0f 10 00 00 00 00 00 00 r0 += r1
     45      11:       18 01 00 00 0c 00 00 00 00 00 00 00 00 00 00 00 r1 = 12 ll
     46                0000000000000058:  R_BPF_64_64  sec
     47      13:       61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0)
     48      14:       0f 10 00 00 00 00 00 00 r0 += r1
     49      15:       95 00 00 00 00 00 00 00 exit
     50
     51There are four relations in the above for four ``LD_imm64`` instructions.
     52The following ``llvm-readelf -r test.o`` shows the binary values of the four
     53relocations::
     54
     55  Relocation section '.rel.text' at offset 0x190 contains 4 entries:
     56      Offset             Info             Type               Symbol's Value  Symbol's Name
     57  0000000000000000  0000000600000001 R_BPF_64_64            0000000000000000 g1
     58  0000000000000018  0000000700000001 R_BPF_64_64            0000000000000004 g2
     59  0000000000000038  0000000400000001 R_BPF_64_64            0000000000000000 sec
     60  0000000000000058  0000000400000001 R_BPF_64_64            0000000000000000 sec
     61
     62Each relocation is represented by ``Offset`` (8 bytes) and ``Info`` (8 bytes).
     63For example, the first relocation corresponds to the first instruction
     64(Offset 0x0) and the corresponding ``Info`` indicates the relocation type
     65of ``R_BPF_64_64`` (type 1) and the entry in the symbol table (entry 6).
     66The following is the symbol table with ``llvm-readelf -s test.o``::
     67
     68  Symbol table '.symtab' contains 8 entries:
     69     Num:    Value          Size Type    Bind   Vis       Ndx Name
     70       0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT   UND
     71       1: 0000000000000000     0 FILE    LOCAL  DEFAULT   ABS test.c
     72       2: 0000000000000008     4 OBJECT  LOCAL  DEFAULT     4 l1
     73       3: 000000000000000c     4 OBJECT  LOCAL  DEFAULT     4 l2
     74       4: 0000000000000000     0 SECTION LOCAL  DEFAULT     4 sec
     75       5: 0000000000000000   128 FUNC    GLOBAL DEFAULT     2 test
     76       6: 0000000000000000     4 OBJECT  GLOBAL DEFAULT     4 g1
     77       7: 0000000000000004     4 OBJECT  GLOBAL DEFAULT     4 g2
     78
     79The 6th entry is global variable ``g1`` with value 0.
     80
     81Similarly, the second relocation is at ``.text`` offset ``0x18``, instruction 3,
     82for global variable ``g2`` which has a symbol value 4, the offset
     83from the start of ``.data`` section.
     84
     85The third and fourth relocations refers to static variables ``l1``
     86and ``l2``. From ``.rel.text`` section above, it is not clear
     87which symbols they really refers to as they both refers to
     88symbol table entry 4, symbol ``sec``, which has ``STT_SECTION`` type
     89and represents a section. So for static variable or function,
     90the section offset is written to the original insn
     91buffer, which is called ``A`` (addend). Looking at
     92above insn ``7`` and ``11``, they have section offset ``8`` and ``12``.
     93From symbol table, we can find that they correspond to entries ``2``
     94and ``3`` for ``l1`` and ``l2``.
     95
     96In general, the ``A`` is 0 for global variables and functions,
     97and is the section offset or some computation result based on
     98section offset for static variables/functions. The non-section-offset
     99case refers to function calls. See below for more details.
    100
    101Different Relocation Types
    102==========================
    103
    104Six relocation types are supported. The following is an overview and
    105``S`` represents the value of the symbol in the symbol table::
    106
    107  Enum  ELF Reloc Type     Description      BitSize  Offset        Calculation
    108  0     R_BPF_NONE         None
    109  1     R_BPF_64_64        ld_imm64 insn    32       r_offset + 4  S + A
    110  2     R_BPF_64_ABS64     normal data      64       r_offset      S + A
    111  3     R_BPF_64_ABS32     normal data      32       r_offset      S + A
    112  4     R_BPF_64_NODYLD32  .BTF[.ext] data  32       r_offset      S + A
    113  10    R_BPF_64_32        call insn        32       r_offset + 4  (S + A) / 8 - 1
    114
    115For example, ``R_BPF_64_64`` relocation type is used for ``ld_imm64`` instruction.
    116The actual to-be-relocated data (0 or section offset)
    117is stored at ``r_offset + 4`` and the read/write
    118data bitsize is 32 (4 bytes). The relocation can be resolved with
    119the symbol value plus implicit addend. Note that the ``BitSize`` is 32 which
    120means the section offset must be less than or equal to ``UINT32_MAX`` and this
    121is enforced by LLVM BPF backend.
    122
    123In another case, ``R_BPF_64_ABS64`` relocation type is used for normal 64-bit data.
    124The actual to-be-relocated data is stored at ``r_offset`` and the read/write data
    125bitsize is 64 (8 bytes). The relocation can be resolved with
    126the symbol value plus implicit addend.
    127
    128Both ``R_BPF_64_ABS32`` and ``R_BPF_64_NODYLD32`` types are for 32-bit data.
    129But ``R_BPF_64_NODYLD32`` specifically refers to relocations in ``.BTF`` and
    130``.BTF.ext`` sections. For cases like bcc where llvm ``ExecutionEngine RuntimeDyld``
    131is involved, ``R_BPF_64_NODYLD32`` types of relocations should not be resolved
    132to actual function/variable address. Otherwise, ``.BTF`` and ``.BTF.ext``
    133become unusable by bcc and kernel.
    134
    135Type ``R_BPF_64_32`` is used for call instruction. The call target section
    136offset is stored at ``r_offset + 4`` (32bit) and calculated as
    137``(S + A) / 8 - 1``.
    138
    139Examples
    140========
    141
    142Types ``R_BPF_64_64`` and ``R_BPF_64_32`` are used to resolve ``ld_imm64``
    143and ``call`` instructions. For example::
    144
    145  __attribute__((noinline)) __attribute__((section("sec1")))
    146  int gfunc(int a, int b) {
    147    return a * b;
    148  }
    149  static __attribute__((noinline)) __attribute__((section("sec1")))
    150  int lfunc(int a, int b) {
    151    return a + b;
    152  }
    153  int global __attribute__((section("sec2")));
    154  int test(int a, int b) {
    155    return gfunc(a, b) +  lfunc(a, b) + global;
    156  }
    157
    158Compiled with ``clang -target bpf -O2 -c test.c``, we will have
    159following code with `llvm-objdump -dr test.o``::
    160
    161  Disassembly of section .text:
    162
    163  0000000000000000 <test>:
    164         0:       bf 26 00 00 00 00 00 00 r6 = r2
    165         1:       bf 17 00 00 00 00 00 00 r7 = r1
    166         2:       85 10 00 00 ff ff ff ff call -1
    167                  0000000000000010:  R_BPF_64_32  gfunc
    168         3:       bf 08 00 00 00 00 00 00 r8 = r0
    169         4:       bf 71 00 00 00 00 00 00 r1 = r7
    170         5:       bf 62 00 00 00 00 00 00 r2 = r6
    171         6:       85 10 00 00 02 00 00 00 call 2
    172                  0000000000000030:  R_BPF_64_32  sec1
    173         7:       0f 80 00 00 00 00 00 00 r0 += r8
    174         8:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
    175                  0000000000000040:  R_BPF_64_64  global
    176        10:       61 11 00 00 00 00 00 00 r1 = *(u32 *)(r1 + 0)
    177        11:       0f 10 00 00 00 00 00 00 r0 += r1
    178        12:       95 00 00 00 00 00 00 00 exit
    179
    180  Disassembly of section sec1:
    181
    182  0000000000000000 <gfunc>:
    183         0:       bf 20 00 00 00 00 00 00 r0 = r2
    184         1:       2f 10 00 00 00 00 00 00 r0 *= r1
    185         2:       95 00 00 00 00 00 00 00 exit
    186
    187  0000000000000018 <lfunc>:
    188         3:       bf 20 00 00 00 00 00 00 r0 = r2
    189         4:       0f 10 00 00 00 00 00 00 r0 += r1
    190         5:       95 00 00 00 00 00 00 00 exit
    191
    192The first relocation corresponds to ``gfunc(a, b)`` where ``gfunc`` has a value of 0,
    193so the ``call`` instruction offset is ``(0 + 0)/8 - 1 = -1``.
    194The second relocation corresponds to ``lfunc(a, b)`` where ``lfunc`` has a section
    195offset ``0x18``, so the ``call`` instruction offset is ``(0 + 0x18)/8 - 1 = 2``.
    196The third relocation corresponds to ld_imm64 of ``global``, which has a section
    197offset ``0``.
    198
    199The following is an example to show how R_BPF_64_ABS64 could be generated::
    200
    201  int global() { return 0; }
    202  struct t { void *g; } gbl = { global };
    203
    204Compiled with ``clang -target bpf -O2 -g -c test.c``, we will see a
    205relocation below in ``.data`` section with command
    206``llvm-readelf -r test.o``::
    207
    208  Relocation section '.rel.data' at offset 0x458 contains 1 entries:
    209      Offset             Info             Type               Symbol's Value  Symbol's Name
    210  0000000000000000  0000000700000002 R_BPF_64_ABS64         0000000000000000 global
    211
    212The relocation says the first 8-byte of ``.data`` section should be
    213filled with address of ``global`` variable.
    214
    215With ``llvm-readelf`` output, we can see that dwarf sections have a bunch of
    216``R_BPF_64_ABS32`` and ``R_BPF_64_ABS64`` relocations::
    217
    218  Relocation section '.rel.debug_info' at offset 0x468 contains 13 entries:
    219      Offset             Info             Type               Symbol's Value  Symbol's Name
    220  0000000000000006  0000000300000003 R_BPF_64_ABS32         0000000000000000 .debug_abbrev
    221  000000000000000c  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
    222  0000000000000012  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
    223  0000000000000016  0000000600000003 R_BPF_64_ABS32         0000000000000000 .debug_line
    224  000000000000001a  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
    225  000000000000001e  0000000200000002 R_BPF_64_ABS64         0000000000000000 .text
    226  000000000000002b  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
    227  0000000000000037  0000000800000002 R_BPF_64_ABS64         0000000000000000 gbl
    228  0000000000000040  0000000400000003 R_BPF_64_ABS32         0000000000000000 .debug_str
    229  ......
    230
    231The .BTF/.BTF.ext sections has R_BPF_64_NODYLD32 relocations::
    232
    233  Relocation section '.rel.BTF' at offset 0x538 contains 1 entries:
    234      Offset             Info             Type               Symbol's Value  Symbol's Name
    235  0000000000000084  0000000800000004 R_BPF_64_NODYLD32      0000000000000000 gbl
    236
    237  Relocation section '.rel.BTF.ext' at offset 0x548 contains 2 entries:
    238      Offset             Info             Type               Symbol's Value  Symbol's Name
    239  000000000000002c  0000000200000004 R_BPF_64_NODYLD32      0000000000000000 .text
    240  0000000000000040  0000000200000004 R_BPF_64_NODYLD32      0000000000000000 .text