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