packaging: Enable testing infrastructure
[external/binutils.git] / bfd / elf64-bpf.c
1 /* Linux bpf specific support for 64-bit ELF
2    Copyright (C) 2019 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 /* Relocation tables.  */
35 static reloc_howto_type bpf_elf_howto_table [] =
36 {
37   /* This reloc does nothing.  */
38   HOWTO (R_BPF_NONE,            /* type */
39          0,                     /* rightshift */
40          3,                     /* size (0 = byte, 1 = short, 2 = long) */
41          0,                     /* bitsize */
42          FALSE,                 /* pc_relative */
43          0,                     /* bitpos */
44          complain_overflow_dont, /* complain_on_overflow */
45          bfd_elf_generic_reloc, /* special_function */
46          "R_BPF_NONE",          /* name */
47          FALSE,                 /* partial_inplace */
48          0,                     /* src_mask */
49          0,                     /* dst_mask */
50          FALSE),                /* pcrel_offset */
51
52   /* 64-immediate in LDDW instruction.  */
53   HOWTO (R_BPF_INSN_64,         /* type */
54          0,                     /* rightshift */
55          4,                     /* size (0 = byte, 1 = short, 2 = long) */
56          64,                    /* bitsize */
57          FALSE,                 /* pc_relative */
58          0,                     /* bitpos */
59          complain_overflow_signed, /* complain_on_overflow */
60          bfd_elf_generic_reloc, /* special_function */
61          "R_BPF_INSN_64",       /* name */
62          FALSE,                 /* partial_inplace */
63          0,                     /* src_mask */
64          MINUS_ONE,             /* dst_mask */
65          TRUE),                 /* pcrel_offset */
66
67   /* 32-immediate in LDDW instruction.  */
68   HOWTO (R_BPF_INSN_32,         /* type */
69          0,                     /* rightshift */
70          2,                     /* size (0 = byte, 1 = short, 2 = long) */
71          32,                    /* bitsize */
72          FALSE,                 /* pc_relative */
73          0,                     /* bitpos */
74          complain_overflow_signed, /* complain_on_overflow */
75          bfd_elf_generic_reloc, /* special_function */
76          "R_BPF_INSN_32",       /* name */
77          FALSE,                 /* partial_inplace */
78          0,                     /* src_mask */
79          0xffffffff,            /* dst_mask */
80          TRUE),                 /* pcrel_offset */
81
82   /* 16-bit offsets in instructions.  */
83   HOWTO (R_BPF_INSN_16,         /* type */
84          0,                     /* rightshift */
85          1,                     /* size (0 = byte, 1 = short, 2 = long) */
86          16,                    /* bitsize */
87          FALSE,                 /* pc_relative */
88          0,                     /* bitpos */
89          complain_overflow_signed, /* complain_on_overflow */
90          bfd_elf_generic_reloc, /* special_function */
91          "R_BPF_INSN_16",       /* name */
92          FALSE,                 /* partial_inplace */
93          0,                     /* src_mask */
94          0x0000ffff,            /* dst_mask */
95          TRUE),                 /* pcrel_offset */
96
97   /* 16-bit PC-relative address in jump instructions.  */
98   HOWTO (R_BPF_INSN_DISP16,     /* type */
99          0,                     /* rightshift */
100          1,                     /* size (0 = byte, 1 = short, 2 = long) */
101          16,                    /* bitsize */
102          TRUE,                  /* pc_relative */
103          32,                    /* bitpos */
104          complain_overflow_signed, /* complain_on_overflow */
105          bfd_elf_generic_reloc, /* special_function */
106          "R_BPF_INSN_DISP16",   /* name */
107          FALSE,                 /* partial_inplace */
108          0xffff,                /* src_mask */
109          0xffff,                /* dst_mask */
110          TRUE),                 /* pcrel_offset */
111
112   HOWTO (R_BPF_DATA_8_PCREL,
113          0,                     /* rightshift */
114          0,                     /* size (0 = byte, 1 = short, 2 = long) */
115          8,                     /* bitsize */
116          TRUE,                  /* pc_relative */
117          0,                     /* bitpos */
118          complain_overflow_signed, /* complain_on_overflow */
119          bfd_elf_generic_reloc, /* special_function */
120          "R_BPF_8_PCREL",       /* name */
121          FALSE,                 /* partial_inplace */
122          0,                     /* src_mask */
123          0xff,                  /* dst_mask */
124          TRUE),                 /* pcrel_offset */
125
126   HOWTO (R_BPF_DATA_16_PCREL,
127          0,                     /* rightshift */
128          1,                     /* size (0 = byte, 1 = short, 2 = long) */
129          16,                    /* bitsize */
130          TRUE,                  /* pc_relative */
131          0,                     /* bitpos */
132          complain_overflow_signed, /* complain_on_overflow */
133          bfd_elf_generic_reloc, /* special_function */
134          "R_BPF_16_PCREL",      /* name */
135          FALSE,                 /* partial_inplace */
136          0,                     /* src_mask */
137          0xffff,                /* dst_mask */
138          TRUE),                 /* pcrel_offset */
139
140   HOWTO (R_BPF_DATA_32_PCREL,
141          0,                     /* rightshift */
142          2,                     /* size (0 = byte, 1 = short, 2 = long) */
143          32,                    /* bitsize */
144          TRUE,                  /* pc_relative */
145          0,                     /* bitpos */
146          complain_overflow_signed, /* complain_on_overflow */
147          bfd_elf_generic_reloc, /* special_function */
148          "R_BPF_32_PCREL",      /* name */
149          FALSE,                 /* partial_inplace */
150          0,                     /* src_mask */
151          0xffffffff,            /* dst_mask */
152          TRUE),                 /* pcrel_offset */
153
154   HOWTO (R_BPF_DATA_8,
155          0,                     /* rightshift */
156          0,                     /* size (0 = byte, 1 = short, 2 = long) */
157          8,                     /* bitsize */
158          FALSE,                 /* pc_relative */
159          0,                     /* bitpos */
160          complain_overflow_unsigned, /* complain_on_overflow */
161          bfd_elf_generic_reloc, /* special_function */
162          "R_BPF_DATA_8",        /* name */
163          FALSE,                 /* partial_inplace */
164          0,                     /* src_mask */
165          0xff,                  /* dst_mask */
166          FALSE),                /* pcrel_offset */
167
168   HOWTO (R_BPF_DATA_16,
169          0,                     /* rightshift */
170          1,                     /* size (0 = byte, 1 = short, 2 = long) */
171          16,                    /* bitsize */
172          FALSE,                 /* pc_relative */
173          0,                     /* bitpos */
174          complain_overflow_unsigned, /* complain_on_overflow */
175          bfd_elf_generic_reloc, /* special_function */
176          "R_BPF_DATA_16",       /* name */
177          FALSE,                 /* partial_inplace */
178          0,                     /* src_mask */
179          0xffff,                /* dst_mask */
180          FALSE),                /* pcrel_offset */
181
182   /* 32-bit PC-relative address in call instructions.  */
183   HOWTO (R_BPF_INSN_DISP32,     /* type */
184          0,                     /* rightshift */
185          2,                     /* size (0 = byte, 1 = short, 2 = long) */
186          32,                    /* bitsize */
187          TRUE,                  /* pc_relative */
188          0,                     /* bitpos */
189          complain_overflow_signed, /* complain_on_overflow */
190          bfd_elf_generic_reloc, /* special_function */
191          "R_BPF_INSN_DISP32",   /* name */
192          FALSE,                 /* partial_inplace */
193          0xffffffff,            /* src_mask */
194          0xffffffff,            /* dst_mask */
195          TRUE),                 /* pcrel_offset */
196
197   /* 32-bit data.  */
198   HOWTO (R_BPF_DATA_32,         /* type */
199          0,                     /* rightshift */
200          2,                     /* size (0 = byte, 1 = short, 2 = long) */
201          32,                    /* bitsize */
202          FALSE,                 /* pc_relative */
203          0,                     /* bitpos */
204          complain_overflow_bitfield, /* complain_on_overflow */
205          bfd_elf_generic_reloc, /* special_function */
206          "R_BPF_DATA_32",       /* name */
207          FALSE,                 /* partial_inplace */
208          0,                     /* src_mask */
209          0xffffffff,            /* dst_mask */
210          TRUE),                 /* pcrel_offset */
211
212   /* 64-bit data.  */
213   HOWTO (R_BPF_DATA_64,         /* type */
214          0,                     /* rightshift */
215          4,                     /* size (0 = byte, 1 = short, 2 = long) */
216          64,                    /* bitsize */
217          FALSE,                 /* pc_relative */
218          0,                     /* bitpos */
219          complain_overflow_bitfield, /* complain_on_overflow */
220          bfd_elf_generic_reloc, /* special_function */
221          "R_BPF_DATA_64",       /* name */
222          FALSE,                 /* partial_inplace */
223          0,                     /* src_mask */
224          MINUS_ONE,             /* dst_mask */
225          TRUE),                 /* pcrel_offset */
226
227   HOWTO (R_BPF_DATA_64_PCREL,
228          0,                     /* rightshift */
229          4,                     /* size (0 = byte, 1 = short, 2 = long) */
230          64,                    /* bitsize */
231          TRUE,                  /* pc_relative */
232          0,                     /* bitpos */
233          complain_overflow_signed, /* complain_on_overflow */
234          bfd_elf_generic_reloc, /* special_function */
235          "R_BPF_64_PCREL",      /* name */
236          FALSE,                 /* partial_inplace */
237          0,                     /* src_mask */
238          MINUS_ONE,             /* dst_mask */
239          TRUE),                 /* pcrel_offset */
240 };
241 #undef AHOW
242
243 /* Map BFD reloc types to bpf ELF reloc types.  */
244
245 static reloc_howto_type *
246 bpf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
247                         bfd_reloc_code_real_type code)
248 {
249   /* Note that the bpf_elf_howto_table is indexed by the R_ constants.
250      Thus, the order that the howto records appear in the table *must*
251      match the order of the relocation types defined in
252      include/elf/bpf.h.  */
253
254   switch (code)
255     {
256     case BFD_RELOC_NONE:
257       return &bpf_elf_howto_table[ (int) R_BPF_NONE];
258
259     case BFD_RELOC_8_PCREL:
260       return &bpf_elf_howto_table[ (int) R_BPF_DATA_8_PCREL];
261     case BFD_RELOC_16_PCREL:
262       return &bpf_elf_howto_table[ (int) R_BPF_DATA_16_PCREL];
263     case BFD_RELOC_32_PCREL:
264       return &bpf_elf_howto_table[ (int) R_BPF_DATA_32_PCREL];
265     case BFD_RELOC_64_PCREL:
266       return &bpf_elf_howto_table[ (int) R_BPF_DATA_64_PCREL];
267
268     case BFD_RELOC_8:
269       return &bpf_elf_howto_table[ (int) R_BPF_DATA_8];
270     case BFD_RELOC_16:
271       return &bpf_elf_howto_table[ (int) R_BPF_DATA_16];
272     case BFD_RELOC_32:
273       return &bpf_elf_howto_table[ (int) R_BPF_DATA_32];
274     case BFD_RELOC_64:
275       return &bpf_elf_howto_table[ (int) R_BPF_DATA_64];
276
277     case BFD_RELOC_BPF_64:
278       return &bpf_elf_howto_table[ (int) R_BPF_INSN_64];
279     case BFD_RELOC_BPF_32:
280       return &bpf_elf_howto_table[ (int) R_BPF_INSN_32];
281     case BFD_RELOC_BPF_16:
282       return &bpf_elf_howto_table[ (int) R_BPF_INSN_16];
283     case BFD_RELOC_BPF_DISP16:
284       return &bpf_elf_howto_table[ (int) R_BPF_INSN_DISP16];
285     case BFD_RELOC_BPF_DISP32:
286       return &bpf_elf_howto_table[ (int) R_BPF_INSN_DISP32];
287
288     default:
289       /* Pacify gcc -Wall.  */
290       return NULL;
291     }
292   return NULL;
293 }
294
295 /* Map BFD reloc names to bpf ELF reloc names.  */
296
297 static reloc_howto_type *
298 bpf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
299 {
300   unsigned int i;
301
302   for (i = 0; i < ARRAY_SIZE (bpf_elf_howto_table); i++)
303     if (bpf_elf_howto_table[i].name != NULL
304         && strcasecmp (bpf_elf_howto_table[i].name, r_name) == 0)
305       return &bpf_elf_howto_table[i];
306
307   return NULL;
308 }
309
310 /* Set the howto pointer for a bpf reloc.  */
311
312 static bfd_boolean
313 bpf_info_to_howto (bfd *abfd, arelent *bfd_reloc,
314                     Elf_Internal_Rela *elf_reloc)
315 {
316   unsigned int r_type;
317
318   r_type = ELF64_R_TYPE (elf_reloc->r_info);
319   if (r_type >= (unsigned int) R_BPF_max)
320     {
321       /* xgettext:c-format */
322       _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
323                           abfd, r_type);
324       bfd_set_error (bfd_error_bad_value);
325       return FALSE;
326     }
327
328   bfd_reloc->howto = &bpf_elf_howto_table [r_type];
329   return TRUE;
330 }
331
332 /* Relocate an eBPF ELF section.
333
334    The RELOCATE_SECTION function is called by the new ELF backend linker
335    to handle the relocations for a section.
336
337    The relocs are always passed as Rela structures; if the section
338    actually uses Rel structures, the r_addend field will always be
339    zero.
340
341    This function is responsible for adjusting the section contents as
342    necessary, and (if using Rela relocs and generating a relocatable
343    output file) adjusting the reloc addend as necessary.
344
345    This function does not have to worry about setting the reloc
346    address or the reloc symbol index.
347
348    LOCAL_SYMS is a pointer to the swapped in local symbols.
349
350    LOCAL_SECTIONS is an array giving the section in the input file
351    corresponding to the st_shndx field of each local symbol.
352
353    The global hash table entry for the global symbols can be found
354    via elf_sym_hashes (input_bfd).
355
356    When generating relocatable output, this function must handle
357    STB_LOCAL/STT_SECTION symbols specially.  The output symbol is
358    going to be the section symbol corresponding to the output
359    section, which means that the addend must be adjusted
360    accordingly.  */
361
362 #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
363
364 static bfd_boolean
365 bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
366                           struct bfd_link_info *info,
367                           bfd *input_bfd,
368                           asection *input_section,
369                           bfd_byte *contents,
370                           Elf_Internal_Rela *relocs,
371                           Elf_Internal_Sym *local_syms,
372                           asection **local_sections)
373 {
374   Elf_Internal_Shdr *symtab_hdr;
375   struct elf_link_hash_entry **sym_hashes;
376   Elf_Internal_Rela *rel;
377   Elf_Internal_Rela *relend;
378
379   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
380   sym_hashes = elf_sym_hashes (input_bfd);
381   relend     = relocs + input_section->reloc_count;
382
383   for (rel = relocs; rel < relend; rel ++)
384     {
385       reloc_howto_type *           howto;
386       unsigned long                r_symndx;
387       Elf_Internal_Sym *           sym;
388       asection *                   sec;
389       struct elf_link_hash_entry * h;
390       bfd_vma                      relocation;
391       bfd_reloc_status_type        r;
392       const char *                 name = NULL;
393       int                          r_type ATTRIBUTE_UNUSED;
394
395       r_type = ELF64_R_TYPE (rel->r_info);
396       r_symndx = ELF64_R_SYM (rel->r_info);
397       howto  = bpf_elf_howto_table + ELF64_R_TYPE (rel->r_info);
398       h      = NULL;
399       sym    = NULL;
400       sec    = NULL;
401
402       if (r_symndx < symtab_hdr->sh_info)
403         {
404           sym = local_syms + r_symndx;
405           sec = local_sections [r_symndx];
406           relocation = BASEADDR (sec) + sym->st_value;
407
408           name = bfd_elf_string_from_elf_section
409             (input_bfd, symtab_hdr->sh_link, sym->st_name);
410           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
411         }
412       else
413         {
414           bfd_boolean warned ATTRIBUTE_UNUSED;
415           bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED;
416           bfd_boolean ignored ATTRIBUTE_UNUSED;
417
418           RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
419                                    r_symndx, symtab_hdr, sym_hashes,
420                                    h, sec, relocation,
421                                    unresolved_reloc, warned, ignored);
422
423           name = h->root.root.string;
424         }
425
426       if (sec != NULL && discarded_section (sec))
427         RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
428                                          rel, 1, relend, howto, 0, contents);
429
430       if (bfd_link_relocatable (info))
431         continue;
432
433       switch (howto->type)
434         {
435         case R_BPF_INSN_DISP16:
436         case R_BPF_INSN_DISP32:
437           {
438             bfd_signed_vma addend;
439             
440             /* Make the relocation PC-relative, and change its unit to
441                64-bit words.  */
442             relocation -= sec_addr (input_section) + rel->r_offset;
443             /* Make it 64-bit words.  */
444             relocation = relocation / 8;
445             
446             /* Get the addend from the instruction and apply it.  */
447             addend = bfd_get (howto->bitsize, input_bfd,
448                               contents + rel->r_offset
449                               + (howto->bitsize == 16 ? 2 : 4));
450                               
451             if ((addend & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
452               addend -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
453             relocation += addend;
454
455             /* Write out the relocated value.  */
456             bfd_put (howto->bitsize, input_bfd, relocation,
457                      contents + rel->r_offset
458                      + (howto->bitsize == 16 ? 2 : 4));
459
460             r = bfd_reloc_ok;
461             break;
462           }
463         default:
464           r = _bfd_final_link_relocate (howto, input_bfd, input_section,
465                                         contents, rel->r_offset, relocation,
466                                         rel->r_addend);
467         }
468
469       if (r != bfd_reloc_ok)
470         {
471           const char * msg = NULL;
472
473           switch (r)
474             {
475             case bfd_reloc_overflow:
476               (*info->callbacks->reloc_overflow)
477                 (info, (h ? &h->root : NULL), name, howto->name,
478                  (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
479               break;
480
481             case bfd_reloc_undefined:
482               (*info->callbacks->undefined_symbol)
483                 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
484               break;
485
486             case bfd_reloc_outofrange:
487               msg = _("internal error: out of range error");
488               break;
489
490             case bfd_reloc_notsupported:
491               if (sym != NULL) /* Only if it's not an unresolved symbol.  */
492                 msg = _("internal error: relocation not supported");
493               break;
494
495             case bfd_reloc_dangerous:
496               msg = _("internal error: dangerous relocation");
497               break;
498
499             default:
500               msg = _("internal error: unknown error");
501               break;
502             }
503
504           if (msg)
505             (*info->callbacks->warning) (info, msg, name, input_bfd,
506                                          input_section, rel->r_offset);
507         }
508     }
509
510   return TRUE;
511 }
512
513 /* Merge backend specific data from an object file to the output
514    object file when linking.  */
515
516 static bfd_boolean
517 elf64_bpf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
518 {
519   /* Check if we have the same endianness.  */
520   if (! _bfd_generic_verify_endian_match (ibfd, info))
521     return FALSE;
522
523   return TRUE;
524 }
525
526 /* The macros below configure the architecture.  */
527
528 #define TARGET_LITTLE_SYM bpf_elf64_le_vec
529 #define TARGET_LITTLE_NAME "elf64-bpfle"
530
531 #define TARGET_BIG_SYM bpf_elf64_be_vec
532 #define TARGET_BIG_NAME "elf64-bpfbe"
533
534 #define ELF_ARCH bfd_arch_bpf
535 #define ELF_MACHINE_CODE EM_BPF
536
537 #define ELF_MAXPAGESIZE 0x100000
538
539 #define elf_info_to_howto_rel bpf_info_to_howto
540 #define elf_info_to_howto bpf_info_to_howto
541
542 #define elf_backend_may_use_rel_p               1
543 #define elf_backend_may_use_rela_p              0
544 #define elf_backend_default_use_rela_p          0
545 #define elf_backend_relocate_section            bpf_elf_relocate_section
546
547 #define elf_backend_can_gc_sections             0
548
549 #define elf_symbol_leading_char                 '_'
550 #define bfd_elf64_bfd_reloc_type_lookup         bpf_reloc_type_lookup
551 #define bfd_elf64_bfd_reloc_name_lookup         bpf_reloc_name_lookup
552
553 #define bfd_elf64_bfd_merge_private_bfd_data elf64_bpf_merge_private_bfd_data
554
555 #include "elf64-target.h"