gdbserver: make thread_info non-POD
[deliverable/binutils-gdb.git] / bfd / elf64-bpf.c
CommitLineData
fd0de36e 1/* Linux bpf specific support for 64-bit ELF
250d07de 2 Copyright (C) 2019-2021 Free Software Foundation, Inc.
fd0de36e
JM
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
3ee9565c
DF
34static bfd_reloc_status_type bpf_elf_generic_reloc
35 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
36
fd0de36e
JM
37/* Relocation tables. */
38static 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 */
0a1b45a2 45 false, /* pc_relative */
fd0de36e
JM
46 0, /* bitpos */
47 complain_overflow_dont, /* complain_on_overflow */
3ee9565c 48 bpf_elf_generic_reloc, /* special_function */
fd0de36e 49 "R_BPF_NONE", /* name */
0a1b45a2 50 false, /* partial_inplace */
fd0de36e
JM
51 0, /* src_mask */
52 0, /* dst_mask */
0a1b45a2 53 false), /* pcrel_offset */
fd0de36e
JM
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 */
0a1b45a2 60 false, /* pc_relative */
3ee9565c 61 32, /* bitpos */
fd0de36e 62 complain_overflow_signed, /* complain_on_overflow */
3ee9565c 63 bpf_elf_generic_reloc, /* special_function */
fd0de36e 64 "R_BPF_INSN_64", /* name */
0a1b45a2 65 true, /* partial_inplace */
3ee9565c 66 MINUS_ONE, /* src_mask */
fd0de36e 67 MINUS_ONE, /* dst_mask */
0a1b45a2 68 true), /* pcrel_offset */
fd0de36e 69
3ee9565c 70 /* 32-immediate in many instructions. */
fd0de36e
JM
71 HOWTO (R_BPF_INSN_32, /* type */
72 0, /* rightshift */
73 2, /* size (0 = byte, 1 = short, 2 = long) */
74 32, /* bitsize */
0a1b45a2 75 false, /* pc_relative */
3ee9565c 76 32, /* bitpos */
fd0de36e 77 complain_overflow_signed, /* complain_on_overflow */
3ee9565c 78 bpf_elf_generic_reloc, /* special_function */
fd0de36e 79 "R_BPF_INSN_32", /* name */
0a1b45a2 80 true, /* partial_inplace */
3ee9565c 81 0xffffffff, /* src_mask */
fd0de36e 82 0xffffffff, /* dst_mask */
0a1b45a2 83 true), /* pcrel_offset */
fd0de36e
JM
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 */
0a1b45a2 90 false, /* pc_relative */
3ee9565c 91 16, /* bitpos */
fd0de36e 92 complain_overflow_signed, /* complain_on_overflow */
3ee9565c 93 bpf_elf_generic_reloc, /* special_function */
fd0de36e 94 "R_BPF_INSN_16", /* name */
0a1b45a2 95 true, /* partial_inplace */
3ee9565c 96 0x0000ffff, /* src_mask */
fd0de36e 97 0x0000ffff, /* dst_mask */
0a1b45a2 98 true), /* pcrel_offset */
fd0de36e
JM
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 */
0a1b45a2 105 true, /* pc_relative */
3ee9565c 106 16, /* bitpos */
fd0de36e 107 complain_overflow_signed, /* complain_on_overflow */
3ee9565c 108 bpf_elf_generic_reloc, /* special_function */
fd0de36e 109 "R_BPF_INSN_DISP16", /* name */
0a1b45a2 110 true, /* partial_inplace */
fd0de36e
JM
111 0xffff, /* src_mask */
112 0xffff, /* dst_mask */
0a1b45a2 113 true), /* pcrel_offset */
fd0de36e
JM
114
115 HOWTO (R_BPF_DATA_8_PCREL,
116 0, /* rightshift */
117 0, /* size (0 = byte, 1 = short, 2 = long) */
118 8, /* bitsize */
0a1b45a2 119 true, /* pc_relative */
fd0de36e
JM
120 0, /* bitpos */
121 complain_overflow_signed, /* complain_on_overflow */
3ee9565c 122 bpf_elf_generic_reloc, /* special_function */
fd0de36e 123 "R_BPF_8_PCREL", /* name */
0a1b45a2 124 true, /* partial_inplace */
3ee9565c 125 0xff, /* src_mask */
fd0de36e 126 0xff, /* dst_mask */
0a1b45a2 127 true), /* pcrel_offset */
fd0de36e
JM
128
129 HOWTO (R_BPF_DATA_16_PCREL,
130 0, /* rightshift */
131 1, /* size (0 = byte, 1 = short, 2 = long) */
132 16, /* bitsize */
0a1b45a2 133 true, /* pc_relative */
fd0de36e
JM
134 0, /* bitpos */
135 complain_overflow_signed, /* complain_on_overflow */
3ee9565c 136 bpf_elf_generic_reloc, /* special_function */
fd0de36e 137 "R_BPF_16_PCREL", /* name */
0a1b45a2 138 false, /* partial_inplace */
3ee9565c 139 0xffff, /* src_mask */
fd0de36e 140 0xffff, /* dst_mask */
0a1b45a2 141 true), /* pcrel_offset */
fd0de36e
JM
142
143 HOWTO (R_BPF_DATA_32_PCREL,
144 0, /* rightshift */
145 2, /* size (0 = byte, 1 = short, 2 = long) */
146 32, /* bitsize */
0a1b45a2 147 true, /* pc_relative */
fd0de36e
JM
148 0, /* bitpos */
149 complain_overflow_signed, /* complain_on_overflow */
3ee9565c 150 bpf_elf_generic_reloc, /* special_function */
fd0de36e 151 "R_BPF_32_PCREL", /* name */
0a1b45a2 152 false, /* partial_inplace */
3ee9565c 153 0xffffffff, /* src_mask */
fd0de36e 154 0xffffffff, /* dst_mask */
0a1b45a2 155 true), /* pcrel_offset */
fd0de36e
JM
156
157 HOWTO (R_BPF_DATA_8,
158 0, /* rightshift */
159 0, /* size (0 = byte, 1 = short, 2 = long) */
160 8, /* bitsize */
0a1b45a2 161 false, /* pc_relative */
fd0de36e
JM
162 0, /* bitpos */
163 complain_overflow_unsigned, /* complain_on_overflow */
3ee9565c 164 bpf_elf_generic_reloc, /* special_function */
fd0de36e 165 "R_BPF_DATA_8", /* name */
0a1b45a2 166 true, /* partial_inplace */
3ee9565c 167 0xff, /* src_mask */
fd0de36e 168 0xff, /* dst_mask */
0a1b45a2 169 false), /* pcrel_offset */
fd0de36e
JM
170
171 HOWTO (R_BPF_DATA_16,
172 0, /* rightshift */
173 1, /* size (0 = byte, 1 = short, 2 = long) */
174 16, /* bitsize */
0a1b45a2 175 false, /* pc_relative */
fd0de36e
JM
176 0, /* bitpos */
177 complain_overflow_unsigned, /* complain_on_overflow */
3ee9565c 178 bpf_elf_generic_reloc, /* special_function */
fd0de36e 179 "R_BPF_DATA_16", /* name */
0a1b45a2 180 false, /* partial_inplace */
3ee9565c 181 0xffff, /* src_mask */
fd0de36e 182 0xffff, /* dst_mask */
0a1b45a2 183 false), /* pcrel_offset */
fd0de36e
JM
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 */
0a1b45a2 190 true, /* pc_relative */
3ee9565c 191 32, /* bitpos */
fd0de36e 192 complain_overflow_signed, /* complain_on_overflow */
3ee9565c 193 bpf_elf_generic_reloc, /* special_function */
fd0de36e 194 "R_BPF_INSN_DISP32", /* name */
0a1b45a2 195 true, /* partial_inplace */
fd0de36e
JM
196 0xffffffff, /* src_mask */
197 0xffffffff, /* dst_mask */
0a1b45a2 198 true), /* pcrel_offset */
fd0de36e
JM
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 */
0a1b45a2 205 false, /* pc_relative */
fd0de36e
JM
206 0, /* bitpos */
207 complain_overflow_bitfield, /* complain_on_overflow */
3ee9565c 208 bpf_elf_generic_reloc, /* special_function */
fd0de36e 209 "R_BPF_DATA_32", /* name */
0a1b45a2 210 false, /* partial_inplace */
3ee9565c 211 0xffffffff, /* src_mask */
fd0de36e 212 0xffffffff, /* dst_mask */
0a1b45a2 213 true), /* pcrel_offset */
fd0de36e
JM
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 */
0a1b45a2 220 false, /* pc_relative */
fd0de36e
JM
221 0, /* bitpos */
222 complain_overflow_bitfield, /* complain_on_overflow */
3ee9565c 223 bpf_elf_generic_reloc, /* special_function */
fd0de36e 224 "R_BPF_DATA_64", /* name */
0a1b45a2 225 false, /* partial_inplace */
fd0de36e
JM
226 0, /* src_mask */
227 MINUS_ONE, /* dst_mask */
0a1b45a2 228 true), /* pcrel_offset */
fd0de36e
JM
229
230 HOWTO (R_BPF_DATA_64_PCREL,
231 0, /* rightshift */
232 4, /* size (0 = byte, 1 = short, 2 = long) */
233 64, /* bitsize */
0a1b45a2 234 true, /* pc_relative */
fd0de36e
JM
235 0, /* bitpos */
236 complain_overflow_signed, /* complain_on_overflow */
3ee9565c 237 bpf_elf_generic_reloc, /* special_function */
fd0de36e 238 "R_BPF_64_PCREL", /* name */
0a1b45a2 239 false, /* partial_inplace */
3ee9565c 240 MINUS_ONE, /* src_mask */
fd0de36e 241 MINUS_ONE, /* dst_mask */
0a1b45a2 242 true), /* pcrel_offset */
fd0de36e
JM
243};
244#undef AHOW
245
246/* Map BFD reloc types to bpf ELF reloc types. */
247
248static reloc_howto_type *
249bpf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
250 bfd_reloc_code_real_type code)
251{
fc8de8e2
JM
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
fd0de36e
JM
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
300static reloc_howto_type *
301bpf_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
0a1b45a2 315static bool
fd0de36e
JM
316bpf_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);
0a1b45a2 328 return false;
fd0de36e
JM
329 }
330
331 bfd_reloc->howto = &bpf_elf_howto_table [r_type];
0a1b45a2 332 return true;
fd0de36e
JM
333}
334
fc8de8e2
JM
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
0f684201 367static int
fc8de8e2
JM
368bpf_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;
3ee9565c
DF
397 bfd_signed_vma addend;
398 bfd_byte * where;
fc8de8e2
JM
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;
3ee9565c 406 where = contents + rel->r_offset;
fc8de8e2
JM
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);
fd361982 416 name = name == NULL ? bfd_section_name (sec) : name;
fc8de8e2
JM
417 }
418 else
419 {
0a1b45a2
AM
420 bool warned ATTRIBUTE_UNUSED;
421 bool unresolved_reloc ATTRIBUTE_UNUSED;
422 bool ignored ATTRIBUTE_UNUSED;
fc8de8e2
JM
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 {
fc8de8e2 444 /* Make the relocation PC-relative, and change its unit to
d844f10a
DF
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;
fc8de8e2
JM
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 }
3ee9565c
DF
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 }
12adf805
DF
490 case R_BPF_INSN_32:
491 {
492 /* Write relocated value */
3ee9565c
DF
493
494 addend = bfd_get_32 (input_bfd, where + 4);
495 relocation += addend;
496 bfd_put_32 (input_bfd, relocation, where + 4);
12adf805
DF
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 */
3ee9565c
DF
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);
12adf805
DF
521 r = bfd_reloc_ok;
522 break;
523 }
fc8de8e2 524 default:
3ee9565c 525 r = bfd_reloc_notsupported;
fc8de8e2
JM
526 }
527
3ee9565c
DF
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
fc8de8e2
JM
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)
0a1b45a2 548 (info, name, input_bfd, input_section, rel->r_offset, true);
fc8de8e2
JM
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
0a1b45a2 575 return true;
fc8de8e2
JM
576}
577
fd0de36e
JM
578/* Merge backend specific data from an object file to the output
579 object file when linking. */
580
0a1b45a2 581static bool
fd0de36e
JM
582elf64_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))
0a1b45a2 586 return false;
fd0de36e 587
0a1b45a2 588 return true;
fd0de36e
JM
589}
590
3ee9565c
DF
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
598static bfd_reloc_status_type
599bpf_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
fd0de36e
JM
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
fc8de8e2 681#define elf_backend_relocate_section bpf_elf_relocate_section
fd0de36e
JM
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"
This page took 0.244374 seconds and 4 git commands to generate.