Home | History | Annotate | Line # | Download | only in bfd
      1      1.1  christos /* Linux bpf specific support for 64-bit ELF
      2  1.1.1.5  christos    Copyright (C) 2019-2026 Free Software Foundation, Inc.
      3      1.1  christos    Contributed by Oracle Inc.
      4      1.1  christos 
      5      1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      6      1.1  christos 
      7      1.1  christos    This program is free software; you can redistribute it and/or modify
      8      1.1  christos    it under the terms of the GNU General Public License as published by
      9      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10      1.1  christos    (at your option) any later version.
     11      1.1  christos 
     12      1.1  christos    This program is distributed in the hope that it will be useful,
     13      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  christos    GNU General Public License for more details.
     16      1.1  christos 
     17      1.1  christos    You should have received a copy of the GNU General Public License
     18      1.1  christos    along with this program; if not, write to the Free Software
     19      1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20      1.1  christos    MA 02110-1301, USA.  */
     21      1.1  christos 
     22      1.1  christos #include "sysdep.h"
     23      1.1  christos #include "bfd.h"
     24      1.1  christos #include "libbfd.h"
     25      1.1  christos #include "elf-bfd.h"
     26      1.1  christos #include "elf/bpf.h"
     27      1.1  christos #include "libiberty.h"
     28      1.1  christos 
     29      1.1  christos /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
     30      1.1  christos #define MINUS_ONE (~ (bfd_vma) 0)
     31      1.1  christos 
     32      1.1  christos #define BASEADDR(SEC)	((SEC)->output_section->vma + (SEC)->output_offset)
     33      1.1  christos 
     34  1.1.1.2  christos static bfd_reloc_status_type bpf_elf_generic_reloc
     35  1.1.1.2  christos   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
     36  1.1.1.2  christos 
     37  1.1.1.3  christos #undef BPF_HOWTO
     38  1.1.1.3  christos #define BPF_HOWTO(type, right, size, bits, pcrel, left, ovf, func, name,   \
     39  1.1.1.3  christos 		  inplace, src_mask, dst_mask, pcrel_off)                  \
     40  1.1.1.3  christos 	type##_IDX,
     41  1.1.1.3  christos enum bpf_reloc_index {
     42  1.1.1.3  christos   R_BPF_INVALID_IDX = -1,
     43  1.1.1.3  christos #include "bpf-reloc.def"
     44  1.1.1.3  christos   R_BPF_SIZE
     45  1.1.1.3  christos };
     46  1.1.1.3  christos #undef BPF_HOWTO
     47  1.1.1.3  christos 
     48      1.1  christos /* Relocation tables.  */
     49  1.1.1.3  christos #define BPF_HOWTO(...) HOWTO(__VA_ARGS__),
     50      1.1  christos static reloc_howto_type bpf_elf_howto_table [] =
     51      1.1  christos {
     52  1.1.1.3  christos   #include "bpf-reloc.def"
     53      1.1  christos };
     54      1.1  christos #undef AHOW
     55  1.1.1.3  christos #undef BPF_HOWTO
     56  1.1.1.3  christos 
     57  1.1.1.3  christos #define BPF_HOWTO(type, right, size, bits, pcrel, left, ovf, func, name,   \
     58  1.1.1.3  christos 		  inplace, src_mask, dst_mask, pcrel_off)                  \
     59  1.1.1.3  christos     case type: { return type##_IDX; }
     60  1.1.1.3  christos static enum bpf_reloc_index
     61  1.1.1.3  christos bpf_index_for_rtype(unsigned int r_type)
     62  1.1.1.3  christos {
     63  1.1.1.3  christos   switch(r_type) {
     64  1.1.1.3  christos #include "bpf-reloc.def"
     65  1.1.1.3  christos     default:
     66  1.1.1.3  christos       /* Unreachable code. */
     67  1.1.1.3  christos       BFD_ASSERT(0);
     68  1.1.1.3  christos       return -1;
     69  1.1.1.3  christos   };
     70  1.1.1.3  christos }
     71      1.1  christos 
     72      1.1  christos /* Map BFD reloc types to bpf ELF reloc types.  */
     73      1.1  christos 
     74      1.1  christos static reloc_howto_type *
     75      1.1  christos bpf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
     76      1.1  christos                         bfd_reloc_code_real_type code)
     77      1.1  christos {
     78      1.1  christos   switch (code)
     79      1.1  christos     {
     80      1.1  christos     case BFD_RELOC_NONE:
     81  1.1.1.3  christos       return &bpf_elf_howto_table[ (int) R_BPF_NONE_IDX];
     82      1.1  christos 
     83      1.1  christos     case BFD_RELOC_32:
     84  1.1.1.3  christos       return &bpf_elf_howto_table[ (int) R_BPF_64_ABS32_IDX];
     85      1.1  christos     case BFD_RELOC_64:
     86  1.1.1.3  christos       return &bpf_elf_howto_table[ (int) R_BPF_64_ABS64_IDX];
     87      1.1  christos 
     88      1.1  christos     case BFD_RELOC_BPF_64:
     89  1.1.1.3  christos       return &bpf_elf_howto_table[ (int) R_BPF_64_64_IDX];
     90      1.1  christos     case BFD_RELOC_BPF_DISP32:
     91  1.1.1.3  christos     case BFD_RELOC_BPF_DISPCALL32:
     92  1.1.1.3  christos       return &bpf_elf_howto_table[ (int) R_BPF_64_32_IDX];
     93  1.1.1.3  christos     case BFD_RELOC_BPF_DISP16:
     94  1.1.1.3  christos       return &bpf_elf_howto_table[ (int) R_BPF_GNU_64_16_IDX];
     95      1.1  christos 
     96      1.1  christos     default:
     97      1.1  christos       /* Pacify gcc -Wall.  */
     98      1.1  christos       return NULL;
     99      1.1  christos     }
    100      1.1  christos   return NULL;
    101      1.1  christos }
    102      1.1  christos 
    103      1.1  christos /* Map BFD reloc names to bpf ELF reloc names.  */
    104      1.1  christos 
    105      1.1  christos static reloc_howto_type *
    106      1.1  christos bpf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
    107      1.1  christos {
    108      1.1  christos   unsigned int i;
    109      1.1  christos 
    110  1.1.1.3  christos   for (i = 0; i < R_BPF_SIZE; i++)
    111      1.1  christos     if (bpf_elf_howto_table[i].name != NULL
    112      1.1  christos 	&& strcasecmp (bpf_elf_howto_table[i].name, r_name) == 0)
    113      1.1  christos       return &bpf_elf_howto_table[i];
    114      1.1  christos 
    115      1.1  christos   return NULL;
    116      1.1  christos }
    117      1.1  christos 
    118      1.1  christos /* Set the howto pointer for a bpf reloc.  */
    119      1.1  christos 
    120  1.1.1.2  christos static bool
    121      1.1  christos bpf_info_to_howto (bfd *abfd, arelent *bfd_reloc,
    122      1.1  christos                     Elf_Internal_Rela *elf_reloc)
    123      1.1  christos {
    124      1.1  christos   unsigned int r_type;
    125  1.1.1.3  christos   unsigned int i;
    126      1.1  christos   r_type = ELF64_R_TYPE (elf_reloc->r_info);
    127  1.1.1.3  christos 
    128  1.1.1.3  christos   i = bpf_index_for_rtype(r_type);
    129  1.1.1.3  christos   if (i == (unsigned int) -1)
    130      1.1  christos     {
    131      1.1  christos       /* xgettext:c-format */
    132      1.1  christos       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
    133      1.1  christos                           abfd, r_type);
    134      1.1  christos       bfd_set_error (bfd_error_bad_value);
    135  1.1.1.2  christos       return false;
    136      1.1  christos     }
    137      1.1  christos 
    138  1.1.1.3  christos   bfd_reloc->howto = &bpf_elf_howto_table [i];
    139  1.1.1.2  christos   return true;
    140      1.1  christos }
    141      1.1  christos 
    142      1.1  christos /* Relocate an eBPF ELF section.
    143      1.1  christos 
    144      1.1  christos    The RELOCATE_SECTION function is called by the new ELF backend linker
    145      1.1  christos    to handle the relocations for a section.
    146      1.1  christos 
    147      1.1  christos    The relocs are always passed as Rela structures; if the section
    148      1.1  christos    actually uses Rel structures, the r_addend field will always be
    149      1.1  christos    zero.
    150      1.1  christos 
    151      1.1  christos    This function is responsible for adjusting the section contents as
    152      1.1  christos    necessary, and (if using Rela relocs and generating a relocatable
    153      1.1  christos    output file) adjusting the reloc addend as necessary.
    154      1.1  christos 
    155      1.1  christos    This function does not have to worry about setting the reloc
    156      1.1  christos    address or the reloc symbol index.
    157      1.1  christos 
    158      1.1  christos    LOCAL_SYMS is a pointer to the swapped in local symbols.
    159      1.1  christos 
    160      1.1  christos    LOCAL_SECTIONS is an array giving the section in the input file
    161      1.1  christos    corresponding to the st_shndx field of each local symbol.
    162      1.1  christos 
    163      1.1  christos    The global hash table entry for the global symbols can be found
    164      1.1  christos    via elf_sym_hashes (input_bfd).
    165      1.1  christos 
    166      1.1  christos    When generating relocatable output, this function must handle
    167      1.1  christos    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
    168      1.1  christos    going to be the section symbol corresponding to the output
    169      1.1  christos    section, which means that the addend must be adjusted
    170      1.1  christos    accordingly.  */
    171      1.1  christos 
    172      1.1  christos #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
    173      1.1  christos 
    174  1.1.1.2  christos static int
    175      1.1  christos bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
    176      1.1  christos                           struct bfd_link_info *info,
    177      1.1  christos                           bfd *input_bfd,
    178      1.1  christos                           asection *input_section,
    179      1.1  christos                           bfd_byte *contents,
    180      1.1  christos                           Elf_Internal_Rela *relocs,
    181      1.1  christos                           Elf_Internal_Sym *local_syms,
    182      1.1  christos                           asection **local_sections)
    183      1.1  christos {
    184      1.1  christos   Elf_Internal_Shdr *symtab_hdr;
    185      1.1  christos   struct elf_link_hash_entry **sym_hashes;
    186      1.1  christos   Elf_Internal_Rela *rel;
    187      1.1  christos   Elf_Internal_Rela *relend;
    188      1.1  christos 
    189      1.1  christos   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
    190      1.1  christos   sym_hashes = elf_sym_hashes (input_bfd);
    191      1.1  christos   relend     = relocs + input_section->reloc_count;
    192      1.1  christos 
    193      1.1  christos   for (rel = relocs; rel < relend; rel ++)
    194      1.1  christos     {
    195      1.1  christos       reloc_howto_type *	   howto;
    196  1.1.1.3  christos       unsigned int		   howto_index;
    197      1.1  christos       unsigned long		   r_symndx;
    198      1.1  christos       Elf_Internal_Sym *	   sym;
    199      1.1  christos       asection *		   sec;
    200      1.1  christos       struct elf_link_hash_entry * h;
    201      1.1  christos       bfd_vma			   relocation;
    202      1.1  christos       bfd_reloc_status_type	   r;
    203      1.1  christos       const char *		   name = NULL;
    204      1.1  christos       int			   r_type ATTRIBUTE_UNUSED;
    205  1.1.1.2  christos       bfd_signed_vma               addend;
    206  1.1.1.2  christos       bfd_byte                   * where;
    207      1.1  christos 
    208      1.1  christos       r_type = ELF64_R_TYPE (rel->r_info);
    209      1.1  christos       r_symndx = ELF64_R_SYM (rel->r_info);
    210  1.1.1.3  christos 
    211  1.1.1.3  christos       howto_index = bpf_index_for_rtype (ELF64_R_TYPE (rel->r_info));
    212  1.1.1.3  christos       howto  = &bpf_elf_howto_table[howto_index];
    213      1.1  christos       h      = NULL;
    214      1.1  christos       sym    = NULL;
    215      1.1  christos       sec    = NULL;
    216  1.1.1.2  christos       where  = contents + rel->r_offset;
    217      1.1  christos 
    218      1.1  christos       if (r_symndx < symtab_hdr->sh_info)
    219      1.1  christos 	{
    220      1.1  christos 	  sym = local_syms + r_symndx;
    221      1.1  christos 	  sec = local_sections [r_symndx];
    222      1.1  christos 	  relocation = BASEADDR (sec) + sym->st_value;
    223      1.1  christos 
    224      1.1  christos 	  name = bfd_elf_string_from_elf_section
    225      1.1  christos 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
    226      1.1  christos 	  name = name == NULL ? bfd_section_name (sec) : name;
    227      1.1  christos 	}
    228      1.1  christos       else
    229      1.1  christos 	{
    230  1.1.1.2  christos 	  bool warned ATTRIBUTE_UNUSED;
    231  1.1.1.2  christos 	  bool unresolved_reloc ATTRIBUTE_UNUSED;
    232  1.1.1.2  christos 	  bool ignored ATTRIBUTE_UNUSED;
    233      1.1  christos 
    234      1.1  christos 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
    235      1.1  christos 				   r_symndx, symtab_hdr, sym_hashes,
    236      1.1  christos 				   h, sec, relocation,
    237      1.1  christos 				   unresolved_reloc, warned, ignored);
    238      1.1  christos 
    239      1.1  christos 	  name = h->root.root.string;
    240      1.1  christos 	}
    241      1.1  christos 
    242      1.1  christos       if (sec != NULL && discarded_section (sec))
    243      1.1  christos 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
    244  1.1.1.5  christos 					 rel, 1, relend, R_BPF_NONE,
    245  1.1.1.5  christos 					 howto, 0, contents);
    246      1.1  christos 
    247      1.1  christos       if (bfd_link_relocatable (info))
    248      1.1  christos 	continue;
    249      1.1  christos 
    250      1.1  christos       switch (howto->type)
    251      1.1  christos         {
    252  1.1.1.3  christos 	case R_BPF_64_32:
    253      1.1  christos           {
    254      1.1  christos             /* Make the relocation PC-relative, and change its unit to
    255  1.1.1.2  christos                64-bit words.  Note we need *signed* arithmetic
    256  1.1.1.2  christos                here.  */
    257  1.1.1.2  christos             relocation = ((bfd_signed_vma) relocation
    258  1.1.1.2  christos 			  - (sec_addr (input_section) + rel->r_offset));
    259  1.1.1.2  christos             relocation = (bfd_signed_vma) relocation / 8;
    260      1.1  christos 
    261      1.1  christos             /* Get the addend from the instruction and apply it.  */
    262      1.1  christos             addend = bfd_get (howto->bitsize, input_bfd,
    263      1.1  christos                               contents + rel->r_offset
    264      1.1  christos                               + (howto->bitsize == 16 ? 2 : 4));
    265      1.1  christos 
    266      1.1  christos             if ((addend & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
    267      1.1  christos               addend -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
    268      1.1  christos             relocation += addend;
    269      1.1  christos 
    270      1.1  christos             /* Write out the relocated value.  */
    271      1.1  christos             bfd_put (howto->bitsize, input_bfd, relocation,
    272      1.1  christos                      contents + rel->r_offset
    273      1.1  christos                      + (howto->bitsize == 16 ? 2 : 4));
    274      1.1  christos 
    275      1.1  christos             r = bfd_reloc_ok;
    276      1.1  christos             break;
    277      1.1  christos           }
    278  1.1.1.3  christos 	case R_BPF_64_ABS64:
    279  1.1.1.3  christos 	case R_BPF_64_ABS32:
    280  1.1.1.3  christos 	case R_BPF_64_NODYLD32:
    281  1.1.1.2  christos 	  {
    282  1.1.1.2  christos 	    addend = bfd_get (howto->bitsize, input_bfd, where);
    283  1.1.1.2  christos 	    relocation += addend;
    284  1.1.1.2  christos 	    bfd_put (howto->bitsize, input_bfd, relocation, where);
    285  1.1.1.2  christos 
    286  1.1.1.2  christos 	    r = bfd_reloc_ok;
    287  1.1.1.2  christos 	    break;
    288  1.1.1.2  christos 	  }
    289  1.1.1.3  christos 	case R_BPF_64_64:
    290  1.1.1.2  christos           {
    291  1.1.1.2  christos             /*
    292  1.1.1.2  christos                 LDDW instructions are 128 bits long, with a 64-bit immediate.
    293  1.1.1.2  christos                 The lower 32 bits of the immediate are in the same position
    294  1.1.1.2  christos                 as the imm32 field of other instructions.
    295  1.1.1.2  christos                 The upper 32 bits of the immediate are stored at the end of
    296  1.1.1.2  christos                 the instruction.
    297  1.1.1.2  christos              */
    298  1.1.1.2  christos 
    299  1.1.1.2  christos 
    300  1.1.1.2  christos             /* Get the addend. The upper and lower 32 bits are split.
    301  1.1.1.2  christos                'where' is the beginning of the 16-byte instruction. */
    302  1.1.1.2  christos             addend = bfd_get_32 (input_bfd, where + 4);
    303  1.1.1.2  christos             addend |= (bfd_get_32 (input_bfd, where + 12) << 32);
    304  1.1.1.2  christos 
    305  1.1.1.2  christos             relocation += addend;
    306  1.1.1.2  christos 
    307  1.1.1.2  christos             bfd_put_32 (input_bfd, (relocation & 0xFFFFFFFF), where + 4);
    308  1.1.1.2  christos             bfd_put_32 (input_bfd, (relocation >> 32), where + 12);
    309  1.1.1.2  christos             r = bfd_reloc_ok;
    310  1.1.1.2  christos             break;
    311  1.1.1.2  christos           }
    312      1.1  christos         default:
    313  1.1.1.2  christos 	  r = bfd_reloc_notsupported;
    314      1.1  christos         }
    315      1.1  christos 
    316  1.1.1.2  christos       if (r == bfd_reloc_ok)
    317  1.1.1.2  christos 	  r = bfd_check_overflow (howto->complain_on_overflow,
    318  1.1.1.2  christos 				  howto->bitsize,
    319  1.1.1.2  christos 				  howto->rightshift,
    320  1.1.1.2  christos 				  64, relocation);
    321  1.1.1.2  christos 
    322      1.1  christos       if (r != bfd_reloc_ok)
    323      1.1  christos 	{
    324      1.1  christos 	  const char * msg = NULL;
    325      1.1  christos 
    326      1.1  christos 	  switch (r)
    327      1.1  christos 	    {
    328      1.1  christos 	    case bfd_reloc_overflow:
    329      1.1  christos 	      (*info->callbacks->reloc_overflow)
    330      1.1  christos 		(info, (h ? &h->root : NULL), name, howto->name,
    331      1.1  christos 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
    332      1.1  christos 	      break;
    333      1.1  christos 
    334      1.1  christos 	    case bfd_reloc_undefined:
    335      1.1  christos 	      (*info->callbacks->undefined_symbol)
    336  1.1.1.2  christos 		(info, name, input_bfd, input_section, rel->r_offset, true);
    337      1.1  christos 	      break;
    338      1.1  christos 
    339      1.1  christos 	    case bfd_reloc_outofrange:
    340      1.1  christos 	      msg = _("internal error: out of range error");
    341      1.1  christos 	      break;
    342      1.1  christos 
    343      1.1  christos 	    case bfd_reloc_notsupported:
    344      1.1  christos 	      if (sym != NULL) /* Only if it's not an unresolved symbol.  */
    345      1.1  christos                 msg = _("internal error: relocation not supported");
    346      1.1  christos 	      break;
    347      1.1  christos 
    348      1.1  christos 	    case bfd_reloc_dangerous:
    349      1.1  christos 	      msg = _("internal error: dangerous relocation");
    350      1.1  christos 	      break;
    351      1.1  christos 
    352      1.1  christos 	    default:
    353      1.1  christos 	      msg = _("internal error: unknown error");
    354      1.1  christos 	      break;
    355      1.1  christos 	    }
    356      1.1  christos 
    357      1.1  christos 	  if (msg)
    358      1.1  christos 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
    359      1.1  christos 					 input_section, rel->r_offset);
    360      1.1  christos 	}
    361      1.1  christos     }
    362      1.1  christos 
    363  1.1.1.2  christos   return true;
    364      1.1  christos }
    365      1.1  christos 
    366      1.1  christos /* Merge backend specific data from an object file to the output
    367      1.1  christos    object file when linking.  */
    368      1.1  christos 
    369  1.1.1.2  christos static bool
    370      1.1  christos elf64_bpf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
    371      1.1  christos {
    372      1.1  christos   /* Check if we have the same endianness.  */
    373      1.1  christos   if (! _bfd_generic_verify_endian_match (ibfd, info))
    374  1.1.1.2  christos     return false;
    375      1.1  christos 
    376  1.1.1.2  christos   return true;
    377      1.1  christos }
    378      1.1  christos 
    379  1.1.1.2  christos /* A generic howto special function for installing BPF relocations.
    380  1.1.1.2  christos    This function will be called by the assembler (via bfd_install_relocation),
    381  1.1.1.2  christos    and by various get_relocated_section_contents functions.
    382  1.1.1.2  christos    At link time, bpf_elf_relocate_section will resolve the final relocations.
    383  1.1.1.2  christos 
    384  1.1.1.2  christos    BPF instructions are always big endian, and this approach avoids problems in
    385  1.1.1.2  christos    bfd_install_relocation.  */
    386  1.1.1.2  christos 
    387  1.1.1.2  christos static bfd_reloc_status_type
    388  1.1.1.2  christos bpf_elf_generic_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
    389  1.1.1.3  christos 		       void *data, asection *input_section, bfd *output_bfd,
    390  1.1.1.2  christos 		       char **error_message ATTRIBUTE_UNUSED)
    391  1.1.1.2  christos {
    392  1.1.1.2  christos 
    393  1.1.1.2  christos   bfd_signed_vma relocation;
    394  1.1.1.2  christos   bfd_reloc_status_type status;
    395  1.1.1.2  christos   bfd_byte *where;
    396  1.1.1.2  christos 
    397  1.1.1.3  christos   /* From bfd_elf_generic_reloc.  */
    398  1.1.1.3  christos   if (output_bfd != NULL
    399  1.1.1.3  christos       && (symbol->flags & BSF_SECTION_SYM) == 0
    400  1.1.1.3  christos       && (! reloc_entry->howto->partial_inplace
    401  1.1.1.3  christos 	  || reloc_entry->addend == 0))
    402  1.1.1.3  christos     {
    403  1.1.1.3  christos       reloc_entry->address += input_section->output_offset;
    404  1.1.1.3  christos       return bfd_reloc_ok;
    405  1.1.1.3  christos     }
    406  1.1.1.3  christos 
    407  1.1.1.3  christos   if (output_bfd == NULL
    408  1.1.1.3  christos       && !reloc_entry->howto->pc_relative
    409  1.1.1.3  christos       && (symbol->section->flags & SEC_DEBUGGING) != 0
    410  1.1.1.3  christos       && (input_section->flags & SEC_DEBUGGING) != 0)
    411  1.1.1.3  christos     reloc_entry->addend -= symbol->section->output_section->vma;
    412  1.1.1.3  christos 
    413  1.1.1.2  christos   /* Sanity check that the address is in range.  */
    414  1.1.1.2  christos   bfd_size_type end = bfd_get_section_limit_octets (abfd, input_section);
    415  1.1.1.2  christos   bfd_size_type reloc_size;
    416  1.1.1.3  christos   if (reloc_entry->howto->type == R_BPF_64_64)
    417  1.1.1.2  christos     reloc_size = 16;
    418  1.1.1.2  christos   else
    419  1.1.1.2  christos     reloc_size = (reloc_entry->howto->bitsize
    420  1.1.1.2  christos 		  + reloc_entry->howto->bitpos) / 8;
    421  1.1.1.2  christos 
    422  1.1.1.2  christos   if (reloc_entry->address > end
    423  1.1.1.2  christos       || end - reloc_entry->address < reloc_size)
    424  1.1.1.2  christos     return bfd_reloc_outofrange;
    425  1.1.1.2  christos 
    426  1.1.1.3  christos   /* Behave similarly to bfd_install_relocation with install_addend set.
    427  1.1.1.3  christos      That is, just install the addend and do not include the value of
    428  1.1.1.3  christos      the symbol.  */
    429  1.1.1.3  christos   relocation = reloc_entry->addend;
    430  1.1.1.2  christos 
    431  1.1.1.2  christos   if (symbol->flags & BSF_SECTION_SYM)
    432  1.1.1.2  christos     /* Relocation against a section symbol: add in the section base address.  */
    433  1.1.1.2  christos     relocation += BASEADDR (symbol->section);
    434  1.1.1.2  christos 
    435  1.1.1.2  christos   where = (bfd_byte *) data + reloc_entry->address;
    436  1.1.1.2  christos 
    437  1.1.1.2  christos   status = bfd_check_overflow (reloc_entry->howto->complain_on_overflow,
    438  1.1.1.2  christos 			       reloc_entry->howto->bitsize,
    439  1.1.1.2  christos 			       reloc_entry->howto->rightshift, 64, relocation);
    440  1.1.1.2  christos 
    441  1.1.1.2  christos   if (status != bfd_reloc_ok)
    442  1.1.1.2  christos     return status;
    443  1.1.1.2  christos 
    444  1.1.1.2  christos   /* Now finally install the relocation.  */
    445  1.1.1.3  christos   if (reloc_entry->howto->type == R_BPF_64_64)
    446  1.1.1.2  christos     {
    447  1.1.1.2  christos       /* lddw is a 128-bit (!) instruction that allows loading a 64-bit
    448  1.1.1.2  christos 	 immediate into a register. the immediate is split in half, with the
    449  1.1.1.2  christos 	 lower 32 bits in the same position as the imm32 field of other
    450  1.1.1.2  christos 	 instructions, and the upper 32 bits placed at the very end of the
    451  1.1.1.2  christos 	 instruction. that is, there are 32 unused bits between them. */
    452  1.1.1.2  christos 
    453  1.1.1.2  christos       bfd_put_32 (abfd, (relocation & 0xFFFFFFFF), where + 4);
    454  1.1.1.2  christos       bfd_put_32 (abfd, (relocation >> 32), where + 12);
    455  1.1.1.2  christos     }
    456  1.1.1.2  christos   else
    457  1.1.1.2  christos     {
    458  1.1.1.2  christos       /* For other kinds of relocations, the relocated value simply goes
    459  1.1.1.2  christos 	 BITPOS bits from the start of the entry. This is always a multiple
    460  1.1.1.2  christos 	 of 8, i.e. whole bytes.  */
    461  1.1.1.2  christos       bfd_put (reloc_entry->howto->bitsize, abfd, relocation,
    462  1.1.1.2  christos 	       where + reloc_entry->howto->bitpos / 8);
    463  1.1.1.2  christos     }
    464  1.1.1.2  christos 
    465  1.1.1.3  christos   if (output_bfd != NULL)
    466  1.1.1.3  christos     reloc_entry->address += input_section->output_offset;
    467  1.1.1.2  christos 
    468  1.1.1.2  christos   return bfd_reloc_ok;
    469  1.1.1.2  christos }
    470  1.1.1.2  christos 
    471  1.1.1.2  christos 
    472      1.1  christos /* The macros below configure the architecture.  */
    473      1.1  christos 
    474      1.1  christos #define TARGET_LITTLE_SYM bpf_elf64_le_vec
    475      1.1  christos #define TARGET_LITTLE_NAME "elf64-bpfle"
    476      1.1  christos 
    477      1.1  christos #define TARGET_BIG_SYM bpf_elf64_be_vec
    478      1.1  christos #define TARGET_BIG_NAME "elf64-bpfbe"
    479      1.1  christos 
    480      1.1  christos #define ELF_ARCH bfd_arch_bpf
    481      1.1  christos #define ELF_MACHINE_CODE EM_BPF
    482      1.1  christos 
    483      1.1  christos #define ELF_MAXPAGESIZE 0x100000
    484      1.1  christos 
    485      1.1  christos #define elf_info_to_howto_rel bpf_info_to_howto
    486      1.1  christos #define elf_info_to_howto bpf_info_to_howto
    487      1.1  christos 
    488      1.1  christos #define elf_backend_may_use_rel_p		1
    489      1.1  christos #define elf_backend_may_use_rela_p		0
    490      1.1  christos #define elf_backend_default_use_rela_p		0
    491      1.1  christos #define elf_backend_relocate_section		bpf_elf_relocate_section
    492      1.1  christos 
    493      1.1  christos #define elf_backend_can_gc_sections		0
    494      1.1  christos 
    495      1.1  christos #define elf_symbol_leading_char			'_'
    496      1.1  christos #define bfd_elf64_bfd_reloc_type_lookup		bpf_reloc_type_lookup
    497      1.1  christos #define bfd_elf64_bfd_reloc_name_lookup		bpf_reloc_name_lookup
    498      1.1  christos 
    499      1.1  christos #define bfd_elf64_bfd_merge_private_bfd_data elf64_bpf_merge_private_bfd_data
    500      1.1  christos 
    501      1.1  christos #include "elf64-target.h"
    502