[PATCH] bpf: relocation fixes for eBPF ELF backend

Jose E. Marchesi jose.marchesi@oracle.com
Thu Aug 6 13:16:53 GMT 2020


Hi David.

> 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.

I just installed this in master, on your behalf.
Thanks!

> 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.
> ---
>  bfd/elf64-bpf.c                              | 206 ++++++++++++++-----
>  ld/testsuite/ld-bpf/call-2.d                 |  20 ++
>  ld/testsuite/ld-bpf/call-2.s                 |   3 +
>  ld/testsuite/ld-bpf/reloc-data-be.d          |  11 +
>  ld/testsuite/ld-bpf/reloc-data-le.d          |  11 +
>  ld/testsuite/ld-bpf/reloc-data.s             |  16 ++
>  ld/testsuite/ld-bpf/reloc-insn-external-be.d |  16 ++
>  ld/testsuite/ld-bpf/reloc-insn-external-le.d |  16 ++
>  ld/testsuite/ld-bpf/reloc-insn-external.s    |   5 +
>  ld/testsuite/ld-bpf/reloc-insn32-be.d        |  19 ++
>  ld/testsuite/ld-bpf/reloc-insn32-le.d        |  19 ++
>  ld/testsuite/ld-bpf/reloc-insn32.s           |  20 ++
>  ld/testsuite/ld-bpf/reloc-insn64-be.d        |  12 ++
>  ld/testsuite/ld-bpf/reloc-insn64-le.d        |  12 ++
>  ld/testsuite/ld-bpf/reloc-insn64.s           |   9 +
>  15 files changed, 347 insertions(+), 48 deletions(-)
>  create mode 100644 ld/testsuite/ld-bpf/call-2.d
>  create mode 100644 ld/testsuite/ld-bpf/call-2.s
>  create mode 100644 ld/testsuite/ld-bpf/reloc-data-be.d
>  create mode 100644 ld/testsuite/ld-bpf/reloc-data-le.d
>  create mode 100644 ld/testsuite/ld-bpf/reloc-data.s
>  create mode 100644 ld/testsuite/ld-bpf/reloc-insn-external-be.d
>  create mode 100644 ld/testsuite/ld-bpf/reloc-insn-external-le.d
>  create mode 100644 ld/testsuite/ld-bpf/reloc-insn-external.s
>  create mode 100644 ld/testsuite/ld-bpf/reloc-insn32-be.d
>  create mode 100644 ld/testsuite/ld-bpf/reloc-insn32-le.d
>  create mode 100644 ld/testsuite/ld-bpf/reloc-insn32.s
>  create mode 100644 ld/testsuite/ld-bpf/reloc-insn64-be.d
>  create mode 100644 ld/testsuite/ld-bpf/reloc-insn64-le.d
>  create mode 100644 ld/testsuite/ld-bpf/reloc-insn64.s
>
> diff --git a/bfd/elf64-bpf.c b/bfd/elf64-bpf.c
> index 641caa1f05..c6a726d932 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/testsuite/ld-bpf/call-2.d b/ld/testsuite/ld-bpf/call-2.d
> new file mode 100644
> index 0000000000..3d09095f6b
> --- /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 0000000000..e2a5b90647
> --- /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 0000000000..4d793e2b41
> --- /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 0000000000..97cb1b36a2
> --- /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 0000000000..431ef5aef6
> --- /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 0000000000..032d3649d2
> --- /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 0000000000..d3513766ee
> --- /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 0000000000..be12813934
> --- /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 0000000000..27d592d243
> --- /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 0000000000..bdbb45f28c
> --- /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 0000000000..a53a0dc43f
> --- /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 0000000000..ca74e33099
> --- /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 0000000000..63dcce3bd1
> --- /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 0000000000..8cb1d9f896
> --- /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


More information about the Binutils mailing list