| /* NFP-specific support for 64-bit ELF |
| Copyright (C) 2017-2024 Free Software Foundation, Inc. |
| Contributed by Francois H. Theron <francois.theron@netronome.com> |
| |
| This file is part of BFD, the Binary File Descriptor library. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin Street - Fifth Floor, |
| Boston, MA 02110-1301, USA. */ |
| |
| #include "sysdep.h" |
| #include "bfd.h" |
| #include "libbfd.h" |
| #include "elf-bfd.h" |
| #include "elf/nfp.h" |
| |
| |
| static bfd_reloc_status_type |
| elf64_nfp_reloc (bfd * abfd ATTRIBUTE_UNUSED, |
| arelent * reloc_entry, |
| asymbol * symbol, |
| void *data ATTRIBUTE_UNUSED, |
| asection * input_section, |
| bfd * output_bfd, |
| char **error_message ATTRIBUTE_UNUSED); |
| |
| /* We don't actually apply any relocations in this toolset |
| so we make them all do nothing, but at least display useful |
| names. |
| Most of these are mainly used by the NFP toolchain to resolve things |
| before the final ELF file is created. */ |
| #define NFP_HOWTO(type) \ |
| HOWTO (type, 0, 0, 0, false, 0, complain_overflow_dont, elf64_nfp_reloc, \ |
| #type, false, 0, 0, false) |
| static reloc_howto_type elf_nfp_howto_table[] = |
| { |
| NFP_HOWTO (R_NFP_NOTYPE), |
| NFP_HOWTO (R_NFP_W32LE), |
| NFP_HOWTO (R_NFP_SRC8_A), |
| NFP_HOWTO (R_NFP_SRC8_B), |
| NFP_HOWTO (R_NFP_IMMED8_I), |
| NFP_HOWTO (R_NFP_SC), |
| NFP_HOWTO (R_NFP_IMMED_LO16_I_A), |
| NFP_HOWTO (R_NFP_IMMED_LO16_I_B), |
| NFP_HOWTO (R_NFP_SRC7_B), |
| NFP_HOWTO (R_NFP_SRC7_A), |
| NFP_HOWTO (R_NFP_SRC8_I_B), |
| NFP_HOWTO (R_NFP_SRC8_I_A), |
| NFP_HOWTO (R_NFP_IMMED_HI16_I_A), |
| NFP_HOWTO (R_NFP_IMMED_HI16_I_B), |
| NFP_HOWTO (R_NFP_W64LE), |
| NFP_HOWTO (R_NFP_SH_INFO), |
| NFP_HOWTO (R_NFP_W32BE), |
| NFP_HOWTO (R_NFP_W64BE), |
| NFP_HOWTO (R_NFP_W32_29_24), |
| NFP_HOWTO (R_NFP_W32LE_AND), |
| NFP_HOWTO (R_NFP_W32BE_AND), |
| NFP_HOWTO (R_NFP_W32LE_OR), |
| NFP_HOWTO (R_NFP_W32BE_OR), |
| NFP_HOWTO (R_NFP_W64LE_AND), |
| NFP_HOWTO (R_NFP_W64BE_AND), |
| NFP_HOWTO (R_NFP_W64LE_OR), |
| NFP_HOWTO (R_NFP_W64BE_OR) |
| }; |
| |
| static bool |
| elf64_nfp_object_p (bfd * abfd) |
| { |
| /* If the e_machine value is one of the unofficial ones, we convert |
| it first and set e_flags accordingly for later consistency. */ |
| if (elf_elfheader (abfd)->e_machine == E_NFP_MACH_3200) |
| { |
| elf_elfheader (abfd)->e_machine = EM_NFP; |
| elf_elfheader (abfd)->e_flags &= ~EF_NFP_SET_MACH (~0); |
| elf_elfheader (abfd)->e_flags |= EF_NFP_SET_MACH (E_NFP_MACH_3200); |
| } |
| else if (elf_elfheader (abfd)->e_machine == E_NFP_MACH_6000) |
| { |
| elf_elfheader (abfd)->e_machine = EM_NFP; |
| elf_elfheader (abfd)->e_flags &= ~EF_NFP_SET_MACH (~0); |
| elf_elfheader (abfd)->e_flags |= EF_NFP_SET_MACH (E_NFP_MACH_6000); |
| } |
| |
| if (elf_elfheader (abfd)->e_machine == EM_NFP) |
| { |
| int e_mach = EF_NFP_MACH (elf_elfheader (abfd)->e_flags); |
| |
| switch (e_mach) |
| { |
| case E_NFP_MACH_3200: |
| case E_NFP_MACH_6000: |
| if (!bfd_default_set_arch_mach (abfd, bfd_arch_nfp, e_mach)) |
| return false; |
| default: |
| break; |
| } |
| } |
| |
| return true; |
| } |
| |
| static bool |
| elf64_nfp_section_from_shdr (bfd * abfd, |
| Elf_Internal_Shdr * hdr, |
| const char *name, int shindex) |
| { |
| switch (hdr->sh_type) |
| { |
| case SHT_NFP_INITREG: |
| case SHT_NFP_MECONFIG: |
| case SHT_NFP_UDEBUG: |
| return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex); |
| default: |
| return false; |
| } |
| } |
| |
| bfd_reloc_status_type |
| elf64_nfp_reloc (bfd * abfd ATTRIBUTE_UNUSED, |
| arelent * reloc_entry ATTRIBUTE_UNUSED, |
| asymbol * symbol ATTRIBUTE_UNUSED, |
| void *data ATTRIBUTE_UNUSED, |
| asection * input_section ATTRIBUTE_UNUSED, |
| bfd * output_bfd ATTRIBUTE_UNUSED, |
| char **error_message ATTRIBUTE_UNUSED) |
| { |
| return bfd_reloc_ok; |
| } |
| |
| static bool |
| elf64_nfp_info_to_howto (bfd * abfd ATTRIBUTE_UNUSED, |
| arelent * cache_ptr, Elf_Internal_Rela * dst) |
| { |
| unsigned int r_type; |
| |
| r_type = ELF64_R_TYPE (dst->r_info); |
| if (r_type >= R_NFP_MAX) |
| { |
| /* xgettext:c-format */ |
| _bfd_error_handler (_("%pB: unsupported relocation type %#x"), |
| abfd, r_type); |
| bfd_set_error (bfd_error_bad_value); |
| return false; |
| } |
| cache_ptr->howto = &elf_nfp_howto_table[r_type]; |
| return true; |
| } |
| |
| static reloc_howto_type * |
| elf64_nfp_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, |
| bfd_reloc_code_real_type code ATTRIBUTE_UNUSED) |
| { |
| return NULL; |
| } |
| |
| static reloc_howto_type * |
| elf64_nfp_reloc_name_lookup (bfd * abfd ATTRIBUTE_UNUSED, |
| const char *r_name ATTRIBUTE_UNUSED) |
| { |
| return NULL; |
| } |
| |
| #define ELF_ARCH bfd_arch_nfp |
| #define ELF_MACHINE_CODE EM_NFP |
| #define ELF_MACHINE_ALT1 E_NFP_MACH_6000 |
| #define ELF_MACHINE_ALT2 E_NFP_MACH_3200 |
| #define ELF_MAXPAGESIZE 1 |
| #define TARGET_LITTLE_NAME "elf64-nfp" |
| #define TARGET_LITTLE_SYM nfp_elf64_vec |
| |
| #define elf_backend_object_p elf64_nfp_object_p |
| #define elf_backend_section_from_shdr elf64_nfp_section_from_shdr |
| #define elf_info_to_howto elf64_nfp_info_to_howto |
| #define bfd_elf64_bfd_reloc_type_lookup elf64_nfp_reloc_type_lookup |
| #define bfd_elf64_bfd_reloc_name_lookup elf64_nfp_reloc_name_lookup |
| |
| #include "elf64-target.h" |