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
];
92 case BFD_RELOC_BPF_DISP16
:
93 return &bpf_elf_howto_table
[ (int) R_BPF_GNU_64_16_IDX
];
96 /* Pacify gcc -Wall. */
102 /* Map BFD reloc names to bpf ELF reloc names. */
104 static reloc_howto_type
*
105 bpf_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
109 for (i
= 0; i
< R_BPF_SIZE
; i
++)
110 if (bpf_elf_howto_table
[i
].name
!= NULL
111 && strcasecmp (bpf_elf_howto_table
[i
].name
, r_name
) == 0)
112 return &bpf_elf_howto_table
[i
];
117 /* Set the howto pointer for a bpf reloc. */
120 bpf_info_to_howto (bfd
*abfd
, arelent
*bfd_reloc
,
121 Elf_Internal_Rela
*elf_reloc
)
125 r_type
= ELF64_R_TYPE (elf_reloc
->r_info
);
127 i
= bpf_index_for_rtype(r_type
);
128 if (i
== (unsigned int) -1)
130 /* xgettext:c-format */
131 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
133 bfd_set_error (bfd_error_bad_value
);
137 bfd_reloc
->howto
= &bpf_elf_howto_table
[i
];
141 /* Relocate an eBPF ELF section.
143 The RELOCATE_SECTION function is called by the new ELF backend linker
144 to handle the relocations for a section.
146 The relocs are always passed as Rela structures; if the section
147 actually uses Rel structures, the r_addend field will always be
150 This function is responsible for adjusting the section contents as
151 necessary, and (if using Rela relocs and generating a relocatable
152 output file) adjusting the reloc addend as necessary.
154 This function does not have to worry about setting the reloc
155 address or the reloc symbol index.
157 LOCAL_SYMS is a pointer to the swapped in local symbols.
159 LOCAL_SECTIONS is an array giving the section in the input file
160 corresponding to the st_shndx field of each local symbol.
162 The global hash table entry for the global symbols can be found
163 via elf_sym_hashes (input_bfd).
165 When generating relocatable output, this function must handle
166 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
167 going to be the section symbol corresponding to the output
168 section, which means that the addend must be adjusted
171 #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
174 bpf_elf_relocate_section (bfd
*output_bfd ATTRIBUTE_UNUSED
,
175 struct bfd_link_info
*info
,
177 asection
*input_section
,
179 Elf_Internal_Rela
*relocs
,
180 Elf_Internal_Sym
*local_syms
,
181 asection
**local_sections
)
183 Elf_Internal_Shdr
*symtab_hdr
;
184 struct elf_link_hash_entry
**sym_hashes
;
185 Elf_Internal_Rela
*rel
;
186 Elf_Internal_Rela
*relend
;
188 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
189 sym_hashes
= elf_sym_hashes (input_bfd
);
190 relend
= relocs
+ input_section
->reloc_count
;
192 for (rel
= relocs
; rel
< relend
; rel
++)
194 reloc_howto_type
* howto
;
195 unsigned int howto_index
;
196 unsigned long r_symndx
;
197 Elf_Internal_Sym
* sym
;
199 struct elf_link_hash_entry
* h
;
201 bfd_reloc_status_type r
;
202 const char * name
= NULL
;
203 int r_type ATTRIBUTE_UNUSED
;
204 bfd_signed_vma addend
;
207 r_type
= ELF64_R_TYPE (rel
->r_info
);
208 r_symndx
= ELF64_R_SYM (rel
->r_info
);
210 howto_index
= bpf_index_for_rtype (ELF64_R_TYPE (rel
->r_info
));
211 howto
= &bpf_elf_howto_table
[howto_index
];
215 where
= contents
+ rel
->r_offset
;
217 if (r_symndx
< symtab_hdr
->sh_info
)
219 sym
= local_syms
+ r_symndx
;
220 sec
= local_sections
[r_symndx
];
221 relocation
= BASEADDR (sec
) + sym
->st_value
;
223 name
= bfd_elf_string_from_elf_section
224 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
225 name
= name
== NULL
? bfd_section_name (sec
) : name
;
229 bool warned ATTRIBUTE_UNUSED
;
230 bool unresolved_reloc ATTRIBUTE_UNUSED
;
231 bool ignored ATTRIBUTE_UNUSED
;
233 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
234 r_symndx
, symtab_hdr
, sym_hashes
,
236 unresolved_reloc
, warned
, ignored
);
238 name
= h
->root
.root
.string
;
241 if (sec
!= NULL
&& discarded_section (sec
))
242 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
243 rel
, 1, relend
, howto
, 0, contents
);
245 if (bfd_link_relocatable (info
))
252 /* Make the relocation PC-relative, and change its unit to
253 64-bit words. Note we need *signed* arithmetic
255 relocation
= ((bfd_signed_vma
) relocation
256 - (sec_addr (input_section
) + rel
->r_offset
));
257 relocation
= (bfd_signed_vma
) relocation
/ 8;
259 /* Get the addend from the instruction and apply it. */
260 addend
= bfd_get (howto
->bitsize
, input_bfd
,
261 contents
+ rel
->r_offset
262 + (howto
->bitsize
== 16 ? 2 : 4));
264 if ((addend
& (((~howto
->src_mask
) >> 1) & howto
->src_mask
)) != 0)
265 addend
-= (((~howto
->src_mask
) >> 1) & howto
->src_mask
) << 1;
266 relocation
+= addend
;
268 /* Write out the relocated value. */
269 bfd_put (howto
->bitsize
, input_bfd
, relocation
,
270 contents
+ rel
->r_offset
271 + (howto
->bitsize
== 16 ? 2 : 4));
279 addend
= bfd_get (howto
->bitsize
, input_bfd
, where
);
280 relocation
+= addend
;
281 bfd_put (howto
->bitsize
, input_bfd
, relocation
, where
);
289 LDDW instructions are 128 bits long, with a 64-bit immediate.
290 The lower 32 bits of the immediate are in the same position
291 as the imm32 field of other instructions.
292 The upper 32 bits of the immediate are stored at the end of
297 /* Get the addend. The upper and lower 32 bits are split.
298 'where' is the beginning of the 16-byte instruction. */
299 addend
= bfd_get_32 (input_bfd
, where
+ 4);
300 addend
|= (bfd_get_32 (input_bfd
, where
+ 12) << 32);
302 relocation
+= addend
;
304 bfd_put_32 (input_bfd
, (relocation
& 0xFFFFFFFF), where
+ 4);
305 bfd_put_32 (input_bfd
, (relocation
>> 32), where
+ 12);
310 r
= bfd_reloc_notsupported
;
313 if (r
== bfd_reloc_ok
)
314 r
= bfd_check_overflow (howto
->complain_on_overflow
,
319 if (r
!= bfd_reloc_ok
)
321 const char * msg
= NULL
;
325 case bfd_reloc_overflow
:
326 (*info
->callbacks
->reloc_overflow
)
327 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
328 (bfd_vma
) 0, input_bfd
, input_section
, rel
->r_offset
);
331 case bfd_reloc_undefined
:
332 (*info
->callbacks
->undefined_symbol
)
333 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, true);
336 case bfd_reloc_outofrange
:
337 msg
= _("internal error: out of range error");
340 case bfd_reloc_notsupported
:
341 if (sym
!= NULL
) /* Only if it's not an unresolved symbol. */
342 msg
= _("internal error: relocation not supported");
345 case bfd_reloc_dangerous
:
346 msg
= _("internal error: dangerous relocation");
350 msg
= _("internal error: unknown error");
355 (*info
->callbacks
->warning
) (info
, msg
, name
, input_bfd
,
356 input_section
, rel
->r_offset
);
363 /* Merge backend specific data from an object file to the output
364 object file when linking. */
367 elf64_bpf_merge_private_bfd_data (bfd
*ibfd
, struct bfd_link_info
*info
)
369 /* Check if we have the same endianness. */
370 if (! _bfd_generic_verify_endian_match (ibfd
, info
))
376 /* A generic howto special function for installing BPF relocations.
377 This function will be called by the assembler (via bfd_install_relocation),
378 and by various get_relocated_section_contents functions.
379 At link time, bpf_elf_relocate_section will resolve the final relocations.
381 BPF instructions are always big endian, and this approach avoids problems in
382 bfd_install_relocation. */
384 static bfd_reloc_status_type
385 bpf_elf_generic_reloc (bfd
*abfd
, arelent
*reloc_entry
, asymbol
*symbol
,
386 void *data
, asection
*input_section
,
387 bfd
*output_bfd ATTRIBUTE_UNUSED
,
388 char **error_message ATTRIBUTE_UNUSED
)
391 bfd_signed_vma relocation
;
392 bfd_reloc_status_type status
;
395 /* Sanity check that the address is in range. */
396 bfd_size_type end
= bfd_get_section_limit_octets (abfd
, input_section
);
397 bfd_size_type reloc_size
;
398 if (reloc_entry
->howto
->type
== R_BPF_64_64
)
401 reloc_size
= (reloc_entry
->howto
->bitsize
402 + reloc_entry
->howto
->bitpos
) / 8;
404 if (reloc_entry
->address
> end
405 || end
- reloc_entry
->address
< reloc_size
)
406 return bfd_reloc_outofrange
;
408 /* Get the symbol value. */
409 if (bfd_is_com_section (symbol
->section
))
412 relocation
= symbol
->value
;
414 if (symbol
->flags
& BSF_SECTION_SYM
)
415 /* Relocation against a section symbol: add in the section base address. */
416 relocation
+= BASEADDR (symbol
->section
);
418 relocation
+= reloc_entry
->addend
;
420 where
= (bfd_byte
*) data
+ reloc_entry
->address
;
422 status
= bfd_check_overflow (reloc_entry
->howto
->complain_on_overflow
,
423 reloc_entry
->howto
->bitsize
,
424 reloc_entry
->howto
->rightshift
, 64, relocation
);
426 if (status
!= bfd_reloc_ok
)
429 /* Now finally install the relocation. */
430 if (reloc_entry
->howto
->type
== R_BPF_64_64
)
432 /* lddw is a 128-bit (!) instruction that allows loading a 64-bit
433 immediate into a register. the immediate is split in half, with the
434 lower 32 bits in the same position as the imm32 field of other
435 instructions, and the upper 32 bits placed at the very end of the
436 instruction. that is, there are 32 unused bits between them. */
438 bfd_put_32 (abfd
, (relocation
& 0xFFFFFFFF), where
+ 4);
439 bfd_put_32 (abfd
, (relocation
>> 32), where
+ 12);
443 /* For other kinds of relocations, the relocated value simply goes
444 BITPOS bits from the start of the entry. This is always a multiple
445 of 8, i.e. whole bytes. */
446 bfd_put (reloc_entry
->howto
->bitsize
, abfd
, relocation
,
447 where
+ reloc_entry
->howto
->bitpos
/ 8);
450 reloc_entry
->addend
= relocation
;
451 reloc_entry
->address
+= input_section
->output_offset
;
457 /* The macros below configure the architecture. */
459 #define TARGET_LITTLE_SYM bpf_elf64_le_vec
460 #define TARGET_LITTLE_NAME "elf64-bpfle"
462 #define TARGET_BIG_SYM bpf_elf64_be_vec
463 #define TARGET_BIG_NAME "elf64-bpfbe"
465 #define ELF_ARCH bfd_arch_bpf
466 #define ELF_MACHINE_CODE EM_BPF
468 #define ELF_MAXPAGESIZE 0x100000
470 #define elf_info_to_howto_rel bpf_info_to_howto
471 #define elf_info_to_howto bpf_info_to_howto
473 #define elf_backend_may_use_rel_p 1
474 #define elf_backend_may_use_rela_p 0
475 #define elf_backend_default_use_rela_p 0
476 #define elf_backend_relocate_section bpf_elf_relocate_section
478 #define elf_backend_can_gc_sections 0
480 #define elf_symbol_leading_char '_'
481 #define bfd_elf64_bfd_reloc_type_lookup bpf_reloc_type_lookup
482 #define bfd_elf64_bfd_reloc_name_lookup bpf_reloc_name_lookup
484 #define bfd_elf64_bfd_merge_private_bfd_data elf64_bpf_merge_private_bfd_data
486 #include "elf64-target.h"