ld: Always call elf_backend_output_arch_local_syms
[binutils-gdb.git] / bfd / coff-aarch64.c
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
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 /* 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
198 static bool
199 in_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. */
208 const 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 };