Fix size of external_reloc for pe-aarch64
[binutils-gdb.git] / bfd / coff-aarch64.c
1 /* BFD back-end for AArch64 COFF files.
2 Copyright (C) 2021-2023 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
45 static 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
50 static 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
55 static 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
60 static 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
65 static 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
70 static 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
75 static 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
80 static 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
86 static 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
106 static reloc_howto_type *
107 coff_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
136 static reloc_howto_type *
137 coff_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
153 static reloc_howto_type *
154 coff_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 /* Return TRUE if this relocation should
192 appear in the output .reloc section. */
193
194 static bool
195 in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
196 reloc_howto_type * howto)
197 {
198 return !howto->pc_relative;
199 }
200
201 #include "coffcode.h"
202
203 /* Target vectors. */
204 const bfd_target
205 #ifdef TARGET_SYM
206 TARGET_SYM =
207 #else
208 # error "target symbol name not specified"
209 #endif
210 {
211 #ifdef TARGET_NAME
212 TARGET_NAME,
213 #else
214 # error "target name not specified"
215 #endif
216 bfd_target_coff_flavour,
217 BFD_ENDIAN_LITTLE, /* Data byte order is little. */
218 BFD_ENDIAN_LITTLE, /* Header byte order is little. */
219
220 (HAS_RELOC | EXEC_P /* Object flags. */
221 | HAS_LINENO | HAS_DEBUG
222 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
223
224 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags. */
225 #if defined(COFF_WITH_PE)
226 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
227 #endif
228 | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
229
230 #ifdef TARGET_UNDERSCORE
231 TARGET_UNDERSCORE, /* Leading underscore. */
232 #else
233 0, /* Leading underscore. */
234 #endif
235 '/', /* Ar_pad_char. */
236 15, /* Ar_max_namelen. */
237 0, /* match priority. */
238 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
239
240 /* Data conversion functions. */
241 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
242 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
243 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */
244 /* Header 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, /* Hdrs. */
248
249 /* Note that we allow an object file to be treated as a core file as well. */
250 { /* bfd_check_format. */
251 _bfd_dummy_target,
252 coff_object_p,
253 bfd_generic_archive_p,
254 coff_object_p
255 },
256 { /* bfd_set_format. */
257 _bfd_bool_bfd_false_error,
258 coff_mkobject,
259 _bfd_generic_mkarchive,
260 _bfd_bool_bfd_false_error
261 },
262 { /* bfd_write_contents. */
263 _bfd_bool_bfd_false_error,
264 coff_write_object_contents,
265 _bfd_write_archive_contents,
266 _bfd_bool_bfd_false_error
267 },
268
269 BFD_JUMP_TABLE_GENERIC (coff),
270 BFD_JUMP_TABLE_COPY (coff),
271 BFD_JUMP_TABLE_CORE (_bfd_nocore),
272 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
273 BFD_JUMP_TABLE_SYMBOLS (coff),
274 BFD_JUMP_TABLE_RELOCS (coff),
275 BFD_JUMP_TABLE_WRITE (coff),
276 BFD_JUMP_TABLE_LINK (coff),
277 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
278
279 NULL,
280
281 COFF_SWAP_TABLE
282 };