bpf: relocation fixes for eBPF ELF backend
authorDavid Faust <david.faust@oracle.com>
Thu, 6 Aug 2020 13:14:54 +0000 (15:14 +0200)
committerJose E. Marchesi <jose.marchesi@oracle.com>
Thu, 6 Aug 2020 13:14:54 +0000 (15:14 +0200)
The eBPF ELF backend was not properly recording relocation addends
during installation, nor reading and applying them when performing
the final relocation. This lead to various issues with incorrect
relocations.

These issues are fixed with a new howto special function to install
the relocations, and updates to bpf_elf_relocate_section to read and
use the addends as recorded in the input_bfd.

bfd/ChangeLog

2020-08-05  David Faust  <david.faust@oracle.com>

* elf64-bpf.c (bpf_elf_generic_reloc): New function.
(bpf_elf_howto_table): Use it here.
(bpf_elf_relocate_section): Use addends recorded in input_bfd for
instruction and data relocations.

ld/ChangeLog

2020-08-05  David Faust  <david.faust@oracle.com>

* testsuite/ld-bpf/call-2.s: New file.
* testsuite/ld-bpf/call-2.d: Likewise.
* testsuite/ld-bpf/reloc-data-be.d: Likewise.
* testsuite/ld-bpf/reloc-data-le.d: Likewise.
* testsuite/ld-bpf/reloc-data.s: Likewise.
* testsuite/ld-bpf/reloc-insn-external-be.d: Likewise.
* testsuite/ld-bpf/reloc-insn-external-le.d: Likewise.
* testsuite/ld-bpf/reloc-insn-external.s: Likewise.
* testsuite/ld-bpf/reloc-insn32-be.d: Likewise.
* testsuite/ld-bpf/reloc-insn32-le.d: Likewise.
* testsuite/ld-bpf/reloc-insn32.s: Likewise.
* testsuite/ld-bpf/reloc-insn64-be.d: Likewise.
* testsuite/ld-bpf/reloc-insn64-le.d: Likewise.
* testsuite/ld-bpf/reloc-insn64.s: Likewise.

17 files changed:
bfd/ChangeLog
bfd/elf64-bpf.c
ld/ChangeLog
ld/testsuite/ld-bpf/call-2.d [new file with mode: 0644]
ld/testsuite/ld-bpf/call-2.s [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-data-be.d [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-data-le.d [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-data.s [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-insn-external-be.d [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-insn-external-le.d [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-insn-external.s [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-insn32-be.d [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-insn32-le.d [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-insn32.s [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-insn64-be.d [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-insn64-le.d [new file with mode: 0644]
ld/testsuite/ld-bpf/reloc-insn64.s [new file with mode: 0644]

index aae554b560d2795f4e61aea390865e4686c162ed..1c96c22008ccd990d80785695673a2b53fd652ec 100644 (file)
@@ -1,3 +1,10 @@
+2020-08-05  David Faust  <david.faust@oracle.com>
+
+       * elf64-bpf.c (bpf_elf_generic_reloc): New function.
+       (bpf_elf_howto_table): Use it here.
+       (bpf_elf_relocate_section): Use addends recorded in input_bfd for
+       instruction and data relocations.
+
 2020-08-03  Alan Modra  <amodra@gmail.com>
 
        * vms-lib.c (vms_traverse_index): Sanity check size remaining
index 641caa1f058e07a99c3cdb94086fb3586b417d88..c6a726d932431da909a4f0cc627f2e7e350b1873 100644 (file)
@@ -31,6 +31,9 @@
 
 #define BASEADDR(SEC)  ((SEC)->output_section->vma + (SEC)->output_offset)
 
+static bfd_reloc_status_type bpf_elf_generic_reloc
+  (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+
 /* Relocation tables.  */
 static reloc_howto_type bpf_elf_howto_table [] =
 {
@@ -42,7 +45,7 @@ static reloc_howto_type bpf_elf_howto_table [] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_NONE",          /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -55,27 +58,27 @@ static reloc_howto_type bpf_elf_howto_table [] =
         4,                     /* size (0 = byte, 1 = short, 2 = long) */
         64,                    /* bitsize */
         FALSE,                 /* pc_relative */
-        0,                     /* bitpos */
+        32,                    /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_INSN_64",       /* name */
-        FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        TRUE,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
         MINUS_ONE,             /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
-  /* 32-immediate in many instructions. Note: handled manually.  */
+  /* 32-immediate in many instructions.  */
   HOWTO (R_BPF_INSN_32,                /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
         FALSE,                 /* pc_relative */
-        0,                     /* bitpos */
+        32,                    /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_INSN_32",       /* name */
-        FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        TRUE,                  /* partial_inplace */
+        0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
@@ -85,12 +88,12 @@ static reloc_howto_type bpf_elf_howto_table [] =
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
         FALSE,                 /* pc_relative */
-        0,                     /* bitpos */
+        16,                    /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_INSN_16",       /* name */
-        FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        TRUE,                  /* partial_inplace */
+        0x0000ffff,            /* src_mask */
         0x0000ffff,            /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
@@ -100,11 +103,11 @@ static reloc_howto_type bpf_elf_howto_table [] =
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
         TRUE,                  /* pc_relative */
-        32,                    /* bitpos */
+        16,                    /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_INSN_DISP16",   /* name */
-        FALSE,                 /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
         TRUE),                 /* pcrel_offset */
@@ -116,10 +119,10 @@ static reloc_howto_type bpf_elf_howto_table [] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_8_PCREL",       /* name */
-        FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        TRUE,                  /* partial_inplace */
+        0xff,                  /* src_mask */
         0xff,                  /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
@@ -130,10 +133,10 @@ static reloc_howto_type bpf_elf_howto_table [] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_16_PCREL",      /* name */
         FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
@@ -144,10 +147,10 @@ static reloc_howto_type bpf_elf_howto_table [] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_32_PCREL",      /* name */
         FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
@@ -158,10 +161,10 @@ static reloc_howto_type bpf_elf_howto_table [] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_unsigned, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_DATA_8",        /* name */
-        FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        TRUE,                  /* partial_inplace */
+        0xff,                  /* src_mask */
         0xff,                  /* dst_mask */
         FALSE),                /* pcrel_offset */
 
@@ -172,10 +175,10 @@ static reloc_howto_type bpf_elf_howto_table [] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_unsigned, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_DATA_16",       /* name */
         FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
         FALSE),                /* pcrel_offset */
 
@@ -185,11 +188,11 @@ static reloc_howto_type bpf_elf_howto_table [] =
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
         TRUE,                  /* pc_relative */
-        0,                     /* bitpos */
+        32,                    /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_INSN_DISP32",   /* name */
-        FALSE,                 /* partial_inplace */
+        TRUE,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
         TRUE),                 /* pcrel_offset */
@@ -202,10 +205,10 @@ static reloc_howto_type bpf_elf_howto_table [] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_DATA_32",       /* name */
         FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
@@ -217,7 +220,7 @@ static reloc_howto_type bpf_elf_howto_table [] =
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_DATA_64",       /* name */
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
@@ -231,10 +234,10 @@ static reloc_howto_type bpf_elf_howto_table [] =
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
-        bfd_elf_generic_reloc, /* special_function */
+        bpf_elf_generic_reloc, /* special_function */
         "R_BPF_64_PCREL",      /* name */
         FALSE,                 /* partial_inplace */
-        0,                     /* src_mask */
+        MINUS_ONE,             /* src_mask */
         MINUS_ONE,             /* dst_mask */
         TRUE),                 /* pcrel_offset */
 };
@@ -391,6 +394,8 @@ bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
       bfd_reloc_status_type       r;
       const char *                name = NULL;
       int                         r_type ATTRIBUTE_UNUSED;
+      bfd_signed_vma               addend;
+      bfd_byte                   * where;
 
       r_type = ELF64_R_TYPE (rel->r_info);
       r_symndx = ELF64_R_SYM (rel->r_info);
@@ -398,6 +403,7 @@ bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
       h      = NULL;
       sym    = NULL;
       sec    = NULL;
+      where  = contents + rel->r_offset;
 
       if (r_symndx < symtab_hdr->sh_info)
        {
@@ -435,8 +441,6 @@ bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
         case R_BPF_INSN_DISP16:
         case R_BPF_INSN_DISP32:
           {
-            bfd_signed_vma addend;
-            
             /* Make the relocation PC-relative, and change its unit to
                64-bit words.  */
             relocation -= sec_addr (input_section) + rel->r_offset;
@@ -460,11 +464,35 @@ bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
             r = bfd_reloc_ok;
             break;
           }
+       case R_BPF_DATA_8:
+       case R_BPF_DATA_16:
+       case R_BPF_DATA_32:
+       case R_BPF_DATA_64:
+         {
+           addend = bfd_get (howto->bitsize, input_bfd, where);
+           relocation += addend;
+           bfd_put (howto->bitsize, input_bfd, relocation, where);
+
+           r = bfd_reloc_ok;
+           break;
+         }
+       case R_BPF_INSN_16:
+         {
+
+           addend = bfd_get_16 (input_bfd, where + 2);
+           relocation += addend;
+           bfd_put_16 (input_bfd, relocation, where + 2);
+
+           r = bfd_reloc_ok;
+           break;
+         }
         case R_BPF_INSN_32:
           {
             /*  Write relocated value */
-            bfd_put (howto->bitsize, input_bfd, relocation,
-                     contents + rel->r_offset + 4);
+
+           addend = bfd_get_32 (input_bfd, where + 4);
+           relocation += addend;
+            bfd_put_32 (input_bfd, relocation, where + 4);
 
             r = bfd_reloc_ok;
             break;
@@ -478,19 +506,30 @@ bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
                 The upper 32 bits of the immediate are stored at the end of
                 the instruction.
              */
-            bfd_put (32, input_bfd, (relocation & 0xFFFFFFFF),
-                     contents + rel->r_offset + 4);
-            bfd_put (32, input_bfd, (relocation >> 32),
-                     contents + rel->r_offset + 12);
+
+
+            /* Get the addend. The upper and lower 32 bits are split.
+               'where' is the beginning of the 16-byte instruction. */
+            addend = bfd_get_32 (input_bfd, where + 4);
+            addend |= (bfd_get_32 (input_bfd, where + 12) << 32);
+
+            relocation += addend;
+
+            bfd_put_32 (input_bfd, (relocation & 0xFFFFFFFF), where + 4);
+            bfd_put_32 (input_bfd, (relocation >> 32), where + 12);
             r = bfd_reloc_ok;
             break;
           }
         default:
-          r = _bfd_final_link_relocate (howto, input_bfd, input_section,
-                                        contents, rel->r_offset, relocation,
-                                        rel->r_addend);
+         r = bfd_reloc_notsupported;
         }
 
+      if (r == bfd_reloc_ok)
+         r = bfd_check_overflow (howto->complain_on_overflow,
+                                 howto->bitsize,
+                                 howto->rightshift,
+                                 64, relocation);
+
       if (r != bfd_reloc_ok)
        {
          const char * msg = NULL;
@@ -548,6 +587,77 @@ elf64_bpf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
   return TRUE;
 }
 
+/* A generic howto special function for installing BPF relocations.
+   This function will be called by the assembler (via bfd_install_relocation).
+   At link time, bpf_elf_relocate_section will resolve the final relocations.
+
+   BPF instructions are always big endian, and this approach avoids problems in
+   bfd_install_relocation.  */
+
+static bfd_reloc_status_type
+bpf_elf_generic_reloc (bfd * abfd, arelent *reloc_entry, asymbol *symbol,
+                      void *data, asection *input_section,
+                      bfd *output_bfd,
+                      char **error_message ATTRIBUTE_UNUSED)
+{
+
+  bfd_signed_vma relocation;
+  bfd_reloc_status_type status;
+  bfd_byte *where;
+
+  /* Sanity check that the address is in range.  */
+  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
+    return bfd_reloc_outofrange;
+
+  /*  Get the symbol value.  */
+  if (bfd_is_com_section (symbol->section))
+    relocation = 0;
+  else
+    relocation = symbol->value;
+
+  if (symbol->flags & BSF_SECTION_SYM)
+    /* Relocation against a section symbol: add in the section base address.  */
+    relocation += BASEADDR (symbol->section);
+
+  relocation += reloc_entry->addend;
+
+  where = (bfd_byte *) data + reloc_entry->address;
+
+  status = bfd_check_overflow (reloc_entry->howto->complain_on_overflow,
+                              reloc_entry->howto->bitsize,
+                              reloc_entry->howto->rightshift, 64, relocation);
+
+  if (status != bfd_reloc_ok)
+    return status;
+
+  /* Now finally install the relocation.  */
+  if (reloc_entry->howto->type == R_BPF_INSN_64)
+    {
+      /* lddw is a 128-bit (!) instruction that allows loading a 64-bit
+        immediate into a register. the immediate is split in half, with the
+        lower 32 bits in the same position as the imm32 field of other
+        instructions, and the upper 32 bits placed at the very end of the
+        instruction. that is, there are 32 unused bits between them. */
+
+      bfd_put_32 (output_bfd, (relocation & 0xFFFFFFFF), where + 4);
+      bfd_put_32 (output_bfd, (relocation >> 32), where + 12);
+    }
+  else
+    {
+      /* For other kinds of relocations, the relocated value simply goes
+        BITPOS bits from the start of the entry. This is always a multiple
+        of 8, i.e. whole bytes.  */
+      bfd_put (reloc_entry->howto->bitsize, output_bfd, relocation,
+              where + reloc_entry->howto->bitpos / 8);
+    }
+
+  reloc_entry->addend = relocation;
+  reloc_entry->address += input_section->output_offset;
+
+  return bfd_reloc_ok;
+}
+
+
 /* The macros below configure the architecture.  */
 
 #define TARGET_LITTLE_SYM bpf_elf64_le_vec
index b413418471441bf2dff6a988264cc2f93bfd175d..d46e9769c080467edee6474036fb201cf52a81e3 100644 (file)
@@ -1,3 +1,20 @@
+2020-08-05  David Faust  <david.faust@oracle.com>
+
+       * testsuite/ld-bpf/call-2.s: New file.
+       * testsuite/ld-bpf/call-2.d: Likewise.
+       * testsuite/ld-bpf/reloc-data-be.d: Likewise.
+       * testsuite/ld-bpf/reloc-data-le.d: Likewise.
+       * testsuite/ld-bpf/reloc-data.s: Likewise.
+       * testsuite/ld-bpf/reloc-insn-external-be.d: Likewise.
+       * testsuite/ld-bpf/reloc-insn-external-le.d: Likewise.
+       * testsuite/ld-bpf/reloc-insn-external.s: Likewise.
+       * testsuite/ld-bpf/reloc-insn32-be.d: Likewise.
+       * testsuite/ld-bpf/reloc-insn32-le.d: Likewise.
+       * testsuite/ld-bpf/reloc-insn32.s: Likewise.
+       * testsuite/ld-bpf/reloc-insn64-be.d: Likewise.
+       * testsuite/ld-bpf/reloc-insn64-le.d: Likewise.
+       * testsuite/ld-bpf/reloc-insn64.s: Likewise.
+
 2020-08-06  Jozef Lawrynowicz  <jozef.l@mittosystems.com>
 
        * emultempl/msp430.em (change_output_section): Update the tail
diff --git a/ld/testsuite/ld-bpf/call-2.d b/ld/testsuite/ld-bpf/call-2.d
new file mode 100644 (file)
index 0000000..3d09095
--- /dev/null
@@ -0,0 +1,20 @@
+#as: --EL
+#source: call-2.s
+#source: bar.s
+#objdump: -dr
+#ld: -EL
+#name: CALL with disp32 reloc and addend
+
+.*: +file format .*bpf.*
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+:   b7 01 00 00 01 00 00 00         mov %r1,1
+ *[0-9a-f]+:   85 10 00 00 02 00 00 00         call 2
+ *[0-9a-f]+:   95 00 00 00 00 00 00 00         exit
+
+[0-9a-f]+ <bar>:
+ *[0-9a-f]+:   bf 21 00 00 00 00 00 00         mov %r1,%r2
+ *[0-9a-f]+:   bf 13 00 00 00 00 00 00         mov %r3,%r1
+ *[0-9a-f]+:   95 00 00 00 00 00 00 00         exit
diff --git a/ld/testsuite/ld-bpf/call-2.s b/ld/testsuite/ld-bpf/call-2.s
new file mode 100644 (file)
index 0000000..e2a5b90
--- /dev/null
@@ -0,0 +1,3 @@
+    mov %r1, 1
+    call bar + 0x1
+    exit
diff --git a/ld/testsuite/ld-bpf/reloc-data-be.d b/ld/testsuite/ld-bpf/reloc-data-be.d
new file mode 100644 (file)
index 0000000..4d793e2
--- /dev/null
@@ -0,0 +1,11 @@
+#as: --EB
+#source: reloc-data.s
+#objdump: -s
+#ld: -Tdata=0x20 -EB
+#name: data relocs BE
+
+.*:     file format .*-bpfbe
+
+Contents of section \.data:
+ 0020 666f6f00 62617200 00000000 00000020  .*
+ 0030 00000028 003034                      .*
diff --git a/ld/testsuite/ld-bpf/reloc-data-le.d b/ld/testsuite/ld-bpf/reloc-data-le.d
new file mode 100644 (file)
index 0000000..97cb1b3
--- /dev/null
@@ -0,0 +1,11 @@
+#as: --EL
+#source: reloc-data.s
+#objdump: -s
+#ld: -Tdata=0x20 -EL
+#name: data relocs LE
+
+.*:     file format .*-bpfle
+
+Contents of section \.data:
+ 0020 666f6f00 62617200 20000000 00000000  .*
+ 0030 28000000 300034                      .*
diff --git a/ld/testsuite/ld-bpf/reloc-data.s b/ld/testsuite/ld-bpf/reloc-data.s
new file mode 100644 (file)
index 0000000..431ef5a
--- /dev/null
@@ -0,0 +1,16 @@
+    .data
+foo:
+    .string "foo"
+
+    .global bar
+bar:
+    .string "bar"
+
+d64:
+    .quad foo
+d32:
+    .word d64
+d16:
+    .half d32
+d8:
+    .byte d16
diff --git a/ld/testsuite/ld-bpf/reloc-insn-external-be.d b/ld/testsuite/ld-bpf/reloc-insn-external-be.d
new file mode 100644 (file)
index 0000000..032d364
--- /dev/null
@@ -0,0 +1,16 @@
+#as: --EB
+#source: reloc-data.s
+#source: reloc-insn-external.s
+#objdump: -dr
+#ld: -Tdata=0x20 -EB
+#name: reloc insn external BE
+
+.*: +file format .*bpfbe
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+:   18 10 00 00 00 00 00 28[        ]*lddw %r1,0x28
+ *[0-9a-f]+:   00 00 00 00 00 00 00 00[        ]*
+ *[0-9a-f]+:   b7 20 00 00 00 00 00 26[        ]*mov %r2,0x26
+ *[0-9a-f]+:   61 34 00 24 00 00 00 00[        ]*ldxw %r3,\[%r4\+0x24\]
diff --git a/ld/testsuite/ld-bpf/reloc-insn-external-le.d b/ld/testsuite/ld-bpf/reloc-insn-external-le.d
new file mode 100644 (file)
index 0000000..d351376
--- /dev/null
@@ -0,0 +1,16 @@
+#as: --EL
+#source: reloc-data.s
+#source: reloc-insn-external.s
+#objdump: -dr
+#ld: -Tdata=0x20 -EL
+#name: reloc insn external LE
+
+.*: +file format .*bpfle
+
+Disassembly of section .text:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+:   18 01 00 00 28 00 00 00[        ]*lddw %r1,0x28
+ *[0-9a-f]+:   00 00 00 00 00 00 00 00[        ]*
+ *[0-9a-f]+:   b7 02 00 00 26 00 00 00[        ]*mov %r2,0x26
+ *[0-9a-f]+:   61 43 24 00 00 00 00 00[        ]*ldxw %r3,\[%r4\+0x24\]
diff --git a/ld/testsuite/ld-bpf/reloc-insn-external.s b/ld/testsuite/ld-bpf/reloc-insn-external.s
new file mode 100644 (file)
index 0000000..be12813
--- /dev/null
@@ -0,0 +1,5 @@
+
+    lddw %r1, bar + 4
+    mov %r2, bar + 2
+
+    ldxw %r3, [%r4 + bar]
diff --git a/ld/testsuite/ld-bpf/reloc-insn32-be.d b/ld/testsuite/ld-bpf/reloc-insn32-be.d
new file mode 100644 (file)
index 0000000..27d592d
--- /dev/null
@@ -0,0 +1,19 @@
+#as: --EB
+#source: reloc-insn32.s
+#objdump: -d
+#ld: -Tdata=0xdabeef -EB
+#name: reloc INSN32 BE
+
+.*: +file format .*bpfbe
+
+Disassembly of section .text:
+
+[0-9a-f]+ <main>:
+ *[0-9a-f]+:   b7 10 00 00 00 da be f3[        ]*mov %r1,0xdabef3
+ *[0-9a-f]+:   16 10 00 02 00 da be f3[        ]*jeq32 %r1,0xdabef3,2
+ *[0-9a-f]+:   38 00 00 00 00 da be ff[        ]*ldabsdw 0xdabeff
+ *[0-9a-f]+:   95 00 00 00 00 00 00 00[        ]*exit
+
+[0-9a-f]+ <baz>:
+ *[0-9a-f]+:   07 10 00 00 00 da be ef[        ]*add %r1,0xdabeef
+ *[0-9a-f]+:   62 20 00 08 00 da be f7[        ]*stw \[%r2\+8\],0xdabef7
diff --git a/ld/testsuite/ld-bpf/reloc-insn32-le.d b/ld/testsuite/ld-bpf/reloc-insn32-le.d
new file mode 100644 (file)
index 0000000..bdbb45f
--- /dev/null
@@ -0,0 +1,19 @@
+#as: --EL
+#source: reloc-insn32.s
+#objdump: -d
+#ld: -Tdata=0xdabeef -EL
+#name: reloc INSN32 LE
+
+.*: +file format .*bpfle
+
+Disassembly of section .text:
+
+[0-9a-f]+ <main>:
+ *[0-9a-f]+:   b7 01 00 00 f3 be da 00[        ]*mov %r1,0xdabef3
+ *[0-9a-f]+:   16 01 02 00 f3 be da 00[        ]*jeq32 %r1,0xdabef3,2
+ *[0-9a-f]+:   38 00 00 00 ff be da 00[        ]*ldabsdw 0xdabeff
+ *[0-9a-f]+:   95 00 00 00 00 00 00 00[        ]*exit
+
+[0-9a-f]+ <baz>:
+ *[0-9a-f]+:   07 01 00 00 ef be da 00[        ]*add %r1,0xdabeef
+ *[0-9a-f]+:   62 02 08 00 f7 be da 00[        ]*stw \[%r2\+8\],0xdabef7
diff --git a/ld/testsuite/ld-bpf/reloc-insn32.s b/ld/testsuite/ld-bpf/reloc-insn32.s
new file mode 100644 (file)
index 0000000..a53a0dc
--- /dev/null
@@ -0,0 +1,20 @@
+    .data
+foo:
+    .string "foo"
+bar:
+    .string "bar"
+d64:
+    .dword bar
+d32:
+    .word d64
+
+    .text
+main:
+    mov %r1, bar
+    jeq32 %r1, bar, baz
+    ldabsdw d32
+    exit
+
+baz:
+    add %r1, foo
+    stw [%r2 + 8], d64
diff --git a/ld/testsuite/ld-bpf/reloc-insn64-be.d b/ld/testsuite/ld-bpf/reloc-insn64-be.d
new file mode 100644 (file)
index 0000000..ca74e33
--- /dev/null
@@ -0,0 +1,12 @@
+#as: --EB
+#source: reloc-insn64.s
+#objdump: -s
+#ld: -Tdata=0xdeadbeef1234 -EB
+#name: reloc INSN64 big-endian
+
+.*:     file format .*-bpfbe
+
+#...
+Contents of section \.text:
+[      ][0-9a-f]+ 18100000 beef1238 00000000 0000dead .*
+#pass
diff --git a/ld/testsuite/ld-bpf/reloc-insn64-le.d b/ld/testsuite/ld-bpf/reloc-insn64-le.d
new file mode 100644 (file)
index 0000000..63dcce3
--- /dev/null
@@ -0,0 +1,12 @@
+#as: --EL
+#source: reloc-insn64.s
+#objdump: -s
+#ld: -Tdata=0xdeadbeef1234 -EL
+#name: reloc INSN64 little-endian
+
+.*:     file format .*-bpfle
+
+#...
+Contents of section \.text:
+[      ][0-9a-f]+ 18010000 3812efbe 00000000 adde0000 .*
+#pass
diff --git a/ld/testsuite/ld-bpf/reloc-insn64.s b/ld/testsuite/ld-bpf/reloc-insn64.s
new file mode 100644 (file)
index 0000000..8cb1d9f
--- /dev/null
@@ -0,0 +1,9 @@
+    .data
+x:
+    .string "foo"
+y:
+    .string "bar"
+
+    .text
+main:
+    lddw %r1, y