xref: /netbsd/external/gpl3/gdb/dist/bfd/elf64-bpf.c (revision 1424dfb3)
1 /* Linux bpf specific support for 64-bit ELF
2    Copyright (C) 2019-2020 Free Software Foundation, Inc.
3    Contributed by Oracle Inc.
4 
5    This file is part of BFD, the Binary File Descriptor library.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21 
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/bpf.h"
27 #include "libiberty.h"
28 
29 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value.  */
30 #define MINUS_ONE (~ (bfd_vma) 0)
31 
32 #define BASEADDR(SEC)	((SEC)->output_section->vma + (SEC)->output_offset)
33 
34 static bfd_reloc_status_type bpf_elf_generic_reloc
35   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
36 
37 /* Relocation tables.  */
38 static reloc_howto_type bpf_elf_howto_table [] =
39 {
40   /* This reloc does nothing.  */
41   HOWTO (R_BPF_NONE,		/* type */
42 	 0,			/* rightshift */
43 	 3,			/* size (0 = byte, 1 = short, 2 = long) */
44 	 0,			/* bitsize */
45 	 FALSE,			/* pc_relative */
46 	 0,			/* bitpos */
47 	 complain_overflow_dont, /* complain_on_overflow */
48 	 bpf_elf_generic_reloc, /* special_function */
49 	 "R_BPF_NONE",		/* name */
50 	 FALSE,			/* partial_inplace */
51 	 0,			/* src_mask */
52 	 0,			/* dst_mask */
53 	 FALSE),		/* pcrel_offset */
54 
55   /* 64-immediate in LDDW instruction.  */
56   HOWTO (R_BPF_INSN_64,		/* type */
57 	 0,			/* rightshift */
58 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
59 	 64,			/* bitsize */
60 	 FALSE,			/* pc_relative */
61 	 32,			/* bitpos */
62 	 complain_overflow_signed, /* complain_on_overflow */
63 	 bpf_elf_generic_reloc, /* special_function */
64 	 "R_BPF_INSN_64",	/* name */
65 	 TRUE,			/* partial_inplace */
66 	 MINUS_ONE,		/* src_mask */
67 	 MINUS_ONE,		/* dst_mask */
68 	 TRUE),			/* pcrel_offset */
69 
70   /* 32-immediate in many instructions.  */
71   HOWTO (R_BPF_INSN_32,		/* type */
72 	 0,			/* rightshift */
73 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
74 	 32,			/* bitsize */
75 	 FALSE,			/* pc_relative */
76 	 32,			/* bitpos */
77 	 complain_overflow_signed, /* complain_on_overflow */
78 	 bpf_elf_generic_reloc, /* special_function */
79 	 "R_BPF_INSN_32",	/* name */
80 	 TRUE,			/* partial_inplace */
81 	 0xffffffff,		/* src_mask */
82 	 0xffffffff,		/* dst_mask */
83 	 TRUE),			/* pcrel_offset */
84 
85   /* 16-bit offsets in instructions.  */
86   HOWTO (R_BPF_INSN_16,		/* type */
87 	 0,			/* rightshift */
88 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
89 	 16,			/* bitsize */
90 	 FALSE,			/* pc_relative */
91 	 16,			/* bitpos */
92 	 complain_overflow_signed, /* complain_on_overflow */
93 	 bpf_elf_generic_reloc, /* special_function */
94 	 "R_BPF_INSN_16",	/* name */
95 	 TRUE,			/* partial_inplace */
96 	 0x0000ffff,		/* src_mask */
97 	 0x0000ffff,		/* dst_mask */
98 	 TRUE),			/* pcrel_offset */
99 
100   /* 16-bit PC-relative address in jump instructions.  */
101   HOWTO (R_BPF_INSN_DISP16,	/* type */
102 	 0,			/* rightshift */
103 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
104 	 16,			/* bitsize */
105 	 TRUE,			/* pc_relative */
106 	 16,			/* bitpos */
107 	 complain_overflow_signed, /* complain_on_overflow */
108 	 bpf_elf_generic_reloc, /* special_function */
109 	 "R_BPF_INSN_DISP16",   /* name */
110 	 TRUE,			/* partial_inplace */
111 	 0xffff,		/* src_mask */
112 	 0xffff,		/* dst_mask */
113 	 TRUE),			/* pcrel_offset */
114 
115   HOWTO (R_BPF_DATA_8_PCREL,
116 	 0,			/* rightshift */
117 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
118 	 8,			/* bitsize */
119 	 TRUE,			/* pc_relative */
120 	 0,			/* bitpos */
121 	 complain_overflow_signed, /* complain_on_overflow */
122 	 bpf_elf_generic_reloc, /* special_function */
123 	 "R_BPF_8_PCREL",	/* name */
124 	 TRUE,			/* partial_inplace */
125 	 0xff,			/* src_mask */
126 	 0xff,			/* dst_mask */
127 	 TRUE),			/* pcrel_offset */
128 
129   HOWTO (R_BPF_DATA_16_PCREL,
130 	 0,			/* rightshift */
131 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
132 	 16,			/* bitsize */
133 	 TRUE,			/* pc_relative */
134 	 0,			/* bitpos */
135 	 complain_overflow_signed, /* complain_on_overflow */
136 	 bpf_elf_generic_reloc, /* special_function */
137 	 "R_BPF_16_PCREL",	/* name */
138 	 FALSE,			/* partial_inplace */
139 	 0xffff,		/* src_mask */
140 	 0xffff,		/* dst_mask */
141 	 TRUE),			/* pcrel_offset */
142 
143   HOWTO (R_BPF_DATA_32_PCREL,
144 	 0,			/* rightshift */
145 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
146 	 32,			/* bitsize */
147 	 TRUE,			/* pc_relative */
148 	 0,			/* bitpos */
149 	 complain_overflow_signed, /* complain_on_overflow */
150 	 bpf_elf_generic_reloc, /* special_function */
151 	 "R_BPF_32_PCREL",	/* name */
152 	 FALSE,			/* partial_inplace */
153 	 0xffffffff,		/* src_mask */
154 	 0xffffffff,		/* dst_mask */
155 	 TRUE),			/* pcrel_offset */
156 
157   HOWTO (R_BPF_DATA_8,
158 	 0,			/* rightshift */
159 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
160 	 8,			/* bitsize */
161 	 FALSE,			/* pc_relative */
162 	 0,			/* bitpos */
163 	 complain_overflow_unsigned, /* complain_on_overflow */
164 	 bpf_elf_generic_reloc, /* special_function */
165 	 "R_BPF_DATA_8",	/* name */
166 	 TRUE,			/* partial_inplace */
167 	 0xff,			/* src_mask */
168 	 0xff,			/* dst_mask */
169 	 FALSE),		/* pcrel_offset */
170 
171   HOWTO (R_BPF_DATA_16,
172 	 0,			/* rightshift */
173 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
174 	 16,			/* bitsize */
175 	 FALSE,			/* pc_relative */
176 	 0,			/* bitpos */
177 	 complain_overflow_unsigned, /* complain_on_overflow */
178 	 bpf_elf_generic_reloc, /* special_function */
179 	 "R_BPF_DATA_16",	/* name */
180 	 FALSE,			/* partial_inplace */
181 	 0xffff,		/* src_mask */
182 	 0xffff,		/* dst_mask */
183 	 FALSE),		/* pcrel_offset */
184 
185   /* 32-bit PC-relative address in call instructions.  */
186   HOWTO (R_BPF_INSN_DISP32,	/* type */
187 	 0,			/* rightshift */
188 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
189 	 32,			/* bitsize */
190 	 TRUE,			/* pc_relative */
191 	 32,			/* bitpos */
192 	 complain_overflow_signed, /* complain_on_overflow */
193 	 bpf_elf_generic_reloc, /* special_function */
194 	 "R_BPF_INSN_DISP32",   /* name */
195 	 TRUE,			/* partial_inplace */
196 	 0xffffffff,		/* src_mask */
197 	 0xffffffff,		/* dst_mask */
198 	 TRUE),			/* pcrel_offset */
199 
200   /* 32-bit data.  */
201   HOWTO (R_BPF_DATA_32,		/* type */
202 	 0,			/* rightshift */
203 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
204 	 32,			/* bitsize */
205 	 FALSE,			/* pc_relative */
206 	 0,			/* bitpos */
207 	 complain_overflow_bitfield, /* complain_on_overflow */
208 	 bpf_elf_generic_reloc, /* special_function */
209 	 "R_BPF_DATA_32",	/* name */
210 	 FALSE,			/* partial_inplace */
211 	 0xffffffff,		/* src_mask */
212 	 0xffffffff,		/* dst_mask */
213 	 TRUE),			/* pcrel_offset */
214 
215   /* 64-bit data.  */
216   HOWTO (R_BPF_DATA_64,		/* type */
217 	 0,			/* rightshift */
218 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
219 	 64,			/* bitsize */
220 	 FALSE,			/* pc_relative */
221 	 0,			/* bitpos */
222 	 complain_overflow_bitfield, /* complain_on_overflow */
223 	 bpf_elf_generic_reloc, /* special_function */
224 	 "R_BPF_DATA_64",	/* name */
225 	 FALSE,			/* partial_inplace */
226 	 0,			/* src_mask */
227 	 MINUS_ONE,		/* dst_mask */
228 	 TRUE),			/* pcrel_offset */
229 
230   HOWTO (R_BPF_DATA_64_PCREL,
231 	 0,			/* rightshift */
232 	 4,			/* size (0 = byte, 1 = short, 2 = long) */
233 	 64,			/* bitsize */
234 	 TRUE,			/* pc_relative */
235 	 0,			/* bitpos */
236 	 complain_overflow_signed, /* complain_on_overflow */
237 	 bpf_elf_generic_reloc, /* special_function */
238 	 "R_BPF_64_PCREL",	/* name */
239 	 FALSE,			/* partial_inplace */
240 	 MINUS_ONE,		/* src_mask */
241 	 MINUS_ONE,		/* dst_mask */
242 	 TRUE),			/* pcrel_offset */
243 };
244 #undef AHOW
245 
246 /* Map BFD reloc types to bpf ELF reloc types.  */
247 
248 static reloc_howto_type *
bpf_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)249 bpf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
250                         bfd_reloc_code_real_type code)
251 {
252   /* Note that the bpf_elf_howto_table is indexed by the R_ constants.
253      Thus, the order that the howto records appear in the table *must*
254      match the order of the relocation types defined in
255      include/elf/bpf.h.  */
256 
257   switch (code)
258     {
259     case BFD_RELOC_NONE:
260       return &bpf_elf_howto_table[ (int) R_BPF_NONE];
261 
262     case BFD_RELOC_8_PCREL:
263       return &bpf_elf_howto_table[ (int) R_BPF_DATA_8_PCREL];
264     case BFD_RELOC_16_PCREL:
265       return &bpf_elf_howto_table[ (int) R_BPF_DATA_16_PCREL];
266     case BFD_RELOC_32_PCREL:
267       return &bpf_elf_howto_table[ (int) R_BPF_DATA_32_PCREL];
268     case BFD_RELOC_64_PCREL:
269       return &bpf_elf_howto_table[ (int) R_BPF_DATA_64_PCREL];
270 
271     case BFD_RELOC_8:
272       return &bpf_elf_howto_table[ (int) R_BPF_DATA_8];
273     case BFD_RELOC_16:
274       return &bpf_elf_howto_table[ (int) R_BPF_DATA_16];
275     case BFD_RELOC_32:
276       return &bpf_elf_howto_table[ (int) R_BPF_DATA_32];
277     case BFD_RELOC_64:
278       return &bpf_elf_howto_table[ (int) R_BPF_DATA_64];
279 
280     case BFD_RELOC_BPF_64:
281       return &bpf_elf_howto_table[ (int) R_BPF_INSN_64];
282     case BFD_RELOC_BPF_32:
283       return &bpf_elf_howto_table[ (int) R_BPF_INSN_32];
284     case BFD_RELOC_BPF_16:
285       return &bpf_elf_howto_table[ (int) R_BPF_INSN_16];
286     case BFD_RELOC_BPF_DISP16:
287       return &bpf_elf_howto_table[ (int) R_BPF_INSN_DISP16];
288     case BFD_RELOC_BPF_DISP32:
289       return &bpf_elf_howto_table[ (int) R_BPF_INSN_DISP32];
290 
291     default:
292       /* Pacify gcc -Wall.  */
293       return NULL;
294     }
295   return NULL;
296 }
297 
298 /* Map BFD reloc names to bpf ELF reloc names.  */
299 
300 static reloc_howto_type *
bpf_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)301 bpf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
302 {
303   unsigned int i;
304 
305   for (i = 0; i < ARRAY_SIZE (bpf_elf_howto_table); i++)
306     if (bpf_elf_howto_table[i].name != NULL
307 	&& strcasecmp (bpf_elf_howto_table[i].name, r_name) == 0)
308       return &bpf_elf_howto_table[i];
309 
310   return NULL;
311 }
312 
313 /* Set the howto pointer for a bpf reloc.  */
314 
315 static bfd_boolean
bpf_info_to_howto(bfd * abfd,arelent * bfd_reloc,Elf_Internal_Rela * elf_reloc)316 bpf_info_to_howto (bfd *abfd, arelent *bfd_reloc,
317                     Elf_Internal_Rela *elf_reloc)
318 {
319   unsigned int r_type;
320 
321   r_type = ELF64_R_TYPE (elf_reloc->r_info);
322   if (r_type >= (unsigned int) R_BPF_max)
323     {
324       /* xgettext:c-format */
325       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
326                           abfd, r_type);
327       bfd_set_error (bfd_error_bad_value);
328       return FALSE;
329     }
330 
331   bfd_reloc->howto = &bpf_elf_howto_table [r_type];
332   return TRUE;
333 }
334 
335 /* Relocate an eBPF ELF section.
336 
337    The RELOCATE_SECTION function is called by the new ELF backend linker
338    to handle the relocations for a section.
339 
340    The relocs are always passed as Rela structures; if the section
341    actually uses Rel structures, the r_addend field will always be
342    zero.
343 
344    This function is responsible for adjusting the section contents as
345    necessary, and (if using Rela relocs and generating a relocatable
346    output file) adjusting the reloc addend as necessary.
347 
348    This function does not have to worry about setting the reloc
349    address or the reloc symbol index.
350 
351    LOCAL_SYMS is a pointer to the swapped in local symbols.
352 
353    LOCAL_SECTIONS is an array giving the section in the input file
354    corresponding to the st_shndx field of each local symbol.
355 
356    The global hash table entry for the global symbols can be found
357    via elf_sym_hashes (input_bfd).
358 
359    When generating relocatable output, this function must handle
360    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
361    going to be the section symbol corresponding to the output
362    section, which means that the addend must be adjusted
363    accordingly.  */
364 
365 #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
366 
367 static bfd_boolean
bpf_elf_relocate_section(bfd * output_bfd ATTRIBUTE_UNUSED,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,Elf_Internal_Rela * relocs,Elf_Internal_Sym * local_syms,asection ** local_sections)368 bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
369                           struct bfd_link_info *info,
370                           bfd *input_bfd,
371                           asection *input_section,
372                           bfd_byte *contents,
373                           Elf_Internal_Rela *relocs,
374                           Elf_Internal_Sym *local_syms,
375                           asection **local_sections)
376 {
377   Elf_Internal_Shdr *symtab_hdr;
378   struct elf_link_hash_entry **sym_hashes;
379   Elf_Internal_Rela *rel;
380   Elf_Internal_Rela *relend;
381 
382   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
383   sym_hashes = elf_sym_hashes (input_bfd);
384   relend     = relocs + input_section->reloc_count;
385 
386   for (rel = relocs; rel < relend; rel ++)
387     {
388       reloc_howto_type *	   howto;
389       unsigned long		   r_symndx;
390       Elf_Internal_Sym *	   sym;
391       asection *		   sec;
392       struct elf_link_hash_entry * h;
393       bfd_vma			   relocation;
394       bfd_reloc_status_type	   r;
395       const char *		   name = NULL;
396       int			   r_type ATTRIBUTE_UNUSED;
397       bfd_signed_vma               addend;
398       bfd_byte                   * where;
399 
400       r_type = ELF64_R_TYPE (rel->r_info);
401       r_symndx = ELF64_R_SYM (rel->r_info);
402       howto  = bpf_elf_howto_table + ELF64_R_TYPE (rel->r_info);
403       h      = NULL;
404       sym    = NULL;
405       sec    = NULL;
406       where  = contents + rel->r_offset;
407 
408       if (r_symndx < symtab_hdr->sh_info)
409 	{
410 	  sym = local_syms + r_symndx;
411 	  sec = local_sections [r_symndx];
412 	  relocation = BASEADDR (sec) + sym->st_value;
413 
414 	  name = bfd_elf_string_from_elf_section
415 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
416 	  name = name == NULL ? bfd_section_name (sec) : name;
417 	}
418       else
419 	{
420 	  bfd_boolean warned ATTRIBUTE_UNUSED;
421 	  bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED;
422 	  bfd_boolean ignored ATTRIBUTE_UNUSED;
423 
424 	  RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
425 				   r_symndx, symtab_hdr, sym_hashes,
426 				   h, sec, relocation,
427 				   unresolved_reloc, warned, ignored);
428 
429 	  name = h->root.root.string;
430 	}
431 
432       if (sec != NULL && discarded_section (sec))
433 	RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
434 					 rel, 1, relend, howto, 0, contents);
435 
436       if (bfd_link_relocatable (info))
437 	continue;
438 
439       switch (howto->type)
440         {
441         case R_BPF_INSN_DISP16:
442         case R_BPF_INSN_DISP32:
443           {
444             /* Make the relocation PC-relative, and change its unit to
445                64-bit words.  Note we need *signed* arithmetic
446                here.  */
447             relocation = ((bfd_signed_vma) relocation
448 			  - (sec_addr (input_section) + rel->r_offset));
449             relocation = (bfd_signed_vma) relocation / 8;
450 
451             /* Get the addend from the instruction and apply it.  */
452             addend = bfd_get (howto->bitsize, input_bfd,
453                               contents + rel->r_offset
454                               + (howto->bitsize == 16 ? 2 : 4));
455 
456             if ((addend & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
457               addend -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
458             relocation += addend;
459 
460             /* Write out the relocated value.  */
461             bfd_put (howto->bitsize, input_bfd, relocation,
462                      contents + rel->r_offset
463                      + (howto->bitsize == 16 ? 2 : 4));
464 
465             r = bfd_reloc_ok;
466             break;
467           }
468 	case R_BPF_DATA_8:
469 	case R_BPF_DATA_16:
470 	case R_BPF_DATA_32:
471 	case R_BPF_DATA_64:
472 	  {
473 	    addend = bfd_get (howto->bitsize, input_bfd, where);
474 	    relocation += addend;
475 	    bfd_put (howto->bitsize, input_bfd, relocation, where);
476 
477 	    r = bfd_reloc_ok;
478 	    break;
479 	  }
480 	case R_BPF_INSN_16:
481 	  {
482 
483 	    addend = bfd_get_16 (input_bfd, where + 2);
484 	    relocation += addend;
485 	    bfd_put_16 (input_bfd, relocation, where + 2);
486 
487 	    r = bfd_reloc_ok;
488 	    break;
489 	  }
490         case R_BPF_INSN_32:
491           {
492             /*  Write relocated value */
493 
494 	    addend = bfd_get_32 (input_bfd, where + 4);
495 	    relocation += addend;
496             bfd_put_32 (input_bfd, relocation, where + 4);
497 
498             r = bfd_reloc_ok;
499             break;
500           }
501         case R_BPF_INSN_64:
502           {
503             /*
504                 LDDW instructions are 128 bits long, with a 64-bit immediate.
505                 The lower 32 bits of the immediate are in the same position
506                 as the imm32 field of other instructions.
507                 The upper 32 bits of the immediate are stored at the end of
508                 the instruction.
509              */
510 
511 
512             /* Get the addend. The upper and lower 32 bits are split.
513                'where' is the beginning of the 16-byte instruction. */
514             addend = bfd_get_32 (input_bfd, where + 4);
515             addend |= (bfd_get_32 (input_bfd, where + 12) << 32);
516 
517             relocation += addend;
518 
519             bfd_put_32 (input_bfd, (relocation & 0xFFFFFFFF), where + 4);
520             bfd_put_32 (input_bfd, (relocation >> 32), where + 12);
521             r = bfd_reloc_ok;
522             break;
523           }
524         default:
525 	  r = bfd_reloc_notsupported;
526         }
527 
528       if (r == bfd_reloc_ok)
529 	  r = bfd_check_overflow (howto->complain_on_overflow,
530 				  howto->bitsize,
531 				  howto->rightshift,
532 				  64, relocation);
533 
534       if (r != bfd_reloc_ok)
535 	{
536 	  const char * msg = NULL;
537 
538 	  switch (r)
539 	    {
540 	    case bfd_reloc_overflow:
541 	      (*info->callbacks->reloc_overflow)
542 		(info, (h ? &h->root : NULL), name, howto->name,
543 		 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
544 	      break;
545 
546 	    case bfd_reloc_undefined:
547 	      (*info->callbacks->undefined_symbol)
548 		(info, name, input_bfd, input_section, rel->r_offset, TRUE);
549 	      break;
550 
551 	    case bfd_reloc_outofrange:
552 	      msg = _("internal error: out of range error");
553 	      break;
554 
555 	    case bfd_reloc_notsupported:
556 	      if (sym != NULL) /* Only if it's not an unresolved symbol.  */
557                 msg = _("internal error: relocation not supported");
558 	      break;
559 
560 	    case bfd_reloc_dangerous:
561 	      msg = _("internal error: dangerous relocation");
562 	      break;
563 
564 	    default:
565 	      msg = _("internal error: unknown error");
566 	      break;
567 	    }
568 
569 	  if (msg)
570 	    (*info->callbacks->warning) (info, msg, name, input_bfd,
571 					 input_section, rel->r_offset);
572 	}
573     }
574 
575   return TRUE;
576 }
577 
578 /* Merge backend specific data from an object file to the output
579    object file when linking.  */
580 
581 static bfd_boolean
elf64_bpf_merge_private_bfd_data(bfd * ibfd,struct bfd_link_info * info)582 elf64_bpf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
583 {
584   /* Check if we have the same endianness.  */
585   if (! _bfd_generic_verify_endian_match (ibfd, info))
586     return FALSE;
587 
588   return TRUE;
589 }
590 
591 /* A generic howto special function for installing BPF relocations.
592    This function will be called by the assembler (via bfd_install_relocation).
593    At link time, bpf_elf_relocate_section will resolve the final relocations.
594 
595    BPF instructions are always big endian, and this approach avoids problems in
596    bfd_install_relocation.  */
597 
598 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)599 bpf_elf_generic_reloc (bfd * abfd, arelent *reloc_entry, asymbol *symbol,
600 		       void *data, asection *input_section,
601 		       bfd *output_bfd,
602 		       char **error_message ATTRIBUTE_UNUSED)
603 {
604 
605   bfd_signed_vma relocation;
606   bfd_reloc_status_type status;
607   bfd_byte *where;
608 
609   /* Sanity check that the address is in range.  */
610   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
611     return bfd_reloc_outofrange;
612 
613   /*  Get the symbol value.  */
614   if (bfd_is_com_section (symbol->section))
615     relocation = 0;
616   else
617     relocation = symbol->value;
618 
619   if (symbol->flags & BSF_SECTION_SYM)
620     /* Relocation against a section symbol: add in the section base address.  */
621     relocation += BASEADDR (symbol->section);
622 
623   relocation += reloc_entry->addend;
624 
625   where = (bfd_byte *) data + reloc_entry->address;
626 
627   status = bfd_check_overflow (reloc_entry->howto->complain_on_overflow,
628 			       reloc_entry->howto->bitsize,
629 			       reloc_entry->howto->rightshift, 64, relocation);
630 
631   if (status != bfd_reloc_ok)
632     return status;
633 
634   /* Now finally install the relocation.  */
635   if (reloc_entry->howto->type == R_BPF_INSN_64)
636     {
637       /* lddw is a 128-bit (!) instruction that allows loading a 64-bit
638 	 immediate into a register. the immediate is split in half, with the
639 	 lower 32 bits in the same position as the imm32 field of other
640 	 instructions, and the upper 32 bits placed at the very end of the
641 	 instruction. that is, there are 32 unused bits between them. */
642 
643       bfd_put_32 (output_bfd, (relocation & 0xFFFFFFFF), where + 4);
644       bfd_put_32 (output_bfd, (relocation >> 32), where + 12);
645     }
646   else
647     {
648       /* For other kinds of relocations, the relocated value simply goes
649 	 BITPOS bits from the start of the entry. This is always a multiple
650 	 of 8, i.e. whole bytes.  */
651       bfd_put (reloc_entry->howto->bitsize, output_bfd, relocation,
652 	       where + reloc_entry->howto->bitpos / 8);
653     }
654 
655   reloc_entry->addend = relocation;
656   reloc_entry->address += input_section->output_offset;
657 
658   return bfd_reloc_ok;
659 }
660 
661 
662 /* The macros below configure the architecture.  */
663 
664 #define TARGET_LITTLE_SYM bpf_elf64_le_vec
665 #define TARGET_LITTLE_NAME "elf64-bpfle"
666 
667 #define TARGET_BIG_SYM bpf_elf64_be_vec
668 #define TARGET_BIG_NAME "elf64-bpfbe"
669 
670 #define ELF_ARCH bfd_arch_bpf
671 #define ELF_MACHINE_CODE EM_BPF
672 
673 #define ELF_MAXPAGESIZE 0x100000
674 
675 #define elf_info_to_howto_rel bpf_info_to_howto
676 #define elf_info_to_howto bpf_info_to_howto
677 
678 #define elf_backend_may_use_rel_p		1
679 #define elf_backend_may_use_rela_p		0
680 #define elf_backend_default_use_rela_p		0
681 #define elf_backend_relocate_section		bpf_elf_relocate_section
682 
683 #define elf_backend_can_gc_sections		0
684 
685 #define elf_symbol_leading_char			'_'
686 #define bfd_elf64_bfd_reloc_type_lookup		bpf_reloc_type_lookup
687 #define bfd_elf64_bfd_reloc_name_lookup		bpf_reloc_name_lookup
688 
689 #define bfd_elf64_bfd_merge_private_bfd_data elf64_bpf_merge_private_bfd_data
690 
691 #include "elf64-target.h"
692