1 /* Linux bpf specific support for 64-bit ELF
2 Copyright (C) 2019-2024 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 case BFD_RELOC_BPF_DISPCALL32
:
92 return &bpf_elf_howto_table
[ (int) R_BPF_64_32_IDX
];
93 case BFD_RELOC_BPF_DISP16
:
94 return &bpf_elf_howto_table
[ (int) R_BPF_GNU_64_16_IDX
];
97 /* Pacify gcc -Wall. */
103 /* Map BFD reloc names to bpf ELF reloc names. */
105 static reloc_howto_type
*
106 bpf_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
110 for (i
= 0; i
< R_BPF_SIZE
; i
++)
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
];
118 /* Set the howto pointer for a bpf reloc. */
121 bpf_info_to_howto (bfd
*abfd
, arelent
*bfd_reloc
,
122 Elf_Internal_Rela
*elf_reloc
)
126 r_type
= ELF64_R_TYPE (elf_reloc
->r_info
);
128 i
= bpf_index_for_rtype(r_type
);
129 if (i
== (unsigned int) -1)
131 /* xgettext:c-format */
132 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
134 bfd_set_error (bfd_error_bad_value
);
138 bfd_reloc
->howto
= &bpf_elf_howto_table
[i
];
142 /* Relocate an eBPF ELF section.
144 The RELOCATE_SECTION function is called by the new ELF backend linker
145 to handle the relocations for a section.
147 The relocs are always passed as Rela structures; if the section
148 actually uses Rel structures, the r_addend field will always be
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.
155 This function does not have to worry about setting the reloc
156 address or the reloc symbol index.
158 LOCAL_SYMS is a pointer to the swapped in local symbols.
160 LOCAL_SECTIONS is an array giving the section in the input file
161 corresponding to the st_shndx field of each local symbol.
163 The global hash table entry for the global symbols can be found
164 via elf_sym_hashes (input_bfd).
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
172 #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
175 bpf_elf_relocate_section (bfd
*output_bfd ATTRIBUTE_UNUSED
,
176 struct bfd_link_info
*info
,
178 asection
*input_section
,
180 Elf_Internal_Rela
*relocs
,
181 Elf_Internal_Sym
*local_syms
,
182 asection
**local_sections
)
184 Elf_Internal_Shdr
*symtab_hdr
;
185 struct elf_link_hash_entry
**sym_hashes
;
186 Elf_Internal_Rela
*rel
;
187 Elf_Internal_Rela
*relend
;
189 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
190 sym_hashes
= elf_sym_hashes (input_bfd
);
191 relend
= relocs
+ input_section
->reloc_count
;
193 for (rel
= relocs
; rel
< relend
; rel
++)
195 reloc_howto_type
* howto
;
196 unsigned int howto_index
;
197 unsigned long r_symndx
;
198 Elf_Internal_Sym
* sym
;
200 struct elf_link_hash_entry
* h
;
202 bfd_reloc_status_type r
;
203 const char * name
= NULL
;
204 int r_type ATTRIBUTE_UNUSED
;
205 bfd_signed_vma addend
;
208 r_type
= ELF64_R_TYPE (rel
->r_info
);
209 r_symndx
= ELF64_R_SYM (rel
->r_info
);
211 howto_index
= bpf_index_for_rtype (ELF64_R_TYPE (rel
->r_info
));
212 howto
= &bpf_elf_howto_table
[howto_index
];
216 where
= contents
+ rel
->r_offset
;
218 if (r_symndx
< symtab_hdr
->sh_info
)
220 sym
= local_syms
+ r_symndx
;
221 sec
= local_sections
[r_symndx
];
222 relocation
= BASEADDR (sec
) + sym
->st_value
;
224 name
= bfd_elf_string_from_elf_section
225 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
226 name
= name
== NULL
? bfd_section_name (sec
) : name
;
230 bool warned ATTRIBUTE_UNUSED
;
231 bool unresolved_reloc ATTRIBUTE_UNUSED
;
232 bool ignored ATTRIBUTE_UNUSED
;
234 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
235 r_symndx
, symtab_hdr
, sym_hashes
,
237 unresolved_reloc
, warned
, ignored
);
239 name
= h
->root
.root
.string
;
242 if (sec
!= NULL
&& discarded_section (sec
))
243 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
244 rel
, 1, relend
, howto
, 0, contents
);
246 if (bfd_link_relocatable (info
))
253 /* Make the relocation PC-relative, and change its unit to
254 64-bit words. Note we need *signed* arithmetic
256 relocation
= ((bfd_signed_vma
) relocation
257 - (sec_addr (input_section
) + rel
->r_offset
));
258 relocation
= (bfd_signed_vma
) relocation
/ 8;
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));
265 if ((addend
& (((~howto
->src_mask
) >> 1) & howto
->src_mask
)) != 0)
266 addend
-= (((~howto
->src_mask
) >> 1) & howto
->src_mask
) << 1;
267 relocation
+= addend
;
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));
279 case R_BPF_64_NODYLD32
:
281 addend
= bfd_get (howto
->bitsize
, input_bfd
, where
);
282 relocation
+= addend
;
283 bfd_put (howto
->bitsize
, input_bfd
, relocation
, where
);
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
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);
304 relocation
+= addend
;
306 bfd_put_32 (input_bfd
, (relocation
& 0xFFFFFFFF), where
+ 4);
307 bfd_put_32 (input_bfd
, (relocation
>> 32), where
+ 12);
312 r
= bfd_reloc_notsupported
;
315 if (r
== bfd_reloc_ok
)
316 r
= bfd_check_overflow (howto
->complain_on_overflow
,
321 if (r
!= bfd_reloc_ok
)
323 const char * msg
= NULL
;
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
);
333 case bfd_reloc_undefined
:
334 (*info
->callbacks
->undefined_symbol
)
335 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, true);
338 case bfd_reloc_outofrange
:
339 msg
= _("internal error: out of range error");
342 case bfd_reloc_notsupported
:
343 if (sym
!= NULL
) /* Only if it's not an unresolved symbol. */
344 msg
= _("internal error: relocation not supported");
347 case bfd_reloc_dangerous
:
348 msg
= _("internal error: dangerous relocation");
352 msg
= _("internal error: unknown error");
357 (*info
->callbacks
->warning
) (info
, msg
, name
, input_bfd
,
358 input_section
, rel
->r_offset
);
365 /* Merge backend specific data from an object file to the output
366 object file when linking. */
369 elf64_bpf_merge_private_bfd_data (bfd
*ibfd
, struct bfd_link_info
*info
)
371 /* Check if we have the same endianness. */
372 if (! _bfd_generic_verify_endian_match (ibfd
, info
))
378 /* A generic howto special function for installing BPF relocations.
379 This function will be called by the assembler (via bfd_install_relocation),
380 and by various get_relocated_section_contents functions.
381 At link time, bpf_elf_relocate_section will resolve the final relocations.
383 BPF instructions are always big endian, and this approach avoids problems in
384 bfd_install_relocation. */
386 static bfd_reloc_status_type
387 bpf_elf_generic_reloc (bfd
*abfd
, arelent
*reloc_entry
, asymbol
*symbol
,
388 void *data
, asection
*input_section
,
389 bfd
*output_bfd ATTRIBUTE_UNUSED
,
390 char **error_message ATTRIBUTE_UNUSED
)
393 bfd_signed_vma relocation
;
394 bfd_reloc_status_type status
;
397 /* Sanity check that the address is in range. */
398 bfd_size_type end
= bfd_get_section_limit_octets (abfd
, input_section
);
399 bfd_size_type reloc_size
;
400 if (reloc_entry
->howto
->type
== R_BPF_64_64
)
403 reloc_size
= (reloc_entry
->howto
->bitsize
404 + reloc_entry
->howto
->bitpos
) / 8;
406 if (reloc_entry
->address
> end
407 || end
- reloc_entry
->address
< reloc_size
)
408 return bfd_reloc_outofrange
;
410 /* Get the symbol value. */
411 if (bfd_is_com_section (symbol
->section
))
414 relocation
= symbol
->value
;
416 if (symbol
->flags
& BSF_SECTION_SYM
)
417 /* Relocation against a section symbol: add in the section base address. */
418 relocation
+= BASEADDR (symbol
->section
);
420 relocation
+= reloc_entry
->addend
;
422 where
= (bfd_byte
*) data
+ reloc_entry
->address
;
424 status
= bfd_check_overflow (reloc_entry
->howto
->complain_on_overflow
,
425 reloc_entry
->howto
->bitsize
,
426 reloc_entry
->howto
->rightshift
, 64, relocation
);
428 if (status
!= bfd_reloc_ok
)
431 /* Now finally install the relocation. */
432 if (reloc_entry
->howto
->type
== R_BPF_64_64
)
434 /* lddw is a 128-bit (!) instruction that allows loading a 64-bit
435 immediate into a register. the immediate is split in half, with the
436 lower 32 bits in the same position as the imm32 field of other
437 instructions, and the upper 32 bits placed at the very end of the
438 instruction. that is, there are 32 unused bits between them. */
440 bfd_put_32 (abfd
, (relocation
& 0xFFFFFFFF), where
+ 4);
441 bfd_put_32 (abfd
, (relocation
>> 32), where
+ 12);
445 /* For other kinds of relocations, the relocated value simply goes
446 BITPOS bits from the start of the entry. This is always a multiple
447 of 8, i.e. whole bytes. */
448 bfd_put (reloc_entry
->howto
->bitsize
, abfd
, relocation
,
449 where
+ reloc_entry
->howto
->bitpos
/ 8);
452 reloc_entry
->addend
= relocation
;
453 reloc_entry
->address
+= input_section
->output_offset
;
459 /* The macros below configure the architecture. */
461 #define TARGET_LITTLE_SYM bpf_elf64_le_vec
462 #define TARGET_LITTLE_NAME "elf64-bpfle"
464 #define TARGET_BIG_SYM bpf_elf64_be_vec
465 #define TARGET_BIG_NAME "elf64-bpfbe"
467 #define ELF_ARCH bfd_arch_bpf
468 #define ELF_MACHINE_CODE EM_BPF
470 #define ELF_MAXPAGESIZE 0x100000
472 #define elf_info_to_howto_rel bpf_info_to_howto
473 #define elf_info_to_howto bpf_info_to_howto
475 #define elf_backend_may_use_rel_p 1
476 #define elf_backend_may_use_rela_p 0
477 #define elf_backend_default_use_rela_p 0
478 #define elf_backend_relocate_section bpf_elf_relocate_section
480 #define elf_backend_can_gc_sections 0
482 #define elf_symbol_leading_char '_'
483 #define bfd_elf64_bfd_reloc_type_lookup bpf_reloc_type_lookup
484 #define bfd_elf64_bfd_reloc_name_lookup bpf_reloc_name_lookup
486 #define bfd_elf64_bfd_merge_private_bfd_data elf64_bpf_merge_private_bfd_data
488 #include "elf64-target.h"