From fd0de36e274c8141a5dd4579cd04856dc88370da Mon Sep 17 00:00:00 2001 From: "Jose E. Marchesi" Date: Thu, 23 May 2019 19:33:41 +0200 Subject: [PATCH] bfd: add support for eBPF This patch adds support to BFD for elf64-bpf, in both little-endian and big-endian variants. bfd/ChangeLog: 2019-05-23 Jose E. Marchesi * configure.ac: Add bpf_elf64_le_vec and bpf_elf64_be_vec. * configure: Regenerated. * Makefile.am (ALL_MACHINES): Add cpu-bpf.lo. (ALL_MACHINES_CFILES): Add cpu-bpf.c. (BFD64_BACKENDS): Add elf64-bpf.lo. (BFD64_BACKENDS_CFILES): Add elf64-bpf.c. * Makefile.in (SOURCE_HFILES): Regenerate. * config.bfd (targ_cpu): Handle bpf-*-* targets. * cpu-bpf.c: New file. * elf64-bpf.c: Likewise. * targets.c (_bfd_target_vector): Add bpf_elf64_be_vec and bpf_elf64_le_vec. * archures.c: Define architecture bfd_arch_bpf and machine bfd_arch_bpf. * reloc.c: Define BFD relocations used by the BPF target. * bfd-in2.h: Regenerated. * libbfd.h: Likewise. --- bfd/ChangeLog | 20 ++ bfd/Makefile.am | 4 + bfd/Makefile.in | 7 + bfd/archures.c | 4 + bfd/bfd-in2.h | 9 + bfd/config.bfd | 12 ++ bfd/configure | 30 ++- bfd/configure.ac | 2 + bfd/cpu-bpf.c | 41 +++++ bfd/elf64-bpf.c | 463 +++++++++++++++++++++++++++++++++++++++++++++++ bfd/libbfd.h | 5 + bfd/reloc.c | 13 ++ bfd/targets.c | 7 + 13 files changed, 609 insertions(+), 8 deletions(-) create mode 100644 bfd/cpu-bpf.c create mode 100644 bfd/elf64-bpf.c diff --git a/bfd/ChangeLog b/bfd/ChangeLog index f2b2ec5bc0..85f00362a2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,23 @@ +2019-05-23 Jose E. Marchesi + + * configure.ac: Add bpf_elf64_le_vec and bpf_elf64_be_vec. + * configure: Regenerated. + * Makefile.am (ALL_MACHINES): Add cpu-bpf.lo. + (ALL_MACHINES_CFILES): Add cpu-bpf.c. + (BFD64_BACKENDS): Add elf64-bpf.lo. + (BFD64_BACKENDS_CFILES): Add elf64-bpf.c. + * Makefile.in (SOURCE_HFILES): Regenerate. + * config.bfd (targ_cpu): Handle bpf-*-* targets. + * cpu-bpf.c: New file. + * elf64-bpf.c: Likewise. + * targets.c (_bfd_target_vector): Add bpf_elf64_be_vec and + bpf_elf64_le_vec. + * archures.c: Define architecture bfd_arch_bpf and machine + bfd_arch_bpf. + * reloc.c: Define BFD relocations used by the BPF target. + * bfd-in2.h: Regenerated. + * libbfd.h: Likewise. + 2019-05-22 Alan Modra * elf32-arm.c (arm_allocate_glue_section_space): Clear section diff --git a/bfd/Makefile.am b/bfd/Makefile.am index a9191555ad..4703955ee4 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -96,6 +96,7 @@ ALL_MACHINES = \ cpu-arm.lo \ cpu-avr.lo \ cpu-bfin.lo \ + cpu-bpf.lo \ cpu-cr16.lo \ cpu-cr16c.lo \ cpu-cris.lo \ @@ -182,6 +183,7 @@ ALL_MACHINES_CFILES = \ cpu-arm.c \ cpu-avr.c \ cpu-bfin.c \ + cpu-bpf.c \ cpu-cr16.c \ cpu-cr16c.c \ cpu-cris.c \ @@ -574,6 +576,7 @@ BFD64_BACKENDS = \ elf64-tilegx.lo \ elf64-x86-64.lo \ elfxx-x86.lo \ + elf64-bpf.lo \ elf64.lo \ mach-o-aarch64.lo \ mach-o-x86-64.lo \ @@ -607,6 +610,7 @@ BFD64_BACKENDS_CFILES = \ elf64-tilegx.c \ elf64-x86-64.c \ elfxx-x86.c \ + elf64-bpf.c \ elf64.c \ elfn32-mips.c \ elfxx-aarch64.c \ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index 896df52042..5578997e5d 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -438,6 +438,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -519,6 +520,7 @@ ALL_MACHINES = \ cpu-arm.lo \ cpu-avr.lo \ cpu-bfin.lo \ + cpu-bpf.lo \ cpu-cr16.lo \ cpu-cr16c.lo \ cpu-cris.lo \ @@ -605,6 +607,7 @@ ALL_MACHINES_CFILES = \ cpu-arm.c \ cpu-avr.c \ cpu-bfin.c \ + cpu-bpf.c \ cpu-cr16.c \ cpu-cr16c.c \ cpu-cris.c \ @@ -999,6 +1002,7 @@ BFD64_BACKENDS = \ elf64-tilegx.lo \ elf64-x86-64.lo \ elfxx-x86.lo \ + elf64-bpf.lo \ elf64.lo \ mach-o-aarch64.lo \ mach-o-x86-64.lo \ @@ -1032,6 +1036,7 @@ BFD64_BACKENDS_CFILES = \ elf64-tilegx.c \ elf64-x86-64.c \ elfxx-x86.c \ + elf64-bpf.c \ elf64.c \ elfn32-mips.c \ elfxx-aarch64.c \ @@ -1322,6 +1327,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-arm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-avr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-bfin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-bpf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-cr16.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-cr16c.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-cris.Plo@am__quote@ @@ -1484,6 +1490,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-aarch64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-alpha.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-bpf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-gen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-hppa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ia64-vms.Plo@am__quote@ diff --git a/bfd/archures.c b/bfd/archures.c index aaf2e112cf..3465406213 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -415,6 +415,8 @@ DESCRIPTION . bfd_arch_iq2000, {* Vitesse IQ2000. *} .#define bfd_mach_iq2000 1 .#define bfd_mach_iq10 2 +. bfd_arch_bpf, {* Linux eBPF. *} +.#define bfd_mach_bpf 1 . bfd_arch_epiphany, {* Adapteva EPIPHANY. *} .#define bfd_mach_epiphany16 1 .#define bfd_mach_epiphany32 2 @@ -601,6 +603,7 @@ extern const bfd_arch_info_type bfd_csky_arch; extern const bfd_arch_info_type bfd_d10v_arch; extern const bfd_arch_info_type bfd_d30v_arch; extern const bfd_arch_info_type bfd_dlx_arch; +extern const bfd_arch_info_type bfd_bpf_arch; extern const bfd_arch_info_type bfd_epiphany_arch; extern const bfd_arch_info_type bfd_fr30_arch; extern const bfd_arch_info_type bfd_frv_arch; @@ -692,6 +695,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] = &bfd_d10v_arch, &bfd_d30v_arch, &bfd_dlx_arch, + &bfd_bpf_arch, &bfd_epiphany_arch, &bfd_fr30_arch, &bfd_frv_arch, diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 65e2e01efe..03d644c61e 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2357,6 +2357,8 @@ enum bfd_architecture bfd_arch_iq2000, /* Vitesse IQ2000. */ #define bfd_mach_iq2000 1 #define bfd_mach_iq10 2 + bfd_arch_bpf, /* Linux eBPF. */ +#define bfd_mach_bpf 1 bfd_arch_epiphany, /* Adapteva EPIPHANY. */ #define bfd_mach_epiphany16 1 #define bfd_mach_epiphany32 2 @@ -6651,6 +6653,13 @@ assembler and not (currently) written to any object files. */ BFD_RELOC_TILEGX_IMM8_Y0_TLS_ADD, BFD_RELOC_TILEGX_IMM8_Y1_TLS_ADD, +/* Linux eBPF relocations. */ + BFD_RELOC_BPF_64, + BFD_RELOC_BPF_32, + BFD_RELOC_BPF_16, + BFD_RELOC_BPF_DISP16, + BFD_RELOC_BPF_DISP32, + /* Adapteva EPIPHANY - 8 bit signed pc-relative displacement */ BFD_RELOC_EPIPHANY_SIMM8, diff --git a/bfd/config.bfd b/bfd/config.bfd index 8977d2a2a2..562c331c55 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -480,6 +480,12 @@ case "${targ}" in targ_defvec=d30v_elf32_vec ;; + bpf-*-none) + targ_defvec=bpf_elf64_le_vec + targ_selvecs=bpf_elf64_be_vec + targ_underscore=yes + ;; + epiphany-*-*) targ_defvec=epiphany_elf32_vec targ_underscore=yes @@ -1420,6 +1426,12 @@ case "${targ}" in ;; # END OF targmatch.h + bpf-*-*) + echo "*** Configuration $targ is not fully supported." >&2 + echo "*** Use bpf or bpf-*-none as the target instead." >&2 + exit 1 + ;; + *) echo 1>&2 "*** BFD does not support target ${targ}." echo 1>&2 "*** Look in bfd/config.bfd for supported targets." diff --git a/bfd/configure b/bfd/configure index f99979faa0..f2f8735629 100755 --- a/bfd/configure +++ b/bfd/configure @@ -793,6 +793,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -889,6 +890,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1141,6 +1143,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1278,7 +1289,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1431,6 +1442,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -11728,7 +11740,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11731 "configure" +#line 11743 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11834,7 +11846,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11837 "configure" +#line 11849 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12223,7 +12235,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12269,7 +12281,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12293,7 +12305,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12338,7 +12350,7 @@ else We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -12362,7 +12374,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext We can't simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31)) int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -14740,6 +14752,8 @@ do elf32_le_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;; elf64_be_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; elf64_le_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; + bpf_elf64_le_vec) tb="$tb elf64-bpf.lo elf64.lo $elf" ;; + bpf_elf64_be_vec) tb="$tb elf64-bpf.lo elf64.lo $elf" ;; epiphany_elf32_vec) tb="$tb elf32-epiphany.lo elf32.lo $elf" ;; fr30_elf32_vec) tb="$tb elf32-fr30.lo elf32.lo $elf" ;; frv_elf32_vec) tb="$tb elf32-frv.lo elf32.lo $elf" ;; diff --git a/bfd/configure.ac b/bfd/configure.ac index 82aa5b1803..fe6754e789 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -476,6 +476,8 @@ do elf32_le_vec) tb="$tb elf32-gen.lo elf32.lo $elf" ;; elf64_be_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; elf64_le_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;; + bpf_elf64_le_vec) tb="$tb elf64-bpf.lo elf64.lo $elf" ;; + bpf_elf64_be_vec) tb="$tb elf64-bpf.lo elf64.lo $elf" ;; epiphany_elf32_vec) tb="$tb elf32-epiphany.lo elf32.lo $elf" ;; fr30_elf32_vec) tb="$tb elf32-fr30.lo elf32.lo $elf" ;; frv_elf32_vec) tb="$tb elf32-frv.lo elf32.lo $elf" ;; diff --git a/bfd/cpu-bpf.c b/bfd/cpu-bpf.c new file mode 100644 index 0000000000..57fe7d7502 --- /dev/null +++ b/bfd/cpu-bpf.c @@ -0,0 +1,41 @@ +/* BFD support for the BPF processor. + Copyright (C) 2019 Free Software Foundation, Inc. + Contributed by Oracle Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" + +const bfd_arch_info_type bfd_bpf_arch = +{ + 64, /* Bits per word */ + 64, /* Bits per address. */ + 8, /* Bits per byte. */ + bfd_arch_bpf, /* Architecture. */ + bfd_mach_bpf, /* Machine. */ + "bpf", /* Architecture name. */ + "bpf", /* Machine name. */ + 3, /* Section align power. */ + TRUE, /* The default ? */ + bfd_default_compatible, /* Architecture comparison fn. */ + bfd_default_scan, /* String to architecture convert fn. */ + bfd_arch_default_fill, /* Default fill. */ + NULL /* Next in list. */ +}; diff --git a/bfd/elf64-bpf.c b/bfd/elf64-bpf.c new file mode 100644 index 0000000000..3bfa25b54b --- /dev/null +++ b/bfd/elf64-bpf.c @@ -0,0 +1,463 @@ +/* Linux bpf specific support for 64-bit ELF + Copyright (C) 2019 Free Software Foundation, Inc. + Contributed by Oracle Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "elf/bpf.h" +#include "libiberty.h" + +/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ +#define MINUS_ONE (~ (bfd_vma) 0) + +#define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset) + +/* Handler for PC-relative relocations, which must be handled in + 64-bit words. */ + +static bfd_reloc_status_type +bpf_elf_insn_disp_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_signed_vma addend; + reloc_howto_type *howto = reloc_entry->howto; + + /* This part is from bfd_elf_generic_reloc. */ + if (output_bfd != NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && (! reloc_entry->howto->partial_inplace + || reloc_entry->addend == 0)) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + + /* This works because partial_inplace is FALSE. */ + if (output_bfd != NULL) + return bfd_reloc_continue; + + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + return bfd_reloc_outofrange; + + relocation = (symbol->value + + symbol->section->output_section->vma + + symbol->section->output_offset); + /* Make it PC relative. */ + relocation -= (input_section->output_section->vma + + input_section->output_offset); + relocation -= reloc_entry->address; + /* Make it 64-bit words. */ + relocation = relocation / 8; + + /* Get the addend from the instruction and apply it. */ + switch (howto->bitsize) + { + default: + abort (); + break; + case 16: + addend = bfd_get_16 (abfd, (bfd_byte *) data + reloc_entry->address + 2); + break; + case 32: + addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address + 4); + break; + } + + if ((addend & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0) + addend -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1; + relocation += addend; + + /* Write out the relocated value. */ + switch (howto->bitsize) + { + default: + abort (); + break; + case 16: + bfd_put_16 (abfd, relocation, (bfd_byte *) data + reloc_entry->address + 2); + break; + case 32: + bfd_put_32 (abfd, relocation, (bfd_byte *) data + reloc_entry->address + 4); + break; + } + + /* Check for overflow. */ + if (howto->complain_on_overflow == complain_overflow_signed) + { + bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; + bfd_signed_vma reloc_signed_min = ~reloc_signed_max; + + if (relocation > reloc_signed_max || relocation < reloc_signed_min) + return bfd_reloc_overflow; + } + else + abort(); + + return bfd_reloc_ok; +} + +/* Relocation tables. */ +static reloc_howto_type bpf_elf_howto_table [] = +{ + /* This reloc does nothing. */ + HOWTO (R_BPF_NONE, /* type */ + 0, /* rightshift */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_NONE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 64-immediate in LDDW instruction. */ + HOWTO (R_BPF_INSN_64, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_INSN_64", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + MINUS_ONE, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* 32-immediate in LDDW instruction. */ + HOWTO (R_BPF_INSN_32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_INSN_32", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* 16-bit offsets in instructions. */ + HOWTO (R_BPF_INSN_16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_INSN_16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0x0000ffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* 16-bit PC-relative address in jump instructions. */ + HOWTO (R_BPF_INSN_DISP16, /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 32, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bpf_elf_insn_disp_reloc, /* special_function */ + "R_BPF_INSN_DISP16", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_BPF_DATA_8_PCREL, + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_8_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_BPF_DATA_16_PCREL, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_16_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_BPF_DATA_32_PCREL, + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_32_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_BPF_DATA_8, + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_DATA_8", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_BPF_DATA_16, + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_DATA_16", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 32-bit PC-relative address in call instructions. */ + HOWTO (R_BPF_INSN_DISP32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bpf_elf_insn_disp_reloc, /* special_function */ + "R_BPF_INSN_DISP32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* 32-bit data. */ + HOWTO (R_BPF_DATA_32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_DATA_32", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0xffffffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* 64-bit data. */ + HOWTO (R_BPF_DATA_64, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_DATA_64", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + MINUS_ONE, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (R_BPF_DATA_64_PCREL, + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_BPF_64_PCREL", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + MINUS_ONE, /* dst_mask */ + TRUE), /* pcrel_offset */ +}; +#undef AHOW + +/* Map BFD reloc types to bpf ELF reloc types. */ + +static reloc_howto_type * +bpf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) +{ + /* Note that the bpf_elf_howto_table is indxed by the R_ + constants. Thus, the order that the howto records appear in the + table *must* match the order of the relocation types defined in + include/elf/bpf.h. */ + + switch (code) + { + case BFD_RELOC_NONE: + return &bpf_elf_howto_table[ (int) R_BPF_NONE]; + + case BFD_RELOC_8_PCREL: + return &bpf_elf_howto_table[ (int) R_BPF_DATA_8_PCREL]; + case BFD_RELOC_16_PCREL: + return &bpf_elf_howto_table[ (int) R_BPF_DATA_16_PCREL]; + case BFD_RELOC_32_PCREL: + return &bpf_elf_howto_table[ (int) R_BPF_DATA_32_PCREL]; + case BFD_RELOC_64_PCREL: + return &bpf_elf_howto_table[ (int) R_BPF_DATA_64_PCREL]; + + case BFD_RELOC_8: + return &bpf_elf_howto_table[ (int) R_BPF_DATA_8]; + case BFD_RELOC_16: + return &bpf_elf_howto_table[ (int) R_BPF_DATA_16]; + case BFD_RELOC_32: + return &bpf_elf_howto_table[ (int) R_BPF_DATA_32]; + case BFD_RELOC_64: + return &bpf_elf_howto_table[ (int) R_BPF_DATA_64]; + + case BFD_RELOC_BPF_64: + return &bpf_elf_howto_table[ (int) R_BPF_INSN_64]; + case BFD_RELOC_BPF_32: + return &bpf_elf_howto_table[ (int) R_BPF_INSN_32]; + case BFD_RELOC_BPF_16: + return &bpf_elf_howto_table[ (int) R_BPF_INSN_16]; + case BFD_RELOC_BPF_DISP16: + return &bpf_elf_howto_table[ (int) R_BPF_INSN_DISP16]; + case BFD_RELOC_BPF_DISP32: + return &bpf_elf_howto_table[ (int) R_BPF_INSN_DISP32]; + + default: + /* Pacify gcc -Wall. */ + return NULL; + } + return NULL; +} + +/* Map BFD reloc names to bpf ELF reloc names. */ + +static reloc_howto_type * +bpf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE (bpf_elf_howto_table); i++) + if (bpf_elf_howto_table[i].name != NULL + && strcasecmp (bpf_elf_howto_table[i].name, r_name) == 0) + return &bpf_elf_howto_table[i]; + + return NULL; +} + +/* Set the howto pointer for a bpf reloc. */ + +static bfd_boolean +bpf_info_to_howto (bfd *abfd, arelent *bfd_reloc, + Elf_Internal_Rela *elf_reloc) +{ + unsigned int r_type; + + r_type = ELF64_R_TYPE (elf_reloc->r_info); + if (r_type >= (unsigned int) R_BPF_max) + { + /* xgettext:c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + abfd, r_type); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + bfd_reloc->howto = &bpf_elf_howto_table [r_type]; + return TRUE; +} + +/* Merge backend specific data from an object file to the output + object file when linking. */ + +static bfd_boolean +elf64_bpf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) +{ + /* Check if we have the same endianness. */ + if (! _bfd_generic_verify_endian_match (ibfd, info)) + return FALSE; + + return TRUE; +} + +/* The macros below configure the architecture. */ + +#define TARGET_LITTLE_SYM bpf_elf64_le_vec +#define TARGET_LITTLE_NAME "elf64-bpfle" + +#define TARGET_BIG_SYM bpf_elf64_be_vec +#define TARGET_BIG_NAME "elf64-bpfbe" + +#define ELF_ARCH bfd_arch_bpf +#define ELF_MACHINE_CODE EM_BPF + +#define ELF_MAXPAGESIZE 0x100000 + +#define elf_info_to_howto_rel bpf_info_to_howto +#define elf_info_to_howto bpf_info_to_howto + +#define elf_backend_may_use_rel_p 1 +#define elf_backend_may_use_rela_p 0 +#define elf_backend_default_use_rela_p 0 + +#define elf_backend_can_gc_sections 0 + +#define elf_symbol_leading_char '_' +#define bfd_elf64_bfd_reloc_type_lookup bpf_reloc_type_lookup +#define bfd_elf64_bfd_reloc_name_lookup bpf_reloc_name_lookup + +#define bfd_elf64_bfd_merge_private_bfd_data elf64_bpf_merge_private_bfd_data + +#include "elf64-target.h" diff --git a/bfd/libbfd.h b/bfd/libbfd.h index d9b7fb7fa5..da52a2b098 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -3238,6 +3238,11 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_TILEGX_IMM8_X1_TLS_ADD", "BFD_RELOC_TILEGX_IMM8_Y0_TLS_ADD", "BFD_RELOC_TILEGX_IMM8_Y1_TLS_ADD", + "BFD_RELOC_BPF_64", + "BFD_RELOC_BPF_32", + "BFD_RELOC_BPF_16", + "BFD_RELOC_BPF_DISP16", + "BFD_RELOC_BPF_DISP32", "BFD_RELOC_EPIPHANY_SIMM8", "BFD_RELOC_EPIPHANY_SIMM24", "BFD_RELOC_EPIPHANY_HIGH", diff --git a/bfd/reloc.c b/bfd/reloc.c index f1465813f7..8f0263e354 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -7882,6 +7882,19 @@ ENUMX ENUMDOC Tilera TILE-Gx Relocations. +ENUM + BFD_RELOC_BPF_64 +ENUMX + BFD_RELOC_BPF_32 +ENUMX + BFD_RELOC_BPF_16 +ENUMX + BFD_RELOC_BPF_DISP16 +ENUMX + BFD_RELOC_BPF_DISP32 +ENUMDOC + Linux eBPF relocations. + ENUM BFD_RELOC_EPIPHANY_SIMM8 ENUMDOC diff --git a/bfd/targets.c b/bfd/targets.c index 158168cb3b..d3d52a5e2a 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -639,6 +639,8 @@ extern const bfd_target elf32_be_vec; extern const bfd_target elf32_le_vec; extern const bfd_target elf64_be_vec; extern const bfd_target elf64_le_vec; +extern const bfd_target bpf_elf64_le_vec; +extern const bfd_target bpf_elf64_be_vec; extern const bfd_target epiphany_elf32_vec; extern const bfd_target fr30_elf32_vec; extern const bfd_target frv_elf32_vec; @@ -1020,6 +1022,11 @@ static const bfd_target * const _bfd_target_vector[] = &iamcu_elf32_vec, +#ifdef BFD64 + &bpf_elf64_be_vec, + &bpf_elf64_le_vec, +#endif + #ifdef BFD64 #if 0 &ia64_elf32_be_vec, -- 2.34.1