PR23652, Use symbols from debug bfd for _bfd_elf_find_function
[deliverable/binutils-gdb.git] / bfd / elf64-bpf.c
CommitLineData
fd0de36e
JM
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
fd0de36e
JM
34/* Relocation tables. */
35static 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 */
fc8de8e2 105 bfd_elf_generic_reloc, /* special_function */
fd0de36e
JM
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 */
fc8de8e2 190 bfd_elf_generic_reloc, /* special_function */
fd0de36e
JM
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
245static reloc_howto_type *
246bpf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
247 bfd_reloc_code_real_type code)
248{
fc8de8e2
JM
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
fd0de36e
JM
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
297static reloc_howto_type *
298bpf_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
312static bfd_boolean
313bpf_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
fc8de8e2
JM
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
364static bfd_boolean
365bpf_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);
fd361982 410 name = name == NULL ? bfd_section_name (sec) : name;
fc8de8e2
JM
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
fd0de36e
JM
513/* Merge backend specific data from an object file to the output
514 object file when linking. */
515
516static bfd_boolean
517elf64_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
fc8de8e2 545#define elf_backend_relocate_section bpf_elf_relocate_section
fd0de36e
JM
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"
This page took 0.08234 seconds and 4 git commands to generate.