1 /* Linux bpf specific support for 64-bit ELF
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
3 Contributed by Oracle Inc.
5 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
27 #include "libiberty.h"
29 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */
30 #define MINUS_ONE (~ (bfd_vma) 0)
32 #define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset)
34 static bfd_reloc_status_type bpf_elf_generic_reloc
35 (bfd
*, arelent
*, asymbol
*, void *, asection
*, bfd
*, char **);
38 #define BPF_HOWTO(type, right, size, bits, pcrel, left, ovf, func, name, \
39 inplace, src_mask, dst_mask, pcrel_off) \
41 enum bpf_reloc_index
{
42 R_BPF_INVALID_IDX
= -1,
43 #include "bpf-reloc.def"
48 /* Relocation tables. */
49 #define BPF_HOWTO(...) HOWTO(__VA_ARGS__),
50 static reloc_howto_type bpf_elf_howto_table
[] =
52 #include "bpf-reloc.def"
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; }
60 static enum bpf_reloc_index
61 bpf_index_for_rtype(unsigned int r_type
)
64 #include "bpf-reloc.def"
66 /* Unreachable code. */
72 /* Map BFD reloc types to bpf ELF reloc types. */
74 static reloc_howto_type
*
75 bpf_reloc_type_lookup (bfd
* abfd ATTRIBUTE_UNUSED
,
76 bfd_reloc_code_real_type code
)
81 return &bpf_elf_howto_table
[ (int) R_BPF_NONE_IDX
];
84 return &bpf_elf_howto_table
[ (int) R_BPF_64_ABS32_IDX
];
86 return &bpf_elf_howto_table
[ (int) R_BPF_64_ABS64_IDX
];
88 case BFD_RELOC_BPF_64
:
89 return &bpf_elf_howto_table
[ (int) R_BPF_64_64_IDX
];
90 case BFD_RELOC_BPF_DISP32
:
91 return &bpf_elf_howto_table
[ (int) R_BPF_64_32_IDX
];
94 /* Pacify gcc -Wall. */
100 /* Map BFD reloc names to bpf ELF reloc names. */
102 static reloc_howto_type
*
103 bpf_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
107 for (i
= 0; i
< R_BPF_SIZE
; i
++)
108 if (bpf_elf_howto_table
[i
].name
!= NULL
109 && strcasecmp (bpf_elf_howto_table
[i
].name
, r_name
) == 0)
110 return &bpf_elf_howto_table
[i
];
115 /* Set the howto pointer for a bpf reloc. */
118 bpf_info_to_howto (bfd
*abfd
, arelent
*bfd_reloc
,
119 Elf_Internal_Rela
*elf_reloc
)
123 r_type
= ELF64_R_TYPE (elf_reloc
->r_info
);
125 i
= bpf_index_for_rtype(r_type
);
126 if (i
== (unsigned int) -1)
128 /* xgettext:c-format */
129 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
131 bfd_set_error (bfd_error_bad_value
);
135 bfd_reloc
->howto
= &bpf_elf_howto_table
[i
];
139 /* Relocate an eBPF ELF section.
141 The RELOCATE_SECTION function is called by the new ELF backend linker
142 to handle the relocations for a section.
144 The relocs are always passed as Rela structures; if the section
145 actually uses Rel structures, the r_addend field will always be
148 This function is responsible for adjusting the section contents as
149 necessary, and (if using Rela relocs and generating a relocatable
150 output file) adjusting the reloc addend as necessary.
152 This function does not have to worry about setting the reloc
153 address or the reloc symbol index.
155 LOCAL_SYMS is a pointer to the swapped in local symbols.
157 LOCAL_SECTIONS is an array giving the section in the input file
158 corresponding to the st_shndx field of each local symbol.
160 The global hash table entry for the global symbols can be found
161 via elf_sym_hashes (input_bfd).
163 When generating relocatable output, this function must handle
164 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
165 going to be the section symbol corresponding to the output
166 section, which means that the addend must be adjusted
169 #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
172 bpf_elf_relocate_section (bfd
*output_bfd ATTRIBUTE_UNUSED
,
173 struct bfd_link_info
*info
,
175 asection
*input_section
,
177 Elf_Internal_Rela
*relocs
,
178 Elf_Internal_Sym
*local_syms
,
179 asection
**local_sections
)
181 Elf_Internal_Shdr
*symtab_hdr
;
182 struct elf_link_hash_entry
**sym_hashes
;
183 Elf_Internal_Rela
*rel
;
184 Elf_Internal_Rela
*relend
;
186 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
187 sym_hashes
= elf_sym_hashes (input_bfd
);
188 relend
= relocs
+ input_section
->reloc_count
;
190 for (rel
= relocs
; rel
< relend
; rel
++)
192 reloc_howto_type
* howto
;
193 unsigned int howto_index
;
194 unsigned long r_symndx
;
195 Elf_Internal_Sym
* sym
;
197 struct elf_link_hash_entry
* h
;
199 bfd_reloc_status_type r
;
200 const char * name
= NULL
;
201 int r_type ATTRIBUTE_UNUSED
;
202 bfd_signed_vma addend
;
205 r_type
= ELF64_R_TYPE (rel
->r_info
);
206 r_symndx
= ELF64_R_SYM (rel
->r_info
);
208 howto_index
= bpf_index_for_rtype (ELF64_R_TYPE (rel
->r_info
));
209 howto
= &bpf_elf_howto_table
[howto_index
];
213 where
= contents
+ rel
->r_offset
;
215 if (r_symndx
< symtab_hdr
->sh_info
)
217 sym
= local_syms
+ r_symndx
;
218 sec
= local_sections
[r_symndx
];
219 relocation
= BASEADDR (sec
) + sym
->st_value
;
221 name
= bfd_elf_string_from_elf_section
222 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
223 name
= name
== NULL
? bfd_section_name (sec
) : name
;
227 bool warned ATTRIBUTE_UNUSED
;
228 bool unresolved_reloc ATTRIBUTE_UNUSED
;
229 bool ignored ATTRIBUTE_UNUSED
;
231 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
232 r_symndx
, symtab_hdr
, sym_hashes
,
234 unresolved_reloc
, warned
, ignored
);
236 name
= h
->root
.root
.string
;
239 if (sec
!= NULL
&& discarded_section (sec
))
240 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
241 rel
, 1, relend
, howto
, 0, contents
);
243 if (bfd_link_relocatable (info
))
250 /* Make the relocation PC-relative, and change its unit to
251 64-bit words. Note we need *signed* arithmetic
253 relocation
= ((bfd_signed_vma
) relocation
254 - (sec_addr (input_section
) + rel
->r_offset
));
255 relocation
= (bfd_signed_vma
) relocation
/ 8;
257 /* Get the addend from the instruction and apply it. */
258 addend
= bfd_get (howto
->bitsize
, input_bfd
,
259 contents
+ rel
->r_offset
260 + (howto
->bitsize
== 16 ? 2 : 4));
262 if ((addend
& (((~howto
->src_mask
) >> 1) & howto
->src_mask
)) != 0)
263 addend
-= (((~howto
->src_mask
) >> 1) & howto
->src_mask
) << 1;
264 relocation
+= addend
;
266 /* Write out the relocated value. */
267 bfd_put (howto
->bitsize
, input_bfd
, relocation
,
268 contents
+ rel
->r_offset
269 + (howto
->bitsize
== 16 ? 2 : 4));
277 addend
= bfd_get (howto
->bitsize
, input_bfd
, where
);
278 relocation
+= addend
;
279 bfd_put (howto
->bitsize
, input_bfd
, relocation
, where
);
287 LDDW instructions are 128 bits long, with a 64-bit immediate.
288 The lower 32 bits of the immediate are in the same position
289 as the imm32 field of other instructions.
290 The upper 32 bits of the immediate are stored at the end of
295 /* Get the addend. The upper and lower 32 bits are split.
296 'where' is the beginning of the 16-byte instruction. */
297 addend
= bfd_get_32 (input_bfd
, where
+ 4);
298 addend
|= (bfd_get_32 (input_bfd
, where
+ 12) << 32);
300 relocation
+= addend
;
302 bfd_put_32 (input_bfd
, (relocation
& 0xFFFFFFFF), where
+ 4);
303 bfd_put_32 (input_bfd
, (relocation
>> 32), where
+ 12);
308 r
= bfd_reloc_notsupported
;
311 if (r
== bfd_reloc_ok
)
312 r
= bfd_check_overflow (howto
->complain_on_overflow
,
317 if (r
!= bfd_reloc_ok
)
319 const char * msg
= NULL
;
323 case bfd_reloc_overflow
:
324 (*info
->callbacks
->reloc_overflow
)
325 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
326 (bfd_vma
) 0, input_bfd
, input_section
, rel
->r_offset
);
329 case bfd_reloc_undefined
:
330 (*info
->callbacks
->undefined_symbol
)
331 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, true);
334 case bfd_reloc_outofrange
:
335 msg
= _("internal error: out of range error");
338 case bfd_reloc_notsupported
:
339 if (sym
!= NULL
) /* Only if it's not an unresolved symbol. */
340 msg
= _("internal error: relocation not supported");
343 case bfd_reloc_dangerous
:
344 msg
= _("internal error: dangerous relocation");
348 msg
= _("internal error: unknown error");
353 (*info
->callbacks
->warning
) (info
, msg
, name
, input_bfd
,
354 input_section
, rel
->r_offset
);
361 /* Merge backend specific data from an object file to the output
362 object file when linking. */
365 elf64_bpf_merge_private_bfd_data (bfd
*ibfd
, struct bfd_link_info
*info
)
367 /* Check if we have the same endianness. */
368 if (! _bfd_generic_verify_endian_match (ibfd
, info
))
374 /* A generic howto special function for installing BPF relocations.
375 This function will be called by the assembler (via bfd_install_relocation),
376 and by various get_relocated_section_contents functions.
377 At link time, bpf_elf_relocate_section will resolve the final relocations.
379 BPF instructions are always big endian, and this approach avoids problems in
380 bfd_install_relocation. */
382 static bfd_reloc_status_type
383 bpf_elf_generic_reloc (bfd
*abfd
, arelent
*reloc_entry
, asymbol
*symbol
,
384 void *data
, asection
*input_section
,
385 bfd
*output_bfd ATTRIBUTE_UNUSED
,
386 char **error_message ATTRIBUTE_UNUSED
)
389 bfd_signed_vma relocation
;
390 bfd_reloc_status_type status
;
393 /* Sanity check that the address is in range. */
394 bfd_size_type end
= bfd_get_section_limit_octets (abfd
, input_section
);
395 bfd_size_type reloc_size
;
396 if (reloc_entry
->howto
->type
== R_BPF_64_64
)
399 reloc_size
= (reloc_entry
->howto
->bitsize
400 + reloc_entry
->howto
->bitpos
) / 8;
402 if (reloc_entry
->address
> end
403 || end
- reloc_entry
->address
< reloc_size
)
404 return bfd_reloc_outofrange
;
406 /* Get the symbol value. */
407 if (bfd_is_com_section (symbol
->section
))
410 relocation
= symbol
->value
;
412 if (symbol
->flags
& BSF_SECTION_SYM
)
413 /* Relocation against a section symbol: add in the section base address. */
414 relocation
+= BASEADDR (symbol
->section
);
416 relocation
+= reloc_entry
->addend
;
418 where
= (bfd_byte
*) data
+ reloc_entry
->address
;
420 status
= bfd_check_overflow (reloc_entry
->howto
->complain_on_overflow
,
421 reloc_entry
->howto
->bitsize
,
422 reloc_entry
->howto
->rightshift
, 64, relocation
);
424 if (status
!= bfd_reloc_ok
)
427 /* Now finally install the relocation. */
428 if (reloc_entry
->howto
->type
== R_BPF_64_64
)
430 /* lddw is a 128-bit (!) instruction that allows loading a 64-bit
431 immediate into a register. the immediate is split in half, with the
432 lower 32 bits in the same position as the imm32 field of other
433 instructions, and the upper 32 bits placed at the very end of the
434 instruction. that is, there are 32 unused bits between them. */
436 bfd_put_32 (abfd
, (relocation
& 0xFFFFFFFF), where
+ 4);
437 bfd_put_32 (abfd
, (relocation
>> 32), where
+ 12);
441 /* For other kinds of relocations, the relocated value simply goes
442 BITPOS bits from the start of the entry. This is always a multiple
443 of 8, i.e. whole bytes. */
444 bfd_put (reloc_entry
->howto
->bitsize
, abfd
, relocation
,
445 where
+ reloc_entry
->howto
->bitpos
/ 8);
448 reloc_entry
->addend
= relocation
;
449 reloc_entry
->address
+= input_section
->output_offset
;
455 /* The macros below configure the architecture. */
457 #define TARGET_LITTLE_SYM bpf_elf64_le_vec
458 #define TARGET_LITTLE_NAME "elf64-bpfle"
460 #define TARGET_BIG_SYM bpf_elf64_be_vec
461 #define TARGET_BIG_NAME "elf64-bpfbe"
463 #define ELF_ARCH bfd_arch_bpf
464 #define ELF_MACHINE_CODE EM_BPF
466 #define ELF_MAXPAGESIZE 0x100000
468 #define elf_info_to_howto_rel bpf_info_to_howto
469 #define elf_info_to_howto bpf_info_to_howto
471 #define elf_backend_may_use_rel_p 1
472 #define elf_backend_may_use_rela_p 0
473 #define elf_backend_default_use_rela_p 0
474 #define elf_backend_relocate_section bpf_elf_relocate_section
476 #define elf_backend_can_gc_sections 0
478 #define elf_symbol_leading_char '_'
479 #define bfd_elf64_bfd_reloc_type_lookup bpf_reloc_type_lookup
480 #define bfd_elf64_bfd_reloc_name_lookup bpf_reloc_name_lookup
482 #define bfd_elf64_bfd_merge_private_bfd_data elf64_bpf_merge_private_bfd_data
484 #include "elf64-target.h"