aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/elf64-bpf.c206
-rw-r--r--ld/ChangeLog17
-rw-r--r--ld/testsuite/ld-bpf/call-2.d20
-rw-r--r--ld/testsuite/ld-bpf/call-2.s3
-rw-r--r--ld/testsuite/ld-bpf/reloc-data-be.d11
-rw-r--r--ld/testsuite/ld-bpf/reloc-data-le.d11
-rw-r--r--ld/testsuite/ld-bpf/reloc-data.s16
-rw-r--r--ld/testsuite/ld-bpf/reloc-insn-external-be.d16
-rw-r--r--ld/testsuite/ld-bpf/reloc-insn-external-le.d16
-rw-r--r--ld/testsuite/ld-bpf/reloc-insn-external.s5
-rw-r--r--ld/testsuite/ld-bpf/reloc-insn32-be.d19
-rw-r--r--ld/testsuite/ld-bpf/reloc-insn32-le.d19
-rw-r--r--ld/testsuite/ld-bpf/reloc-insn32.s20
-rw-r--r--ld/testsuite/ld-bpf/reloc-insn64-be.d12
-rw-r--r--ld/testsuite/ld-bpf/reloc-insn64-le.d12
-rw-r--r--ld/testsuite/ld-bpf/reloc-insn64.s9
17 files changed, 371 insertions, 48 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index aae554b..1c96c22 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/elf64-bpf.c b/bfd/elf64-bpf.c
index 641caa1..c6a726d 100644
--- a/bfd/elf64-bpf.c
+++ b/bfd/elf64-bpf.c
@@ -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
diff --git a/ld/ChangeLog b/ld/ChangeLog
index b413418..d46e976 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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
index 0000000..3d09095
--- /dev/null
+++ b/ld/testsuite/ld-bpf/call-2.d
@@ -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
index 0000000..e2a5b90
--- /dev/null
+++ b/ld/testsuite/ld-bpf/call-2.s
@@ -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
index 0000000..4d793e2
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-data-be.d
@@ -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
index 0000000..97cb1b3
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-data-le.d
@@ -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
index 0000000..431ef5a
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-data.s
@@ -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
index 0000000..032d364
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-insn-external-be.d
@@ -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
index 0000000..d351376
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-insn-external-le.d
@@ -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
index 0000000..be12813
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-insn-external.s
@@ -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
index 0000000..27d592d
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-insn32-be.d
@@ -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
index 0000000..bdbb45f
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-insn32-le.d
@@ -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
index 0000000..a53a0dc
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-insn32.s
@@ -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
index 0000000..ca74e33
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-insn64-be.d
@@ -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
index 0000000..63dcce3
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-insn64-le.d
@@ -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
index 0000000..8cb1d9f
--- /dev/null
+++ b/ld/testsuite/ld-bpf/reloc-insn64.s
@@ -0,0 +1,9 @@
+ .data
+x:
+ .string "foo"
+y:
+ .string "bar"
+
+ .text
+main:
+ lddw %r1, y