1/* BFD back-end for AArch64 COFF files. 2 Copyright (C) 2021-2022 Free Software Foundation, Inc. 3 4 This file is part of BFD, the Binary File Descriptor library. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 22#ifndef COFF_WITH_peAArch64 23#define COFF_WITH_peAArch64 24#endif 25 26/* Note we have to make sure not to include headers twice. 27 Not all headers are wrapped in #ifdef guards, so we define 28 PEI_HEADERS to prevent double including here. */ 29#ifndef PEI_HEADERS 30#include "sysdep.h" 31#include "bfd.h" 32#include "libbfd.h" 33#include "coff/aarch64.h" 34#include "coff/internal.h" 35#include "coff/pe.h" 36#include "libcoff.h" 37#include "libiberty.h" 38#endif 39 40#include "libcoff.h" 41 42/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ 43#define MINUS_ONE (~ (bfd_vma) 0) 44 45static const reloc_howto_type arm64_reloc_howto_64 = HOWTO(IMAGE_REL_ARM64_ADDR64, 0, 8, 64, false, 0, 46 complain_overflow_bitfield, 47 NULL, "64", 48 false, MINUS_ONE, MINUS_ONE, false); 49 50static const reloc_howto_type arm64_reloc_howto_32 = HOWTO (IMAGE_REL_ARM64_ADDR32, 0, 4, 32, false, 0, 51 complain_overflow_bitfield, 52 NULL, "32", 53 false, 0xffffffff, 0xffffffff, false); 54 55static const reloc_howto_type arm64_reloc_howto_32_pcrel = HOWTO (IMAGE_REL_ARM64_REL32, 0, 4, 32, true, 0, 56 complain_overflow_bitfield, 57 NULL, "DISP32", 58 false, 0xffffffff, 0xffffffff, true); 59 60static const reloc_howto_type arm64_reloc_howto_branch26 = HOWTO (IMAGE_REL_ARM64_BRANCH26, 0, 4, 26, true, 0, 61 complain_overflow_bitfield, 62 NULL, "BRANCH26", 63 false, 0x03ffffff, 0x03ffffff, true); 64 65static const reloc_howto_type arm64_reloc_howto_page21 = HOWTO (IMAGE_REL_ARM64_PAGEBASE_REL21, 12, 4, 21, true, 0, 66 complain_overflow_signed, 67 NULL, "PAGE21", 68 false, 0x1fffff, 0x1fffff, false); 69 70static const reloc_howto_type arm64_reloc_howto_lo21 = HOWTO (IMAGE_REL_ARM64_REL21, 0, 4, 21, true, 0, 71 complain_overflow_signed, 72 NULL, "LO21", 73 false, 0x1fffff, 0x1fffff, true); 74 75static const reloc_howto_type arm64_reloc_howto_pgoff12 = HOWTO (IMAGE_REL_ARM64_PAGEOFFSET_12L, 1, 4, 12, true, 0, 76 complain_overflow_signed, 77 NULL, "PGOFF12", 78 false, 0xffe, 0xffe, true); 79 80static const reloc_howto_type arm64_reloc_howto_branch19 = HOWTO (IMAGE_REL_ARM64_BRANCH19, 2, 4, 19, true, 0, 81 complain_overflow_signed, 82 NULL, "BRANCH19", 83 false, 0x7ffff, 0x7ffff, true); 84 85 86static const reloc_howto_type* const arm64_howto_table[] = { 87 &arm64_reloc_howto_64, 88 &arm64_reloc_howto_32, 89 &arm64_reloc_howto_32_pcrel, 90 &arm64_reloc_howto_branch26, 91 &arm64_reloc_howto_page21, 92 &arm64_reloc_howto_lo21, 93 &arm64_reloc_howto_pgoff12, 94 &arm64_reloc_howto_branch19 95}; 96 97#ifndef NUM_ELEM 98#define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0])) 99#endif 100 101#define NUM_RELOCS NUM_ELEM (arm64_howto_table) 102 103#define coff_bfd_reloc_type_lookup coff_aarch64_reloc_type_lookup 104#define coff_bfd_reloc_name_lookup coff_aarch64_reloc_name_lookup 105 106static reloc_howto_type * 107coff_aarch64_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) 108{ 109 switch (code) 110 { 111 case BFD_RELOC_64: 112 return &arm64_reloc_howto_64; 113 case BFD_RELOC_32: 114 return &arm64_reloc_howto_32; 115 case BFD_RELOC_32_PCREL: 116 return &arm64_reloc_howto_32_pcrel; 117 case BFD_RELOC_AARCH64_CALL26: 118 case BFD_RELOC_AARCH64_JUMP26: 119 return &arm64_reloc_howto_branch26; 120 case BFD_RELOC_AARCH64_ADR_HI21_PCREL: 121 return &arm64_reloc_howto_page21; 122 case BFD_RELOC_AARCH64_ADR_LO21_PCREL: 123 return &arm64_reloc_howto_lo21; 124 case BFD_RELOC_AARCH64_LDST16_LO12: 125 return &arm64_reloc_howto_pgoff12; 126 case BFD_RELOC_AARCH64_BRANCH19: 127 return &arm64_reloc_howto_branch19; 128 default: 129 BFD_FAIL (); 130 return NULL; 131 } 132 133 return NULL; 134} 135 136static reloc_howto_type * 137coff_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 138 const char *r_name) 139{ 140 unsigned int i; 141 142 for (i = 0; i < NUM_RELOCS; i++) 143 if (arm64_howto_table[i]->name != NULL 144 && strcasecmp (arm64_howto_table[i]->name, r_name) == 0) 145 return arm64_howto_table[i]; 146 147 return NULL; 148} 149 150#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2 151#define COFF_PAGE_SIZE 0x1000 152 153static reloc_howto_type * 154coff_aarch64_rtype_lookup (unsigned int code) 155{ 156 switch (code) 157 { 158 case IMAGE_REL_ARM64_ADDR64: 159 return &arm64_reloc_howto_64; 160 case IMAGE_REL_ARM64_ADDR32: 161 return &arm64_reloc_howto_32; 162 case IMAGE_REL_ARM64_REL32: 163 return &arm64_reloc_howto_32_pcrel; 164 case IMAGE_REL_ARM64_BRANCH26: 165 return &arm64_reloc_howto_branch26; 166 case IMAGE_REL_ARM64_PAGEBASE_REL21: 167 return &arm64_reloc_howto_page21; 168 case IMAGE_REL_ARM64_REL21: 169 return &arm64_reloc_howto_lo21; 170 case IMAGE_REL_ARM64_PAGEOFFSET_12L: 171 return &arm64_reloc_howto_pgoff12; 172 case IMAGE_REL_ARM64_BRANCH19: 173 return &arm64_reloc_howto_branch19; 174 default: 175 BFD_FAIL (); 176 return NULL; 177 } 178 179 return NULL; 180} 181 182#define RTYPE2HOWTO(cache_ptr, dst) \ 183 ((cache_ptr)->howto = coff_aarch64_rtype_lookup((dst)->r_type)) 184 185#define SELECT_RELOC(x,howto) { (x).r_type = (howto)->type; } 186 187#ifndef bfd_pe_print_pdata 188#define bfd_pe_print_pdata NULL 189#endif 190 191/* Handle include/coff/aarch64.h external_reloc. */ 192#define SWAP_IN_RELOC_OFFSET H_GET_32 193#define SWAP_OUT_RELOC_OFFSET H_PUT_32 194 195/* Return TRUE if this relocation should 196 appear in the output .reloc section. */ 197 198static bool 199in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED, 200 reloc_howto_type * howto) 201{ 202 return !howto->pc_relative; 203} 204 205#include "coffcode.h" 206 207/* Target vectors. */ 208const bfd_target 209#ifdef TARGET_SYM 210 TARGET_SYM = 211#else 212# error "target symbol name not specified" 213#endif 214{ 215#ifdef TARGET_NAME 216 TARGET_NAME, 217#else 218# error "target name not specified" 219#endif 220 bfd_target_coff_flavour, 221 BFD_ENDIAN_LITTLE, /* Data byte order is little. */ 222 BFD_ENDIAN_LITTLE, /* Header byte order is little. */ 223 224 (HAS_RELOC | EXEC_P /* Object flags. */ 225 | HAS_LINENO | HAS_DEBUG 226 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS), 227 228 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags. */ 229#if defined(COFF_WITH_PE) 230 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING 231#endif 232 | SEC_CODE | SEC_DATA | SEC_EXCLUDE ), 233 234#ifdef TARGET_UNDERSCORE 235 TARGET_UNDERSCORE, /* Leading underscore. */ 236#else 237 0, /* Leading underscore. */ 238#endif 239 '/', /* Ar_pad_char. */ 240 15, /* Ar_max_namelen. */ 241 0, /* match priority. */ 242 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ 243 244 /* Data conversion functions. */ 245 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 246 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 247 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ 248 /* Header conversion functions. */ 249 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 250 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 251 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */ 252 253 /* Note that we allow an object file to be treated as a core file as well. */ 254 { /* bfd_check_format. */ 255 _bfd_dummy_target, 256 coff_object_p, 257 bfd_generic_archive_p, 258 coff_object_p 259 }, 260 { /* bfd_set_format. */ 261 _bfd_bool_bfd_false_error, 262 coff_mkobject, 263 _bfd_generic_mkarchive, 264 _bfd_bool_bfd_false_error 265 }, 266 { /* bfd_write_contents. */ 267 _bfd_bool_bfd_false_error, 268 coff_write_object_contents, 269 _bfd_write_archive_contents, 270 _bfd_bool_bfd_false_error 271 }, 272 273 BFD_JUMP_TABLE_GENERIC (coff), 274 BFD_JUMP_TABLE_COPY (coff), 275 BFD_JUMP_TABLE_CORE (_bfd_nocore), 276 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), 277 BFD_JUMP_TABLE_SYMBOLS (coff), 278 BFD_JUMP_TABLE_RELOCS (coff), 279 BFD_JUMP_TABLE_WRITE (coff), 280 BFD_JUMP_TABLE_LINK (coff), 281 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 282 283 NULL, 284 285 COFF_SWAP_TABLE 286}; 287